ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERFPC.H
Go to the documentation of this file.
1 #ifndef ERF_PC_H_
2 #define ERF_PC_H_
3 
4 #ifdef ERF_USE_PARTICLES
5 
6 #include <string>
7 #include <AMReX_Particles.H>
8 
9 struct ERFParticlesIntIdxAoS
10 {
11  enum {
12  k = 0,
13  ncomps
14  };
15 };
16 
17 struct ERFParticlesRealIdxAoS
18 {
19  enum {
20  ncomps = 0
21  };
22 };
23 
24 struct ERFParticlesIntIdxSoA
25 {
26  enum {
27  ncomps = 0
28  };
29 };
30 
31 struct ERFParticlesRealIdxSoA
32 {
33  enum {
34  vx = 0,
35  vy,
36  vz,
37  mass,
38  temperature,
39  ncomps
40  };
41 };
42 
43 namespace ERFParticleInitializations
44 {
45  /* list of particle initializations */
46  const std::string init_box_uniform = "box";
47 }
48 
49 namespace ERFParticleNames
50 {
51  const std::string tracers = "tracer_particles";
52 }
53 
54 struct ERFParticlesAssignor
55 {
56  template <typename P>
57  AMREX_GPU_HOST_DEVICE
58  amrex::IntVect operator() ( P const& p,
59  amrex::GpuArray<amrex::Real,AMREX_SPACEDIM> const& plo,
60  amrex::GpuArray<amrex::Real,AMREX_SPACEDIM> const& dxi,
61  const amrex::Box& domain ) const noexcept
62  {
63  amrex::IntVect iv(
64  AMREX_D_DECL( int(amrex::Math::floor((p.pos(0)-plo[0])*dxi[0])),
65  int(amrex::Math::floor((p.pos(1)-plo[1])*dxi[1])),
66  p.idata(ERFParticlesIntIdxAoS::k) ) );
67  iv[0] += domain.smallEnd()[0];
68  iv[1] += domain.smallEnd()[1];
69  return iv;
70  }
71 };
72 
73 template <typename P>
74 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
75 void update_location_idata ( P& a_p,
76  amrex::GpuArray<amrex::Real,AMREX_SPACEDIM> const& a_plo,
77  amrex::GpuArray<amrex::Real,AMREX_SPACEDIM> const& a_dxi,
78  const amrex::Array4<amrex::Real const>& a_height_arr )
79 {
80  if (a_height_arr) {
81  while (1) {
82  amrex::IntVect iv( int(amrex::Math::floor((a_p.pos(0)-a_plo[0])*a_dxi[0])),
83  int(amrex::Math::floor((a_p.pos(1)-a_plo[1])*a_dxi[1])),
84  a_p.idata(ERFParticlesIntIdxAoS::k) );
85  amrex::Real lx = (a_p.pos(0)-a_plo[0])*a_dxi[0] - static_cast<amrex::Real>(iv[0]);
86  amrex::Real ly = (a_p.pos(1)-a_plo[1])*a_dxi[1] - static_cast<amrex::Real>(iv[1]);
87  auto zlo = a_height_arr(iv[0] ,iv[1] ,iv[2] ) * (1.0-lx) * (1.0-ly) +
88  a_height_arr(iv[0]+1,iv[1] ,iv[2] ) * lx * (1.0-ly) +
89  a_height_arr(iv[0] ,iv[1]+1,iv[2] ) * (1.0-lx) * ly +
90  a_height_arr(iv[0]+1,iv[1]+1,iv[2] ) * lx * ly;
91  auto zhi = a_height_arr(iv[0] ,iv[1] ,iv[2]+1) * (1.0-lx) * (1.0-ly) +
92  a_height_arr(iv[0]+1,iv[1] ,iv[2]+1) * lx * (1.0-ly) +
93  a_height_arr(iv[0] ,iv[1]+1,iv[2]+1) * (1.0-lx) * ly +
94  a_height_arr(iv[0]+1,iv[1]+1,iv[2]+1) * lx * ly;
95 
96  if (a_p.pos(2) > zhi) {
97  a_p.idata(ERFParticlesIntIdxAoS::k) += 1;
98  } else if (a_p.pos(2) <= zlo) {
99  a_p.idata(ERFParticlesIntIdxAoS::k) -= 1;
100  } else {
101  break;
102  }
103  }
104  }
105 }
106 
107 class ERFPC : public amrex::ParticleContainer< ERFParticlesRealIdxAoS::ncomps, // AoS real attributes
108  ERFParticlesIntIdxAoS::ncomps, // AoS integer attributes
109  ERFParticlesRealIdxSoA::ncomps, // SoA real attributes
110  ERFParticlesIntIdxSoA::ncomps, // SoA integer attributes
111  amrex::DefaultAllocator,
112  ERFParticlesAssignor >
113 {
114  public:
115 
116  /*! Constructor */
117  ERFPC ( amrex::ParGDBBase* a_gdb,
118  const std::string& a_name = "particles" )
119  : amrex::ParticleContainer< ERFParticlesRealIdxAoS::ncomps, // AoS real attributes
120  ERFParticlesIntIdxAoS::ncomps, // AoS integer attributes
121  ERFParticlesRealIdxSoA::ncomps, // SoA real attributes
122  ERFParticlesIntIdxSoA::ncomps, // SoA integer attributes
123  amrex::DefaultAllocator,
124  ERFParticlesAssignor> (a_gdb)
125  {
126  BL_PROFILE("ERFPCPC::ERFPC()");
127  m_name = a_name;
128  readInputs();
129  }
130 
131  /*! Constructor */
132  ERFPC ( const amrex::Geometry& a_geom,
133  const amrex::DistributionMapping& a_dmap,
134  const amrex::BoxArray& a_ba,
135  const std::string& a_name = "particles" )
136  : amrex::ParticleContainer< ERFParticlesRealIdxAoS::ncomps, // AoS real attributes
137  ERFParticlesIntIdxAoS::ncomps, // AoS real attributes
138  ERFParticlesRealIdxSoA::ncomps, // SoA real attributes
139  ERFParticlesIntIdxSoA::ncomps, // SoA integer attributes
140  amrex::DefaultAllocator,
141  ERFParticlesAssignor> ( a_geom, a_dmap, a_ba )
142  {
143  BL_PROFILE("ERFPCPC::ERFPC()");
144  m_name = a_name;
145  readInputs();
146  }
147 
148  /*! Initialize particles in domain */
149  virtual void InitializeParticles (const amrex::Real time, const std::unique_ptr<amrex::MultiFab>& a_ptr = nullptr);
150 
151  /*! Evolve particles for one time step */
152  virtual void EvolveParticles ( int,
153  amrex::Real,
154  amrex::Vector<amrex::Vector<amrex::MultiFab>>&,
155  const amrex::Vector<std::unique_ptr<amrex::MultiFab>>& );
156 
157  /*! Get real-type particle attribute names */
158  virtual amrex::Vector<std::string> varNames () const
159  {
160  BL_PROFILE("ERFPCPC::varNames()");
161  return {AMREX_D_DECL("xvel","yvel","zvel"),"mass","temperature"};
162  }
163 
164  /*! Get real-type particle attribute names */
165  virtual amrex::Vector<std::string> meshPlotVarNames () const
166  {
167  BL_PROFILE("ERFPCPC::varNames()");
168  return {"mass_density"};
169  }
170 
171  /*! Uses midpoint method to advance particles using flow velocity. */
172  virtual void AdvectWithFlow ( amrex::MultiFab*,
173  int,
174  amrex::Real,
175  const std::unique_ptr<amrex::MultiFab>& );
176 
177  /*! Uses midpoint method to advance particles falling under gravity. */
178  virtual void AdvectWithGravity ( int,
179  amrex::Real,
180  const std::unique_ptr<amrex::MultiFab>& );
181 
182  /*! Interpolates flow temperature to particles */
183  virtual void ComputeTemperature ( const amrex::MultiFab&,
184  int,
185  amrex::Real,
186  const std::unique_ptr<amrex::MultiFab>& );
187 
188  /*! Compute mass density */
189  virtual void massDensity ( amrex::MultiFab&, const int&, const int& a_comp = 0) const;
190 
191  /*! Compute mesh variable from particles */
192  virtual void computeMeshVar( const std::string& a_var_name,
193  amrex::MultiFab& a_mf,
194  const int a_lev) const
195  {
196  if (a_var_name == "mass_density") {
197  massDensity( a_mf, a_lev );
198  } else {
199  a_mf.setVal(0.0);
200  }
201  }
202 
203  /*! Specify if particles should advect with flow */
204  inline void setAdvectWithFlow (bool a_flag)
205  {
206  BL_PROFILE("ERFPCPC::setAdvectWithFlow()");
207  m_advect_w_flow = a_flag;
208  }
209  /*! Specify if particles fall under gravity */
210  inline void setAdvectWithGravity (bool a_flag)
211  {
212  BL_PROFILE("ERFPCPC::setAdvectWithGravity()");
213  m_advect_w_gravity = a_flag;
214  }
215 
216  // the following functions should ideally be private or protected, but need to be
217  // public due to CUDA extended lambda capture rules
218 
219  /*! Default particle initialization */
220  void initializeParticlesUniformDistributionInBox (const std::unique_ptr<amrex::MultiFab>& a_ptr,
221  const amrex::RealBox& particle_box);
222 
223  protected:
224 
225  bool m_advect_w_flow; /*!< advect with flow velocity */
226  bool m_advect_w_gravity; /*!< advect under gravitational force */
227 
228  amrex::RealBox m_particle_box; /*!< box within which to place particles */
229 
230  std::string m_name; /*!< name of this particle species */
231 
232  std::string m_initialization_type; /*!< initial particle distribution type */
233  int m_ppc_init; /*!< initial number of particles per cell */
234 
235  amrex::Real m_inject_start_time; /*!< particles will only be initialized/injected if time >= m_inject_start_time */
236 
237  bool m_initialized = false; /*!< have the particles been initialized */
238 
239  bool m_stable_redistribute; /*!< use stable redistribute for deterministic simulations */
240 
241  /*! read inputs from file */
242  virtual void readInputs ();
243 
244  private:
245 
246  bool place_randomly_in_cells; /*!< place particles at random positions? */
247 };
248 
249 #endif
250 #endif
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_ConsoleIO.cpp:12