ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SuperDropletPC.H
Go to the documentation of this file.
1 #ifndef SUPERDROPLET_PC_H_
2 #define SUPERDROPLET_PC_H_
3 
4 #ifdef ERF_USE_PARTICLES
5 
6 #include <random>
7 #include "ERF_Constants.H"
10 
11 class SuperDropletPC : public ERFPC
12 {
13  using MFPtr = std::unique_ptr<amrex::MultiFab>;
14  using BCTypeArr = amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2>;
15 
16  public:
17 
18  /*! \brief Constructor */
19  SuperDropletPC ( amrex::ParGDBBase* a_gdb,
20  const std::vector<Species::Name>& a_species_mat,
21  const std::vector<Species::Name>& a_aerosol_mat,
22  const amrex::Real a_dt,
23  const std::string& a_name = "super_droplets" )
24  : ERFPC (a_gdb, a_name)
25  {
26  define( a_species_mat,
27  a_aerosol_mat,
28  a_gdb->ParticleBoxArray(m_lev),
29  a_gdb->ParticleDistributionMap(m_lev),
30  a_dt );
31  }
32 
33  /*! \brief Constructor */
34  SuperDropletPC ( const amrex::Geometry& a_geom,
35  const amrex::DistributionMapping& a_dmap,
36  const amrex::BoxArray& a_ba,
37  const std::vector<Species::Name>& a_species_mat,
38  const std::vector<Species::Name>& a_aerosol_mat,
39  const amrex::Real a_dt,
40  const std::string& a_name = "super_droplets" )
41  : ERFPC (a_geom, a_dmap, a_ba, a_name)
42  {
43  define(a_species_mat, a_aerosol_mat, a_ba, a_dmap, a_dt);
44  }
45 
46  /*! \brief Destructor */
47  ~SuperDropletPC()
48  {
49  if (m_mass_change_logging) {
50  fclose(m_mass_change_log);
51  }
52  }
53 
54  /*! \brief Set vapour species material */
55  AMREX_FORCE_INLINE
56  virtual void setSpeciesMaterial ( const Species::Name& a_name )
57  {
58  if (a_name == Species::Name::H2O) {
59  m_idx_w = m_species_mat.size();
60  }
61  m_species_mat.push_back(std::make_unique<MaterialProperties>(a_name));
62  }
63 
64  /*! \brief Set species material */
65  AMREX_FORCE_INLINE
66  virtual void setSpeciesMaterial ( const std::vector<Species::Name>& a_names )
67  {
68  for (auto& name : a_names) { setSpeciesMaterial(name); }
69  }
70 
71  /*! \brief Get vapour material */
72  AMREX_FORCE_INLINE
73  virtual const MaterialProperties& getSpeciesMaterial(const Species::Name& a_name) const
74  {
75  for (auto& species : m_species_mat) {
76  if (species->m_name == a_name) { return *species; }
77  }
78  amrex::Abort("SuperDropletPC::getSpeciesMaterial() - species not found");
79  return *m_species_mat[0];
80  }
81 
82  /*! \brief Set aerosol material */
83  AMREX_FORCE_INLINE
84  virtual void setAerosolMaterial ( const Species::Name& a_name )
85  {
86  m_aerosol_mat.push_back(std::make_unique<MaterialProperties>(a_name));
87  }
88 
89  /*! \brief Set aerosol material */
90  AMREX_FORCE_INLINE
91  virtual void setAerosolMaterial ( const std::vector<Species::Name>& a_names )
92  {
93  for (auto& name : a_names) { setAerosolMaterial(name); }
94  }
95 
96  /*! \brief Get real-type particle attribute names */
97  [[nodiscard]] virtual amrex::Vector<std::string> varNames () const override;
98 
99  /*! \brief Get Eulerian plot variable names */
100  [[nodiscard]] virtual amrex::Vector<std::string> meshPlotVarNames () const override;
101 
102  /*! \brief Compute mesh variable from particles */
103  virtual void computeMeshVar( const std::string&,
104  amrex::MultiFab&,
105  const int ) const override;
106 
107  /*! \brief Initialize super-droplets in domain */
108  virtual void InitializeParticles (const amrex::Real, const MFPtr& a_ptr) override;
109 
110  /*! \brief Inject super-droplets in domain */
111  virtual void InjectParticles (const amrex::Real, const MFPtr& a_ptr, const amrex::Real);
112 
113  /*! \brief add particles for a given set of initialization parameters */
114  void addParticles ( const MFPtr&, const SDInitProperties& );
115 
116  /*! \brief Set initial number of superdroplets per cell as a box with uniform density */
117  void setNumSDBoxDistribution( amrex::iMultiFab&,
118  const int,
119  const MFPtr&,
120  const amrex::RealBox&,
121  const bool );
122 
123  /*! \brief Set initial number of superdroplets per cell as a bubble with uniform density */
124  void setNumSDBubbleDistribution( amrex::iMultiFab&,
125  const int,
126  const MFPtr&,
127  const amrex::RealBox&,
128  const bool );
129 
130  /*! \brief Set super-droplets attributes from a given condensate mass density
131  * \param[in] a_mf Multifab containing the initial condensate mass density
132  */
133  virtual void SetAttributes ( amrex::MultiFab& a_mf );
134 
135  /*! \brief Scale the SDM number density with air density
136  * \param[in] a_mf Multifab containing the air density field
137  */
138  virtual void DensityScaling ( const amrex::MultiFab& a_mf );
139 
140  /*! \brief Evolve particles for one time step */
141  virtual void EvolveParticles ( int,
142  amrex::Real,
143  amrex::Vector<amrex::Vector<amrex::MultiFab>>&,
144  const amrex::Vector<MFPtr>& ) override
145  {
146  amrex::Abort("SuperDropletPC::EvolveParticles() is intentionally disabled.");
147  }
148 
149  /*! \brief Advect particles for one time step
150  * \param[in] a_lev AMR level
151  * \param[in] a_time Current simulation time
152  * \param[in] a_dt Timestep for advection
153  * \param[in] a_flow_vel Array of face-based velocities
154  * \param[in] a_density Density field
155  * \param[in] a_pressure Pressure field
156  * \param[in] a_temperature Temperature field
157  * \param[in] a_z_phys_nd Array of terrain heights
158  * \param[in] a_bctypes Array of boundary condition types
159  * \param[in] a_recycle Flag to enable particle recycling
160  */
161  virtual void AdvectParticles ( int a_lev,
162  amrex::Real a_time,
163  amrex::Real a_dt,
164  const amrex::MultiFab* const a_flow_vel,
165  const amrex::MultiFab& a_density,
166  const amrex::MultiFab& a_pressure,
167  const amrex::MultiFab& a_temperature,
168  const amrex::Vector<MFPtr>& a_z_phys_nd,
169  const BCTypeArr& a_bctypes,
170  const bool a_recycle);
171 
172  /*! \brief Grow/shrink particles for one time step
173  * \param[in] a_lev AMR level
174  * \param[in] a_dt Timestep for mass change
175  * \param[in] a_vap_name Name of the vapour species undergoing phase change
176  * \param[in] a_temperature Temperature field
177  * \param[in] a_pressure Pressure field
178  * \param[in] a_sat_pressure Saturation pressure field
179  * \param[in] a_sat_ratio Saturation ratio field
180  * \param[in] a_z_phys_nd Array of terrain heights
181  * \param[in] a_is_water Flag indicating if this is water species
182  */
183  virtual void MassChange ( int a_lev,
184  amrex::Real a_dt,
185  const Species::Name& a_vap_name,
186  const amrex::MultiFab& a_temperature,
187  const amrex::MultiFab& a_pressure,
188  const amrex::MultiFab& a_sat_pressure,
189  const amrex::MultiFab& a_sat_ratio,
190  const amrex::Vector<MFPtr>& a_z_phys_nd,
191  const bool a_is_water);
192 
193  /*! \brief Coalescence of super-droplets
194  * \param[in] a_lev AMR level
195  * \param[in] a_dt Timestep for coalescence
196  * \param[in] a_pressure Pressure field used in coalescence calculation
197  * \param[in] a_temperature Temperature field used in coalescence calculation
198  */
199  virtual void Coalescence ( int a_lev,
200  amrex::Real a_dt,
201  const amrex::MultiFab& a_pressure,
202  const amrex::MultiFab& a_temperature);
203 
204  /*! \brief Recycle super-droplets
205  * \param[in] a_lev AMR level
206  * \param[in] a_z_phys_nd Array of terrain heights
207  * \param[in] a_iter Current iteration number
208  * \param[in] a_dt Timestep size
209  * \param[in] a_recycle Flag to enable recycling
210  */
211  virtual void Recycle ( const int a_lev,
212  const amrex::Vector<MFPtr>& a_z_phys_nd,
213  const int a_iter,
214  const amrex::Real a_dt,
215  const bool a_recycle);
216 
217  /*! \brief Return the number of super-droplets
218  This returns the number of AMReX particles being used in the simulation. */
219  [[nodiscard]] inline virtual amrex::Long NumSuperDroplets ()
220  {
221  return ERFPC::TotalNumberOfParticles();
222  }
223 
224  /*! \brief Return the total number of physical particles */
225  [[nodiscard]] virtual amrex::Real TotalNumberOfParticles ();
226 
227  /*! \brief Return the number of deactivated super-droplets */
228  [[nodiscard]] virtual amrex::Long NumSDDeactivated ();
229 
230  /*! \brief Compute and print diagnostics */
231  virtual void Diagnostics (int, amrex::Real, bool);
232  /*! \brief Compute mass density distribution */
233  virtual void ComputeDistributions ( int,
234  amrex::ParticleReal,
235  amrex::ParticleReal );
236 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
237  /*! \brief Compute binned size distributions */
238  virtual void ComputeBinnedDistributions ( int );
239  /*! \brief Compute cell-wise binned size distributions */
240  virtual void ComputeBinnedDistributionsCell ( int, amrex::Real );
241 #endif
242 
243  /*! \brief Compute the SD number density on a mesh */
244  virtual void SDNumberDensity ( amrex::MultiFab&, const int a_comp=0 ) const;
245  /*! \brief Compute the particle number density on a mesh */
246  virtual void numberDensity ( amrex::MultiFab&, const int a_comp=0 ) const;
247  /*! \brief Compute the particle mass density on a mesh */
248  virtual void massDensity ( amrex::MultiFab&, const int a_comp=0 ) const;
249  /*! \brief Compute the mass flux component on a mesh */
250  virtual void massFlux ( amrex::MultiFab&, const int, const int a_comp=0 ) const;
251 
252  /*! \brief Compute the condensate mass density on a mesh */
253  virtual void speciesMassDensity ( amrex::MultiFab& a_mf, const int a_i ) const
254  {
255  speciesMassDensity(a_mf, a_i, 0.0, DBL_MAX);
256  }
257  /*! \brief Compute the condensate mass density on a mesh */
258  virtual void speciesMassDensity ( amrex::MultiFab&,
259  const int,
260  const amrex::Real,
261  const amrex::Real,
262  const int a_comp = 0) const;
263  /*! \brief Compute the condensate mass flux component on a mesh */
264  virtual void speciesMassFlux ( amrex::MultiFab&, const int, const int, const int a_comp=0 ) const;
265 
266  /*! \brief Compute the aerosol mass density on a mesh */
267  virtual void aerosolMassDensity ( amrex::MultiFab&, const int, const int a_comp=0 ) const;
268  /*! \brief Compute the aerosol mass flux component on a mesh */
269  virtual void aerosolMassFlux ( amrex::MultiFab&, const int, const int, const int a_comp=0 ) const;
270 
271  /*! \brief Compute the particle effective radius on a mesh */
272  virtual void effectiveRadius ( amrex::MultiFab&, const int a_comp=0 ) const;
273 
274  /*! \brief Applies boundary treatment to the particle container */
275  virtual void applyBoundaryTreatment ( int, const amrex::Vector<MFPtr>&, const BCTypeArr&, const bool );
276 
277  protected:
278 
279  const int m_lev = 0; /*!< AMR Level: always 0 for super-droplets PC */
280 
281  SDCoalescenceKernelType m_coalescence_kernel; /*!< Coalescence kernel */
282  bool m_include_brownian_coalescence; /*!< Include Brownian coalescence? */
283 
284  SDTerminalVelocityType m_term_vel_type; /*!< Terminal velocity model */
285 
286  int m_num_sd_per_cell; /*!< Number of super-droplets per cell */
287  bool m_density_scaling; /*!< Scale initial number density with air density */
288  bool m_nucleate_particles; /*!< nucleate new superdroplets from vapour */
289  bool m_prescribed_advection; /*!< move particles with prescribed vertical velocity */
290 
291  int m_num_species; /*!< Number of vapour/condensate species */
292  std::vector<std::unique_ptr<MaterialProperties>> m_species_mat; /*!< Vapour/condensate material */
293  int m_num_aerosols; /*!< Number of aerosols */
294  std::vector<std::unique_ptr<MaterialProperties>> m_aerosol_mat; /*!< Aerosol materials */
295 
296  /* Mass change equation Newton solver parameters */
297  amrex::Real m_newton_rtol; /*!< Newton solver - relative tolerance */
298  amrex::Real m_newton_atol; /*!< Newton solver - absolute tolerance */
299  amrex::Real m_newton_stol; /*!< Newton solver - step tolerance */
300  int m_newton_maxits; /*!< Newton solver - maximum iterations */
301 
302  /* Mass change equation (un)convergence logs */
303  bool m_mass_change_logging; /*!< Whether to log unconverged particles */
304  FILE* m_mass_change_log; /*!< File handle for log with unconverged info */
305  std::string m_mass_change_log_fname; /*!< Name of unconverged info log file */
306 
307  amrex::Real m_mass_change_cfl; /*!< CFL for phase change equation */
308  SDMassChangeTIMethod m_mass_change_ti; /*!< time integrator for mass change ODE */
309  long m_num_unconverged_particles; /*!< total number of unconverged particles */
310 
311  amrex::IntVect m_coalescence_bin_size; /*!< bin size for coalescence */
312 
313  int m_distribution_grid_size; /*!< Size of 1D grid to compute distributions on */
314 
315  amrex::MultiFab m_mf_buf;
316 
317 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
318  amrex::Real m_bindist_rmin; /*!< min radius for binned distribution */
319  amrex::Real m_bindist_rmax; /*!< max radius for binned distribution */
320 
321  /*! Cell-wise mass distribution */
322  amrex::MultiFab m_mass_ln_R_mf;
323  /*! Cell-wise number distribution */
324  amrex::MultiFab m_num_ln_R_mf;
325 #endif
326 
327  /*! maximum coalescence time scale */
328  amrex::Real m_t_coalescence;
329 
330  /*! Initialization parameters objects */
331  int m_num_initializations = 1;
332  /*! vector of initializations */
333  std::vector< std::unique_ptr<SDInitialization> > m_initializations;
334 
335  /*! Injection parameters objects */
336  int m_num_injections = 0;
337  /*! vector of injections */
338  std::vector< std::unique_ptr<SDInjection> > m_injections;
339 
340  /*! sigma_0 parameter for mass distribution calculation */
341  amrex::Real m_sigma0;
342 
343  /*! place the initial SDs randomly within cells */
344  bool m_place_randomly_in_cells;
345 
346  /*! random engine */
347  std::mt19937 m_rndeng;
348 
349  /*! species index of water */
350  int m_idx_w;
351 
352  /*! inactive particles threshold */
353  amrex::Real m_deac_threshold;
354 
355  /*! save inactive particles to file */
356  bool m_save_inactive;
357 
358  /* recycled particle position bounds */
359  amrex::Real m_recyc_xmin;
360  amrex::Real m_recyc_xmax;
361  amrex::Real m_recyc_ymin;
362  amrex::Real m_recyc_ymax;
363  amrex::Real m_recyc_zmin;
364  amrex::Real m_recyc_zmax;
365 
366  /*! \brief read inputs from file */
367  virtual void readInputs () override
368  {
369  amrex::Abort("SuperDropletPC::readInputs(): Do not use this interface.");
370  }
371 
372  /*! \brief read inputs from file */
373  virtual void readInputs (const amrex::Real);
374 
375  /*! \brief Particle initialization - null (no particles are initialized) */
376  void initializeParticlesNull (const MFPtr&) { }
377 
378  private:
379 
380  /*! \brief define super-droplets */
381  void define ( const std::vector<Species::Name>&,
382  const std::vector<Species::Name>&,
383  const amrex::BoxArray&,
384  const amrex::DistributionMapping&,
385  const amrex::Real );
386 
387  /*! \brief add super-droplet method-specific particle attributes */
388  void add_superdroplet_attributes();
389 
390  /* do not use */
391  using ERFPC::massDensity;
392 
393 };
394 
395 #endif
396 #endif
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Super-droplets initial properties.
Definition: ERF_SDInitialization.H:44
Definition: ERF_MaterialProperties.H:48