Block-Structured AMR Software Framework
AMReX_ParticleMesh.H
Go to the documentation of this file.
1 #ifndef AMREX_PARTICLEMESH_H_
2 #define AMREX_PARTICLEMESH_H_
3 #include <AMReX_Config.H>
4 
5 #include <AMReX_TypeTraits.H>
6 #include <AMReX_MultiFab.H>
7 #include <AMReX_ParticleUtil.H>
8 #include <type_traits>
9 
10 namespace amrex {
11 
12 namespace particle_detail {
13 
14 template <typename F, typename T, typename T_ParticleType, template<class, int, int> class PTDType, int NAR, int NAI>
16 auto call_f (F const& f,
17  const PTDType<T_ParticleType, NAR, NAI>& p,
18  const int i, Array4<T> const& fabarr,
20  GpuArray<Real,AMREX_SPACEDIM> const& dxi) noexcept
21 {
22  using PTDTypeT = std::remove_const_t<std::remove_reference_t<decltype(p)>>;
23  if constexpr ( ! T_ParticleType::is_soa_particle &&
24  IsCallable<F, typename PTDTypeT::ParticleRefType, decltype(fabarr), decltype(plo), decltype(dxi)>::value) {
25  return f(p.m_aos[i], fabarr, plo, dxi);
26  } else if constexpr ( ! T_ParticleType::is_soa_particle &&
27  IsCallable<F, typename PTDTypeT::ParticleRefType, decltype(fabarr)>::value) {
28  return f(p.m_aos[i], fabarr);
29  } else if constexpr (IsCallable<F, decltype(p.getSuperParticle(i)), decltype(fabarr), decltype(plo), decltype(dxi)>::value) {
30  return f(p.getSuperParticle(i), fabarr, plo, dxi);
31  } else if constexpr (IsCallable<F, decltype(p.getSuperParticle(i)), decltype(fabarr)>::value) {
32  return f(p.getSuperParticle(i), fabarr);
33  } else if constexpr (IsCallable<F, decltype(p), int, decltype(fabarr), decltype(plo), decltype(dxi)>::value) {
34  return f(p, i, fabarr, plo, dxi);
35  } else {
36  return f(p, i, fabarr);
37  }
38 }
39 }
40 
41 template <class PC, class MF, class F, std::enable_if_t<IsParticleContainer<PC>::value, int> foo = 0>
42 void
43 ParticleToMesh (PC const& pc, MF& mf, int lev, F const& f, bool zero_out_input=true)
44 {
45  BL_PROFILE("amrex::ParticleToMesh");
46 
47  if (zero_out_input) { mf.setVal(0.0); }
48 
49  MF* mf_pointer;
50 
51  if (pc.OnSameGrids(lev, mf) && zero_out_input)
52  {
53  mf_pointer = &mf;
54  } else {
55  mf_pointer = new MF(pc.ParticleBoxArray(lev),
56  pc.ParticleDistributionMap(lev),
57  mf.nComp(), mf.nGrowVect());
58  mf_pointer->setVal(0.0);
59  }
60 
61  const auto plo = pc.Geom(lev).ProbLoArray();
62  const auto dxi = pc.Geom(lev).InvCellSizeArray();
63 
64  using ParIter = typename PC::ParConstIterType;
65 #ifdef AMREX_USE_GPU
66  if (Gpu::inLaunchRegion())
67  {
68  for(ParIter pti(pc, lev); pti.isValid(); ++pti)
69  {
70  const auto& tile = pti.GetParticleTile();
71  const auto np = tile.numParticles();
72  const auto& ptd = tile.getConstParticleTileData();
73 
74  auto& fab = (*mf_pointer)[pti];
75  auto fabarr = fab.array();
76 
77  AMREX_FOR_1D( np, i,
78  {
79  particle_detail::call_f(f, ptd, i, fabarr, plo, dxi);
80  });
81  }
82  }
83  else
84 #endif
85  {
86 #ifdef AMREX_USE_OMP
87 #pragma omp parallel if (Gpu::notInLaunchRegion())
88 #endif
89  {
90  typename MF::FABType::value_type local_fab;
91  for(ParIter pti(pc, lev); pti.isValid(); ++pti)
92  {
93  const auto& tile = pti.GetParticleTile();
94  const auto np = tile.numParticles();
95  const auto& ptd = tile.getConstParticleTileData();
96 
97  auto& fab = (*mf_pointer)[pti];
98 
99  Box tile_box = pti.tilebox();
100  tile_box.grow(mf_pointer->nGrowVect());
101  local_fab.resize(tile_box,mf_pointer->nComp());
102  local_fab.template setVal<RunOn::Host>(0.0);
103  auto fabarr = local_fab.array();
104 
105  AMREX_FOR_1D( np, i,
106  {
107  particle_detail::call_f(f, ptd, i, fabarr, plo, dxi);
108  });
109 
110  fab.template atomicAdd<RunOn::Host>(local_fab, tile_box, tile_box,
111  0, 0, mf_pointer->nComp());
112  }
113  }
114  }
115 
116  if (mf_pointer != &mf)
117  {
118  mf.ParallelAdd(*mf_pointer, 0, 0, mf_pointer->nComp(),
119  mf_pointer->nGrowVect(), IntVect(0), pc.Geom(lev).periodicity());
120  delete mf_pointer;
121  } else {
122  mf_pointer->SumBoundary(pc.Geom(lev).periodicity());
123  }
124 }
125 
126 template <class PC, class MF, class F, std::enable_if_t<IsParticleContainer<PC>::value, int> foo = 0>
127 void
128 MeshToParticle (PC& pc, MF const& mf, int lev, F const& f)
129 {
130  BL_PROFILE("amrex::MeshToParticle");
131 
132  MF* mf_pointer = pc.OnSameGrids(lev, mf) ?
133  const_cast<MF*>(&mf) : new MF(pc.ParticleBoxArray(lev),
134  pc.ParticleDistributionMap(lev),
135  mf.nComp(), mf.nGrowVect());
136 
137  if (mf_pointer != &mf) {mf_pointer->ParallelCopy(mf,0,0,mf.nComp(),mf.nGrowVect(),mf.nGrowVect()); }
138 
139  const auto plo = pc.Geom(lev).ProbLoArray();
140  const auto dxi = pc.Geom(lev).InvCellSizeArray();
141 
142  using ParIter = typename PC::ParIterType;
143 #ifdef AMREX_USE_OMP
144 #pragma omp parallel if (Gpu::notInLaunchRegion())
145 #endif
146  for(ParIter pti(pc, lev); pti.isValid(); ++pti)
147  {
148  auto& tile = pti.GetParticleTile();
149  const auto np = tile.numParticles();
150  const auto& ptd = tile.getParticleTileData();
151 
152  const auto& fab = (*mf_pointer)[pti];
153  auto fabarr = fab.array();
154 
155  AMREX_FOR_1D( np, i,
156  {
157  particle_detail::call_f(f, ptd, i, fabarr, plo, dxi);
158  });
159  }
160 
161  if (mf_pointer != &mf) { delete mf_pointer; }
162 }
163 
164 }
165 #endif
#define BL_PROFILE(a)
Definition: AMReX_BLProfiler.H:551
#define AMREX_FORCE_INLINE
Definition: AMReX_Extension.H:119
#define AMREX_FOR_1D(...)
Definition: AMReX_GpuLaunch.nolint.H:41
#define AMREX_GPU_HOST_DEVICE
Definition: AMReX_GpuQualifiers.H:20
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< new_dim > resize() const noexcept
Returns a new BoxND of size new_dim by either shrinking or expanding this BoxND.
Definition: AMReX_Box.H:831
AMREX_GPU_HOST_DEVICE BoxND & grow(int i) noexcept
Definition: AMReX_Box.H:627
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition: AMReX_MFIter.H:141
ParticleTileRef GetParticleTile() const
Definition: AMReX_ParIter.H:84
Definition: AMReX_ParIter.H:113
bool inLaunchRegion() noexcept
Definition: AMReX_GpuControl.H:86
static int f(amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data)
Definition: AMReX_SundialsIntegrator.H:44
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE auto call_f(F const &f, const PTDType< T_ParticleType, NAR, NAI > &p, const int i, Array4< T > const &fabarr, GpuArray< Real, AMREX_SPACEDIM > const &plo, GpuArray< Real, AMREX_SPACEDIM > const &dxi) noexcept
Definition: AMReX_ParticleMesh.H:16
Definition: AMReX_Amr.cpp:49
void MeshToParticle(PC &pc, MF const &mf, int lev, F const &f)
Definition: AMReX_ParticleMesh.H:128
void ParticleToMesh(PC const &pc, const Vector< MultiFab * > &mf, int lev_min, int lev_max, F &&f, bool zero_out_input=true, bool vol_weight=true)
Definition: AMReX_AmrParticles.H:156
Definition: AMReX_WriteBinaryParticleData.H:19
Definition: AMReX_Array4.H:61
Test if a given type T is callable with arguments of type Args...
Definition: AMReX_TypeTraits.H:201