1#ifndef AMREX_PARTICLEREDUCE_H_
2#define AMREX_PARTICLEREDUCE_H_
3#include <AMReX_Config.H>
21namespace particle_detail {
23template <
typename F,
typename T_ParticleType,
int NAR,
int NAI>
25auto call_f (F
const& f,
26 const ConstParticleTileData<T_ParticleType, NAR, NAI>& p,
29 if constexpr ( ! T_ParticleType::is_soa_particle &&
30 IsCallable<F, T_ParticleType const&>::value) {
32 }
else if constexpr (IsCallable<
F,
decltype(p.getSuperParticle(i))>::value) {
33 return f(p.getSuperParticle(i));
39template <
typename F,
template<
class,
class>
class PTDType,
class RType,
class IType>
41auto call_f (F
const& f,
42 const PTDType<RType, IType>& p,
90template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
93 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
95 return ReduceSum(pc, 0, pc.finestLevel(), std::forward<F>(f));
138template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
141 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
143 return ReduceSum(pc, lev, lev, std::forward<F>(f));
187template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
189ReduceSum (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
190 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
192 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
200 using ReduceTuple =
typename decltype(reduce_data)::Type;
202 for (
int lev = lev_min; lev <= lev_max; ++lev)
204 const auto& plev = pc.GetParticles(lev);
205 for (
const auto& kv : plev)
207 const auto& tile = plev.at(kv.first);
208 const auto np = tile.numParticles();
209 const auto& ptd = tile.getConstParticleTileData();
210 reduce_op.
eval(np, reduce_data,
212 return particle_detail::call_f(f, ptd, i);
217 ReduceTuple hv = reduce_data.
value(reduce_op);
218 sm = amrex::get<0>(hv);
223 for (
int lev = lev_min; lev <= lev_max; ++lev)
225 const auto& plev = pc.GetParticles(lev);
228 for (
auto& kv : plev)
230 grid_tile_ids.push_back(kv.first);
231 ptile_ptrs.push_back(&(kv.second));
236#pragma omp parallel for if (!system::regtest_reduction) reduction(+:sm)
238 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
240 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
241 const auto np = tile.numParticles();
242 const auto& ptd = tile.getConstParticleTileData();
243 for (
int i = 0; i < np; ++i) {
244 sm += particle_detail::call_f(f, ptd, i);
292template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
295 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
297 return ReduceMax(pc, 0, pc.finestLevel(), std::forward<F>(f));
341template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
344 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
346 return ReduceMax(pc, lev, lev, std::forward<F>(f));
390template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
392ReduceMax (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
393 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
395 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
396 constexpr value_type value_lowest = std::numeric_limits<value_type>::lowest();
397 value_type r = value_lowest;
404 using ReduceTuple =
typename decltype(reduce_data)::Type;
406 for (
int lev = lev_min; lev <= lev_max; ++lev)
408 const auto& plev = pc.GetParticles(lev);
409 for (
const auto& kv : plev)
411 const auto& tile = plev.at(kv.first);
412 const auto np = tile.numParticles();
413 const auto& ptd = tile.getConstParticleTileData();
414 reduce_op.
eval(np, reduce_data,
416 return particle_detail::call_f(f, ptd, i);
421 ReduceTuple hv = reduce_data.
value(reduce_op);
422 r = amrex::get<0>(hv);
427 for (
int lev = lev_min; lev <= lev_max; ++lev)
429 const auto& plev = pc.GetParticles(lev);
432 for (
auto& kv : plev)
434 grid_tile_ids.push_back(kv.first);
435 ptile_ptrs.push_back(&(kv.second));
440#pragma omp parallel for if (!system::regtest_reduction) reduction(max:r)
442 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
444 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
445 const auto np = tile.numParticles();
446 const auto& ptd = tile.getConstParticleTileData();
447 for (
int i = 0; i < np; ++i) {
448 r = std::max(r, particle_detail::call_f(f, ptd, i));
496template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
499 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
501 return ReduceMin(pc, 0, pc.finestLevel(), std::forward<F>(f));
544template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
547 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
549 return ReduceMin(pc, lev, lev, std::forward<F>(f));
593template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
595ReduceMin (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
596 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
598 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
599 constexpr value_type value_max = std::numeric_limits<value_type>::max();
600 value_type r = value_max;
607 using ReduceTuple =
typename decltype(reduce_data)::Type;
609 for (
int lev = lev_min; lev <= lev_max; ++lev)
611 const auto& plev = pc.GetParticles(lev);
612 for (
const auto& kv : plev)
614 const auto& tile = plev.at(kv.first);
615 const auto np = tile.numParticles();
616 const auto& ptd = tile.getConstParticleTileData();
617 reduce_op.
eval(np, reduce_data,
619 return particle_detail::call_f(f, ptd, i);
624 ReduceTuple hv = reduce_data.
value(reduce_op);
625 r = amrex::get<0>(hv);
630 for (
int lev = lev_min; lev <= lev_max; ++lev)
632 const auto& plev = pc.GetParticles(lev);
635 for (
auto& kv : plev)
637 grid_tile_ids.push_back(kv.first);
638 ptile_ptrs.push_back(&(kv.second));
643#pragma omp parallel for if (!system::regtest_reduction) reduction(min:r)
645 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
647 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
648 const auto np = tile.numParticles();
649 const auto& ptd = tile.getConstParticleTileData();
650 for (
int i = 0; i < np; ++i) {
651 r = std::min(r, particle_detail::call_f(f, ptd, i));
699template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
746template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
794template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
805 using ReduceTuple =
typename decltype(reduce_data)::Type;
807 for (
int lev = lev_min; lev <= lev_max; ++lev)
809 const auto& plev = pc.GetParticles(lev);
810 for (
const auto& kv : plev)
812 const auto& tile = plev.at(kv.first);
813 const auto np = tile.numParticles();
814 const auto& ptd = tile.getConstParticleTileData();
815 reduce_op.
eval(np, reduce_data,
817 return particle_detail::call_f(f, ptd, i);
822 ReduceTuple hv = reduce_data.
value(reduce_op);
823 r = amrex::get<0>(hv);
828 for (
int lev = lev_min; lev <= lev_max; ++lev)
830 const auto& plev = pc.GetParticles(lev);
833 for (
auto& kv : plev)
835 grid_tile_ids.push_back(kv.first);
836 ptile_ptrs.push_back(&(kv.second));
841#pragma omp parallel for if (!system::regtest_reduction) reduction(&&:r)
843 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
845 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
846 const auto np = tile.numParticles();
847 const auto& ptd = tile.getConstParticleTileData();
848 for (
int i = 0; i < np; ++i) {
849 r = r && particle_detail::call_f(f, ptd, i);
897template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
944template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
992template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1003 using ReduceTuple =
typename decltype(reduce_data)::Type;
1005 for (
int lev = lev_min; lev <= lev_max; ++lev)
1007 const auto& plev = pc.GetParticles(lev);
1008 for (
const auto& kv : plev)
1010 const auto& tile = plev.at(kv.first);
1011 const auto np = tile.numParticles();
1012 const auto& ptd = tile.getConstParticleTileData();
1013 reduce_op.
eval(np, reduce_data,
1016 return particle_detail::call_f(f, ptd, i);
1021 ReduceTuple hv = reduce_data.
value(reduce_op);
1022 r = amrex::get<0>(hv);
1027 for (
int lev = lev_min; lev <= lev_max; ++lev)
1029 const auto& plev = pc.GetParticles(lev);
1032 for (
auto& kv : plev)
1034 grid_tile_ids.push_back(kv.first);
1035 ptile_ptrs.push_back(&(kv.second));
1040#pragma omp parallel for if (!system::regtest_reduction) reduction(||:r)
1042 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
1044 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
1045 const auto np = tile.numParticles();
1046 const auto& ptd = tile.getConstParticleTileData();
1047 for (
int i = 0; i < np; ++i) {
1048 r = r || particle_detail::call_f(f, ptd, i);
1119template <
class RD,
class PC,
class F,
class ReduceOps,
1120 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1124 return ParticleReduce<RD>(pc, 0, pc.finestLevel(), std::forward<F>(f), reduce_ops);
1190template <
class RD,
class PC,
class F,
class ReduceOps,
1191 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1195 return ParticleReduce<RD>(pc, lev, lev, std::forward<F>(f), reduce_ops);
1262template <
class RD,
class PC,
class F,
class ReduceOps,
1263 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1267 RD reduce_data(reduce_ops);
1268 for (
int lev = lev_min; lev <= lev_max; ++lev) {
1269 const auto& plev = pc.GetParticles(lev);
1272 for (
auto& kv : plev)
1274 grid_tile_ids.push_back(kv.first);
1275 ptile_ptrs.push_back(&(kv.second));
1279#if !defined(AMREX_USE_GPU) && defined(AMREX_USE_OMP)
1280#pragma omp parallel for
1282 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
1284 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
1285 const auto np = tile.numParticles();
1286 const auto& ptd = tile.getConstParticleTileData();
1287 reduce_ops.
eval(np, reduce_data,
1290 return particle_detail::call_f(f, ptd, i);
1294 return reduce_data.value(reduce_ops);
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
Definition AMReX_Reduce.H:453
Type value()
Definition AMReX_Reduce.H:488
Definition AMReX_Reduce.H:612
std::enable_if_t< IsFabArray< MF >::value > eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:748
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:28
bool inLaunchRegion() noexcept
Definition AMReX_GpuControl.H:88
Definition AMReX_Amr.cpp:50
FAB::value_type ReduceMax(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:555
bool ReduceLogicalAnd(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:794
bool ReduceLogicalOr(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:949
RD::Type ParticleReduce(PC const &pc, F &&f, ReduceOps &reduce_ops)
A general reduction method for the particles in a ParticleContainer that can run on either CPUs or GP...
Definition AMReX_ParticleReduce.H:1122
FAB::value_type ReduceMin(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:317
FAB::value_type ReduceSum(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:16