1#ifndef AMREX_PARTICLEREDUCE_H_
2#define AMREX_PARTICLEREDUCE_H_
3#include <AMReX_Config.H>
20namespace particle_detail {
22template <
typename F,
typename T_ParticleType,
int NAR,
int NAI>
24auto call_f (F
const& f,
25 const ConstParticleTileData<T_ParticleType, NAR, NAI>& p,
28 if constexpr ( ! T_ParticleType::is_soa_particle &&
29 IsCallable<F, T_ParticleType const&>::value) {
31 }
else if constexpr (IsCallable<
F,
decltype(p.getSuperParticle(i))>::value) {
32 return f(p.getSuperParticle(i));
80template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
83 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
85 return ReduceSum(pc, 0, pc.finestLevel(), std::forward<F>(f));
128template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
131 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
133 return ReduceSum(pc, lev, lev, std::forward<F>(f));
177template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
179ReduceSum (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
180 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
182 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
190 using ReduceTuple =
typename decltype(reduce_data)::Type;
192 for (
int lev = lev_min; lev <= lev_max; ++lev)
194 const auto& plev = pc.GetParticles(lev);
195 for (
const auto& kv : plev)
197 const auto& tile = plev.at(kv.first);
198 const auto np = tile.numParticles();
199 const auto& ptd = tile.getConstParticleTileData();
200 reduce_op.
eval(np, reduce_data,
202 return particle_detail::call_f(f, ptd, i);
207 ReduceTuple hv = reduce_data.
value(reduce_op);
208 sm = amrex::get<0>(hv);
213 for (
int lev = lev_min; lev <= lev_max; ++lev)
215 const auto& plev = pc.GetParticles(lev);
218 for (
auto& kv : plev)
220 grid_tile_ids.push_back(kv.first);
221 ptile_ptrs.push_back(&(kv.second));
226#pragma omp parallel for if (!system::regtest_reduction) reduction(+:sm)
228 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
230 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
231 const auto np = tile.numParticles();
232 const auto& ptd = tile.getConstParticleTileData();
233 for (
int i = 0; i < np; ++i) {
234 sm += particle_detail::call_f(f, ptd, i);
282template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
285 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
287 return ReduceMax(pc, 0, pc.finestLevel(), std::forward<F>(f));
331template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
334 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
336 return ReduceMax(pc, lev, lev, std::forward<F>(f));
380template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
382ReduceMax (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
383 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
385 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
386 constexpr value_type value_lowest = std::numeric_limits<value_type>::lowest();
387 value_type r = value_lowest;
394 using ReduceTuple =
typename decltype(reduce_data)::Type;
396 for (
int lev = lev_min; lev <= lev_max; ++lev)
398 const auto& plev = pc.GetParticles(lev);
399 for (
const auto& kv : plev)
401 const auto& tile = plev.at(kv.first);
402 const auto np = tile.numParticles();
403 const auto& ptd = tile.getConstParticleTileData();
404 reduce_op.
eval(np, reduce_data,
406 return particle_detail::call_f(f, ptd, i);
411 ReduceTuple hv = reduce_data.
value(reduce_op);
412 r = amrex::get<0>(hv);
417 for (
int lev = lev_min; lev <= lev_max; ++lev)
419 const auto& plev = pc.GetParticles(lev);
422 for (
auto& kv : plev)
424 grid_tile_ids.push_back(kv.first);
425 ptile_ptrs.push_back(&(kv.second));
430#pragma omp parallel for if (!system::regtest_reduction) reduction(max:r)
432 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
434 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
435 const auto np = tile.numParticles();
436 const auto& ptd = tile.getConstParticleTileData();
437 for (
int i = 0; i < np; ++i) {
438 r = std::max(r, particle_detail::call_f(f, ptd, i));
486template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
489 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
491 return ReduceMin(pc, 0, pc.finestLevel(), std::forward<F>(f));
534template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
537 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
539 return ReduceMin(pc, lev, lev, std::forward<F>(f));
583template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
585ReduceMin (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
586 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
588 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
589 constexpr value_type value_max = std::numeric_limits<value_type>::max();
590 value_type r = value_max;
597 using ReduceTuple =
typename decltype(reduce_data)::Type;
599 for (
int lev = lev_min; lev <= lev_max; ++lev)
601 const auto& plev = pc.GetParticles(lev);
602 for (
const auto& kv : plev)
604 const auto& tile = plev.at(kv.first);
605 const auto np = tile.numParticles();
606 const auto& ptd = tile.getConstParticleTileData();
607 reduce_op.
eval(np, reduce_data,
609 return particle_detail::call_f(f, ptd, i);
614 ReduceTuple hv = reduce_data.
value(reduce_op);
615 r = amrex::get<0>(hv);
620 for (
int lev = lev_min; lev <= lev_max; ++lev)
622 const auto& plev = pc.GetParticles(lev);
625 for (
auto& kv : plev)
627 grid_tile_ids.push_back(kv.first);
628 ptile_ptrs.push_back(&(kv.second));
633#pragma omp parallel for if (!system::regtest_reduction) reduction(min:r)
635 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
637 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
638 const auto np = tile.numParticles();
639 const auto& ptd = tile.getConstParticleTileData();
640 for (
int i = 0; i < np; ++i) {
641 r = std::min(r, particle_detail::call_f(f, ptd, i));
689template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
736template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
784template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
795 using ReduceTuple =
typename decltype(reduce_data)::Type;
797 for (
int lev = lev_min; lev <= lev_max; ++lev)
799 const auto& plev = pc.GetParticles(lev);
800 for (
const auto& kv : plev)
802 const auto& tile = plev.at(kv.first);
803 const auto np = tile.numParticles();
804 const auto& ptd = tile.getConstParticleTileData();
805 reduce_op.
eval(np, reduce_data,
807 return particle_detail::call_f(f, ptd, i);
812 ReduceTuple hv = reduce_data.
value(reduce_op);
813 r = amrex::get<0>(hv);
818 for (
int lev = lev_min; lev <= lev_max; ++lev)
820 const auto& plev = pc.GetParticles(lev);
823 for (
auto& kv : plev)
825 grid_tile_ids.push_back(kv.first);
826 ptile_ptrs.push_back(&(kv.second));
831#pragma omp parallel for if (!system::regtest_reduction) reduction(&&:r)
833 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
835 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
836 const auto np = tile.numParticles();
837 const auto& ptd = tile.getConstParticleTileData();
838 for (
int i = 0; i < np; ++i) {
839 r = r && particle_detail::call_f(f, ptd, i);
887template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
934template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
982template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
993 using ReduceTuple =
typename decltype(reduce_data)::Type;
995 for (
int lev = lev_min; lev <= lev_max; ++lev)
997 const auto& plev = pc.GetParticles(lev);
998 for (
const auto& kv : plev)
1000 const auto& tile = plev.at(kv.first);
1001 const auto np = tile.numParticles();
1002 const auto& ptd = tile.getConstParticleTileData();
1003 reduce_op.
eval(np, reduce_data,
1006 return particle_detail::call_f(f, ptd, i);
1011 ReduceTuple hv = reduce_data.
value(reduce_op);
1012 r = amrex::get<0>(hv);
1017 for (
int lev = lev_min; lev <= lev_max; ++lev)
1019 const auto& plev = pc.GetParticles(lev);
1022 for (
auto& kv : plev)
1024 grid_tile_ids.push_back(kv.first);
1025 ptile_ptrs.push_back(&(kv.second));
1030#pragma omp parallel for if (!system::regtest_reduction) reduction(||:r)
1032 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
1034 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
1035 const auto np = tile.numParticles();
1036 const auto& ptd = tile.getConstParticleTileData();
1037 for (
int i = 0; i < np; ++i) {
1038 r = r || particle_detail::call_f(f, ptd, i);
1109template <
class RD,
class PC,
class F,
class ReduceOps,
1110 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1114 return ParticleReduce<RD>(pc, 0, pc.finestLevel(), std::forward<F>(f), reduce_ops);
1180template <
class RD,
class PC,
class F,
class ReduceOps,
1181 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1185 return ParticleReduce<RD>(pc, lev, lev, std::forward<F>(f), reduce_ops);
1252template <
class RD,
class PC,
class F,
class ReduceOps,
1253 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1257 RD reduce_data(reduce_ops);
1258 for (
int lev = lev_min; lev <= lev_max; ++lev) {
1259 const auto& plev = pc.GetParticles(lev);
1262 for (
auto& kv : plev)
1264 grid_tile_ids.push_back(kv.first);
1265 ptile_ptrs.push_back(&(kv.second));
1269#if !defined(AMREX_USE_GPU) && defined(AMREX_USE_OMP)
1270#pragma omp parallel for
1272 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
1274 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
1275 const auto np = tile.numParticles();
1276 const auto& ptd = tile.getConstParticleTileData();
1277 reduce_ops.
eval(np, reduce_data,
1280 return particle_detail::call_f(f, ptd, i);
1284 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:257
Type value()
Definition AMReX_Reduce.H:289
Definition AMReX_Reduce.H:377
std::enable_if_t< IsFabArray< MF >::value > eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:446
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:28
Long size() const noexcept
Definition AMReX_Vector.H:53
bool inLaunchRegion() noexcept
Definition AMReX_GpuControl.H:92
Definition AMReX_Amr.cpp:49
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:1112
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