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