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));
38template <
typename F,
template<
class,
class>
class PTDType,
class RType,
class IType>
40auto call_f (F
const& f,
41 const PTDType<RType, IType>& p,
89template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
92 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
94 return ReduceSum(pc, 0, pc.finestLevel(), std::forward<F>(f));
137template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
140 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
142 return ReduceSum(pc, lev, lev, std::forward<F>(f));
186template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
188ReduceSum (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
189 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
191 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
199 using ReduceTuple =
typename decltype(reduce_data)::Type;
201 for (
int lev = lev_min; lev <= lev_max; ++lev)
203 const auto& plev = pc.GetParticles(lev);
204 for (
const auto& kv : plev)
206 const auto& tile = plev.at(kv.first);
207 const auto np = tile.numParticles();
208 const auto& ptd = tile.getConstParticleTileData();
209 reduce_op.
eval(np, reduce_data,
211 return particle_detail::call_f(f, ptd, i);
216 ReduceTuple hv = reduce_data.
value(reduce_op);
217 sm = amrex::get<0>(hv);
222 for (
int lev = lev_min; lev <= lev_max; ++lev)
224 const auto& plev = pc.GetParticles(lev);
227 for (
auto& kv : plev)
229 grid_tile_ids.push_back(kv.first);
230 ptile_ptrs.push_back(&(kv.second));
235#pragma omp parallel for if (!system::regtest_reduction) reduction(+:sm)
237 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
239 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
240 const auto np = tile.numParticles();
241 const auto& ptd = tile.getConstParticleTileData();
242 for (
int i = 0; i < np; ++i) {
243 sm += particle_detail::call_f(f, ptd, i);
291template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
294 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
296 return ReduceMax(pc, 0, pc.finestLevel(), std::forward<F>(f));
340template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
343 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
345 return ReduceMax(pc, lev, lev, std::forward<F>(f));
389template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
391ReduceMax (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
392 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
394 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
395 constexpr value_type value_lowest = std::numeric_limits<value_type>::lowest();
396 value_type r = value_lowest;
403 using ReduceTuple =
typename decltype(reduce_data)::Type;
405 for (
int lev = lev_min; lev <= lev_max; ++lev)
407 const auto& plev = pc.GetParticles(lev);
408 for (
const auto& kv : plev)
410 const auto& tile = plev.at(kv.first);
411 const auto np = tile.numParticles();
412 const auto& ptd = tile.getConstParticleTileData();
413 reduce_op.
eval(np, reduce_data,
415 return particle_detail::call_f(f, ptd, i);
420 ReduceTuple hv = reduce_data.
value(reduce_op);
421 r = amrex::get<0>(hv);
426 for (
int lev = lev_min; lev <= lev_max; ++lev)
428 const auto& plev = pc.GetParticles(lev);
431 for (
auto& kv : plev)
433 grid_tile_ids.push_back(kv.first);
434 ptile_ptrs.push_back(&(kv.second));
439#pragma omp parallel for if (!system::regtest_reduction) reduction(max:r)
441 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
443 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
444 const auto np = tile.numParticles();
445 const auto& ptd = tile.getConstParticleTileData();
446 for (
int i = 0; i < np; ++i) {
447 r = std::max(r, particle_detail::call_f(f, ptd, i));
495template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
498 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
500 return ReduceMin(pc, 0, pc.finestLevel(), std::forward<F>(f));
543template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
546 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
548 return ReduceMin(pc, lev, lev, std::forward<F>(f));
592template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
594ReduceMin (PC
const& pc,
int lev_min,
int lev_max,
F const& f)
595 ->
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()))
597 using value_type =
decltype(particle_detail::call_f(f,
typename PC::ConstPTDType(),
int()));
598 constexpr value_type value_max = std::numeric_limits<value_type>::max();
599 value_type r = value_max;
606 using ReduceTuple =
typename decltype(reduce_data)::Type;
608 for (
int lev = lev_min; lev <= lev_max; ++lev)
610 const auto& plev = pc.GetParticles(lev);
611 for (
const auto& kv : plev)
613 const auto& tile = plev.at(kv.first);
614 const auto np = tile.numParticles();
615 const auto& ptd = tile.getConstParticleTileData();
616 reduce_op.
eval(np, reduce_data,
618 return particle_detail::call_f(f, ptd, i);
623 ReduceTuple hv = reduce_data.
value(reduce_op);
624 r = amrex::get<0>(hv);
629 for (
int lev = lev_min; lev <= lev_max; ++lev)
631 const auto& plev = pc.GetParticles(lev);
634 for (
auto& kv : plev)
636 grid_tile_ids.push_back(kv.first);
637 ptile_ptrs.push_back(&(kv.second));
642#pragma omp parallel for if (!system::regtest_reduction) reduction(min:r)
644 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
646 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
647 const auto np = tile.numParticles();
648 const auto& ptd = tile.getConstParticleTileData();
649 for (
int i = 0; i < np; ++i) {
650 r = std::min(r, particle_detail::call_f(f, ptd, i));
698template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
745template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
793template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
804 using ReduceTuple =
typename decltype(reduce_data)::Type;
806 for (
int lev = lev_min; lev <= lev_max; ++lev)
808 const auto& plev = pc.GetParticles(lev);
809 for (
const auto& kv : plev)
811 const auto& tile = plev.at(kv.first);
812 const auto np = tile.numParticles();
813 const auto& ptd = tile.getConstParticleTileData();
814 reduce_op.
eval(np, reduce_data,
816 return particle_detail::call_f(f, ptd, i);
821 ReduceTuple hv = reduce_data.
value(reduce_op);
822 r = amrex::get<0>(hv);
827 for (
int lev = lev_min; lev <= lev_max; ++lev)
829 const auto& plev = pc.GetParticles(lev);
832 for (
auto& kv : plev)
834 grid_tile_ids.push_back(kv.first);
835 ptile_ptrs.push_back(&(kv.second));
840#pragma omp parallel for if (!system::regtest_reduction) reduction(&&:r)
842 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
844 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
845 const auto np = tile.numParticles();
846 const auto& ptd = tile.getConstParticleTileData();
847 for (
int i = 0; i < np; ++i) {
848 r = r && particle_detail::call_f(f, ptd, i);
896template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
943template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
991template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1002 using ReduceTuple =
typename decltype(reduce_data)::Type;
1004 for (
int lev = lev_min; lev <= lev_max; ++lev)
1006 const auto& plev = pc.GetParticles(lev);
1007 for (
const auto& kv : plev)
1009 const auto& tile = plev.at(kv.first);
1010 const auto np = tile.numParticles();
1011 const auto& ptd = tile.getConstParticleTileData();
1012 reduce_op.
eval(np, reduce_data,
1015 return particle_detail::call_f(f, ptd, i);
1020 ReduceTuple hv = reduce_data.
value(reduce_op);
1021 r = amrex::get<0>(hv);
1026 for (
int lev = lev_min; lev <= lev_max; ++lev)
1028 const auto& plev = pc.GetParticles(lev);
1031 for (
auto& kv : plev)
1033 grid_tile_ids.push_back(kv.first);
1034 ptile_ptrs.push_back(&(kv.second));
1039#pragma omp parallel for if (!system::regtest_reduction) reduction(||:r)
1041 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
1043 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
1044 const auto np = tile.numParticles();
1045 const auto& ptd = tile.getConstParticleTileData();
1046 for (
int i = 0; i < np; ++i) {
1047 r = r || particle_detail::call_f(f, ptd, i);
1118template <
class RD,
class PC,
class F,
class ReduceOps,
1119 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1123 return ParticleReduce<RD>(pc, 0, pc.finestLevel(), std::forward<F>(f), reduce_ops);
1189template <
class RD,
class PC,
class F,
class ReduceOps,
1190 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1194 return ParticleReduce<RD>(pc, lev, lev, std::forward<F>(f), reduce_ops);
1261template <
class RD,
class PC,
class F,
class ReduceOps,
1262 std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
1266 RD reduce_data(reduce_ops);
1267 for (
int lev = lev_min; lev <= lev_max; ++lev) {
1268 const auto& plev = pc.GetParticles(lev);
1271 for (
auto& kv : plev)
1273 grid_tile_ids.push_back(kv.first);
1274 ptile_ptrs.push_back(&(kv.second));
1278#if !defined(AMREX_USE_GPU) && defined(AMREX_USE_OMP)
1279#pragma omp parallel for
1281 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
1283 const auto& tile = plev.at(grid_tile_ids[pmap_it]);
1284 const auto np = tile.numParticles();
1285 const auto& ptd = tile.getConstParticleTileData();
1286 reduce_ops.
eval(np, reduce_data,
1289 return particle_detail::call_f(f, ptd, i);
1293 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:746
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:1121
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