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>
91requires (IsParticleContainer<PC>::value)
94 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
96 return ReduceSum(pc, 0, pc.finestLevel(), std::forward<F>(f));
139template <
class PC,
class F>
140requires (IsParticleContainer<PC>::value)
143 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
145 return ReduceSum(pc, lev, lev, std::forward<F>(f));
189template <
class PC,
class F>
190requires (IsParticleContainer<PC>::value)
192ReduceSum (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
193 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
195 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
203 using ReduceTuple =
typename decltype(reduce_data)::Type;
205 for (
int lev = lev_min; lev <= lev_max; ++lev)
207 const auto& plev = pc.GetParticles(lev);
208 for (
const auto& kv : plev)
210 const auto& tile = plev.at(kv.first);
211 const auto np = tile.numParticles();
212 const auto& ptd = tile.getConstParticleTileData();
213 reduce_op.
eval(np, reduce_data,
215 return particle_detail::call_f(f, ptd, i);
220 ReduceTuple hv = reduce_data.
value(reduce_op);
221 sm = amrex::get<0>(hv);
226 for (
int lev = lev_min; lev <= lev_max; ++lev)
228 const auto& plev = pc.GetParticles(lev);
231 for (
auto& kv : plev)
233 grid_tile_ids.push_back(kv.first);
234 ptile_ptrs.push_back(&(kv.second));
239#pragma omp parallel for if (!system::regtest_reduction) reduction(+:sm)
241 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
243 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
244 const auto np = tile.numParticles();
245 const auto& ptd = tile.getConstParticleTileData();
246 for (
int i = 0; i < np; ++i) {
247 sm += particle_detail::call_f(f, ptd, i);
295template <
class PC,
class F>
296requires (IsParticleContainer<PC>::value)
299 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
301 return ReduceMax(pc, 0, pc.finestLevel(), std::forward<F>(f));
345template <
class PC,
class F>
346requires (IsParticleContainer<PC>::value)
349 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
351 return ReduceMax(pc, lev, lev, std::forward<F>(f));
395template <
class PC,
class F>
396requires (IsParticleContainer<PC>::value)
398ReduceMax (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
399 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
401 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
402 constexpr value_type value_lowest = std::numeric_limits<value_type>::lowest();
403 value_type r = value_lowest;
410 using ReduceTuple =
typename decltype(reduce_data)::Type;
412 for (
int lev = lev_min; lev <= lev_max; ++lev)
414 const auto& plev = pc.GetParticles(lev);
415 for (
const auto& kv : plev)
417 const auto& tile = plev.at(kv.first);
418 const auto np = tile.numParticles();
419 const auto& ptd = tile.getConstParticleTileData();
420 reduce_op.
eval(np, reduce_data,
422 return particle_detail::call_f(f, ptd, i);
427 ReduceTuple hv = reduce_data.
value(reduce_op);
428 r = amrex::get<0>(hv);
433 for (
int lev = lev_min; lev <= lev_max; ++lev)
435 const auto& plev = pc.GetParticles(lev);
438 for (
auto& kv : plev)
440 grid_tile_ids.push_back(kv.first);
441 ptile_ptrs.push_back(&(kv.second));
446#pragma omp parallel for if (!system::regtest_reduction) reduction(max:r)
448 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
450 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
451 const auto np = tile.numParticles();
452 const auto& ptd = tile.getConstParticleTileData();
453 for (
int i = 0; i < np; ++i) {
454 r = std::max(r, particle_detail::call_f(f, ptd, i));
502template <
class PC,
class F>
503requires (IsParticleContainer<PC>::value)
506 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
508 return ReduceMin(pc, 0, pc.finestLevel(), std::forward<F>(f));
551template <
class PC,
class F>
552requires (IsParticleContainer<PC>::value)
555 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
557 return ReduceMin(pc, lev, lev, std::forward<F>(f));
601template <
class PC,
class F>
602requires (IsParticleContainer<PC>::value)
604ReduceMin (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
605 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
607 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
608 constexpr value_type value_max = std::numeric_limits<value_type>::max();
609 value_type r = value_max;
616 using ReduceTuple =
typename decltype(reduce_data)::Type;
618 for (
int lev = lev_min; lev <= lev_max; ++lev)
620 const auto& plev = pc.GetParticles(lev);
621 for (
const auto& kv : plev)
623 const auto& tile = plev.at(kv.first);
624 const auto np = tile.numParticles();
625 const auto& ptd = tile.getConstParticleTileData();
626 reduce_op.
eval(np, reduce_data,
628 return particle_detail::call_f(f, ptd, i);
633 ReduceTuple hv = reduce_data.
value(reduce_op);
634 r = amrex::get<0>(hv);
639 for (
int lev = lev_min; lev <= lev_max; ++lev)
641 const auto& plev = pc.GetParticles(lev);
644 for (
auto& kv : plev)
646 grid_tile_ids.push_back(kv.first);
647 ptile_ptrs.push_back(&(kv.second));
652#pragma omp parallel for if (!system::regtest_reduction) reduction(min:r)
654 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
656 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
657 const auto np = tile.numParticles();
658 const auto& ptd = tile.getConstParticleTileData();
659 for (
int i = 0; i < np; ++i) {
660 r = std::min(r, particle_detail::call_f(f, ptd, i));
708template <
class PC,
class F>
709requires (IsParticleContainer<PC>::value)
756template <
class PC,
class F>
757requires (IsParticleContainer<PC>::value)
805template <
class PC,
class F>
806requires (IsParticleContainer<PC>::value)
817 using ReduceTuple =
typename decltype(reduce_data)::Type;
819 for (
int lev = lev_min; lev <= lev_max; ++lev)
821 const auto& plev = pc.GetParticles(lev);
822 for (
const auto& kv : plev)
824 const auto& tile = plev.at(kv.first);
825 const auto np = tile.numParticles();
826 const auto& ptd = tile.getConstParticleTileData();
827 reduce_op.
eval(np, reduce_data,
829 return particle_detail::call_f(f, ptd, i);
834 ReduceTuple hv = reduce_data.
value(reduce_op);
835 r = amrex::get<0>(hv);
840 for (
int lev = lev_min; lev <= lev_max; ++lev)
842 const auto& plev = pc.GetParticles(lev);
845 for (
auto& kv : plev)
847 grid_tile_ids.push_back(kv.first);
848 ptile_ptrs.push_back(&(kv.second));
853#pragma omp parallel for if (!system::regtest_reduction) reduction(&&:r)
855 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
857 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
858 const auto np = tile.numParticles();
859 const auto& ptd = tile.getConstParticleTileData();
860 for (
int i = 0; i < np; ++i) {
861 r = r && particle_detail::call_f(f, ptd, i);
909template <
class PC,
class F>
910requires (IsParticleContainer<PC>::value)
957template <
class PC,
class F>
958requires (IsParticleContainer<PC>::value)
1006template <
class PC,
class F>
1007requires (IsParticleContainer<PC>::value)
1018 using ReduceTuple =
typename decltype(reduce_data)::Type;
1020 for (
int lev = lev_min; lev <= lev_max; ++lev)
1022 const auto& plev = pc.GetParticles(lev);
1023 for (
const auto& kv : plev)
1025 const auto& tile = plev.at(kv.first);
1026 const auto np = tile.numParticles();
1027 const auto& ptd = tile.getConstParticleTileData();
1028 reduce_op.
eval(np, reduce_data,
1031 return particle_detail::call_f(f, ptd, i);
1036 ReduceTuple hv = reduce_data.
value(reduce_op);
1037 r = amrex::get<0>(hv);
1042 for (
int lev = lev_min; lev <= lev_max; ++lev)
1044 const auto& plev = pc.GetParticles(lev);
1047 for (
auto& kv : plev)
1049 grid_tile_ids.push_back(kv.first);
1050 ptile_ptrs.push_back(&(kv.second));
1055#pragma omp parallel for if (!system::regtest_reduction) reduction(||:r)
1057 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
1059 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
1060 const auto np = tile.numParticles();
1061 const auto& ptd = tile.getConstParticleTileData();
1062 for (
int i = 0; i < np; ++i) {
1063 r = r || particle_detail::call_f(f, ptd, i);
1134template <
class RD,
class PC,
class F,
class ReduceOps>
1135requires (IsParticleContainer<PC>::value)
1139 return ParticleReduce<RD>(pc, 0, pc.finestLevel(), std::forward<F>(f), reduce_ops);
1205template <
class RD,
class PC,
class F,
class ReduceOps>
1206requires (IsParticleContainer<PC>::value)
1210 return ParticleReduce<RD>(pc, lev, lev, std::forward<F>(f), reduce_ops);
1277template <
class RD,
class PC,
class F,
class ReduceOps>
1278requires (IsParticleContainer<PC>::value)
1282 RD reduce_data(reduce_ops);
1283 for (
int lev = lev_min; lev <= lev_max; ++lev) {
1284 const auto& plev = pc.GetParticles(lev);
1287 for (
auto& kv : plev)
1289 grid_tile_ids.push_back(kv.first);
1290 ptile_ptrs.push_back(&(kv.second));
1294#if !defined(AMREX_USE_GPU) && defined(AMREX_USE_OMP)
1295#pragma omp parallel for
1297 for (
int pmap_it = 0; pmap_it < std::ssize(ptile_ptrs); ++pmap_it)
1299 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
1300 const auto np = tile.numParticles();
1301 const auto& ptd = tile.getConstParticleTileData();
1302 reduce_ops.
eval(np, reduce_data,
1305 return particle_detail::call_f(f, ptd, i);
1309 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:438
Type value()
Definition AMReX_Reduce.H:473
Definition AMReX_Reduce.H:597
void eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:731
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
bool inLaunchRegion() noexcept
Definition AMReX_GpuControl.H:88
Definition AMReX_Amr.cpp:50
FAB::value_type ReduceMin(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:304
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:1137
bool ReduceLogicalOr(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:904
bool ReduceLogicalAnd(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:757
FAB::value_type ReduceMax(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:530
FAB::value_type ReduceSum(FabArray< FAB > const &fa, int nghost, F &&f)
Definition AMReX_FabArrayUtility.H:16