ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SDInitialization.H
Go to the documentation of this file.
1 #ifndef SDINIT_H_
2 #define SDINIT_H_
3 
4 #include <string>
5 #include <vector>
6 #include <random>
7 
8 #include <AMReX_ParmParse.H>
9 #include <AMReX_Enum.H>
10 #include <AMReX_REAL.H>
11 #include <AMReX_RealBox.H>
12 #include <AMReX_Geometry.H>
13 #include <AMReX_Random.H>
14 #include <AMReX_GpuContainers.H>
15 
16 #include "ERF_Constants.H"
17 #include "ERF_MaterialProperties.H"
18 
19 AMREX_ENUM(SDInitShape,
20  uniform,
21  bubble,
22  null
23 );
24 
25 /*! \brief Distribution type enum for GPU compatibility */
26 AMREX_ENUM(SDDistributionType,
27  mass_constant,
28  mass_exponential,
29  radius_log_normal,
30  radius_lognormal_autorange
31 );
32 
33 /*! \brief List of super-droplet initializations */
34 namespace SupDropInit
35 {
36  /*! Maximum number of vapour/condensate species */
37  const int num_species_max = 10;
38 
39  /*! Maximum number of aerosols */
40  const int num_aerosols_max = 8;
41 }
42 
43 AMREX_ENUM(SDMultiplicityType,
44  constant, sampled
45 );
46 
47 /*! \brief GPU-compatible structure holding distribution parameters */
49  SDDistributionType dist_type; /*!< Type of distribution */
50  amrex::Real mass_min; /*!< Minimum mass */
51  amrex::Real mass_max; /*!< Maximum mass */
52  amrex::Real mass_mean; /*!< Mean mass */
53  amrex::Real radius_min; /*!< Minimum radius */
54  amrex::Real radius_max; /*!< Maximum radius */
55  amrex::Real radius_mean; /*!< Mean radius (mu for log-normal) */
56  amrex::Real radius_gstd; /*!< Geometric std dev for radius */
57  amrex::Real density; /*!< Material density */
58  amrex::Real numdens; /*!< Number density for multiplicity */
59  amrex::Real cell_volume; /*!< Cell volume for multiplicity scaling */
60  // Pre-computed values for log-normal CDF inversion (truncated distribution)
61  amrex::Real cdf_min; /*!< CDF at radius_min */
62  amrex::Real cdf_max; /*!< CDF at radius_max */
63  amrex::Real sigma; /*!< log(radius_gstd) */
64  amrex::Real lnrng; /*!< log(radius_max) - log(radius_min) */
65  amrex::Real lnmin; /*!< log(radius_min) or log(mass_min) */
66  amrex::Real delta; /*!< mass_mean - mass_min for exponential */
67  int sampled_mult; /*!< 1 if sampled multiplicity, 0 if constant */
68 };
69 
70 /*! \brief Inverse error function approximation for GPU
71  * \param[in] x Input value in (-1, 1)
72  * \return Approximate inverse error function value
73  */
74 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
76  amrex::Real a = 0.147;
78  amrex::Real term = std::log(1 - x * x + eps);
79  amrex::Real p1 = 2 / (PI * a) + term / 2.0;
80  amrex::Real p2 = term / a;
81  amrex::Real sign = (x >= 0) ? 1.0 : -1.0;
82  return sign * std::sqrt(std::sqrt(p1 * p1 - p2) - p1);
83 }
84 
85 /*! \brief Generate mass from distribution parameters on GPU
86  * \param[in] params Distribution parameters
87  * \param[in] engine Random engine
88  * \param[out] mult_contribution Contribution to multiplicity (added, not set)
89  * \return Generated mass value
90  */
91 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
93  const amrex::RandomEngine& engine,
94  amrex::Real& mult_contribution)
95 {
96  using amrex::Random;
97  amrex::Real mass = 0.0;
98  amrex::Real u = Random(engine);
99 
100  switch (params.dist_type) {
101  case SDDistributionType::mass_constant:
102  mass = params.mass_mean;
103  mult_contribution = u; // Random [0,1] for later rescaling
104  break;
105 
106  case SDDistributionType::mass_exponential: {
107  if (params.sampled_mult) {
108  // Sampled multiplicity: sample uniformly in log-space, weight by exponential PDF
109  amrex::Real lnval = params.lnmin + u * params.lnrng;
110  mass = std::exp(lnval);
111  mult_contribution = (params.numdens * params.cell_volume) * std::exp(-mass / params.delta);
112  } else {
113  // Constant multiplicity: true exponential distribution via inverse transform
114  // If U ~ Uniform(0,1), then -delta*ln(U) ~ Exponential(1/delta)
115  mass = -params.delta * std::log(u) + params.mass_min;
116  mult_contribution = 0.0; // Not used for constant multiplicity
117  }
118  break;
119  }
120 
121  case SDDistributionType::radius_log_normal:
122  case SDDistributionType::radius_lognormal_autorange: {
123  amrex::Real dry_r;
124  if (params.sampled_mult) {
125  // Sampled multiplicity: sample uniformly in log-space, weight by log-normal PDF
126  amrex::Real lnval = params.lnmin + u * params.lnrng;
127  dry_r = std::exp(lnval);
128  // Log-normal PDF contribution for multiplicity weighting
129  amrex::Real term = std::exp(-std::log(dry_r/params.radius_mean)*std::log(dry_r/params.radius_mean)
130  /(2.0*params.sigma*params.sigma));
131  mult_contribution = (params.numdens * params.cell_volume) / (params.sigma * std::sqrt(2.0*PI)) * term;
132  } else {
133  // Constant multiplicity: true log-normal via inverse CDF
134  // Map u from [0,1] to [cdf_min, cdf_max] for truncated distribution
135  amrex::Real u_trunc = params.cdf_min + u * (params.cdf_max - params.cdf_min);
136  // Inverse CDF: r = mu * exp(sigma * sqrt(2) * erfinv(2*u - 1))
137  amrex::Real z = SD_erfinv_gpu(2.0 * u_trunc - 1.0) * std::sqrt(2.0);
138  dry_r = params.radius_mean * std::exp(params.sigma * z);
139  mult_contribution = 0.0; // Not used for constant multiplicity
140  }
141  mass = four_thirds_pi * dry_r * dry_r * dry_r * params.density;
142  break;
143  }
144  }
145  return mass;
146 }
147 
148 /*! \brief Super-droplets initial properties */
150 {
151  public:
152 
153  using MatVec = std::vector<std::unique_ptr<MaterialProperties>>;
154 
155  /*!< Initial number of super-droplets per cell */
156  int m_ppc = 1;
157 
158  /*! Initial distribution type */
159  SDInitShape m_type = SDInitShape::uniform;
160 
161  /*!< Initial number density (m^{-3}) of physical particles */
163  /*!< Maximum multiplicity */
165 
166  /*! Minimum species mass */
167  std::vector<amrex::Real> m_mass_species_min;
168  /*! Maximum species mass */
169  std::vector<amrex::Real> m_mass_species_max;
170  /*! Mean species mass */
171  std::vector<amrex::Real> m_mass_species_mean;
172  /*! Minimum species dry radius */
173  std::vector<amrex::Real> m_radius_species_min;
174  /*! Maximum species dry radius */
175  std::vector<amrex::Real> m_radius_species_max;
176  /*! Mean species dry radius */
177  std::vector<amrex::Real> m_radius_species_mean;
178  /*! Standard deviation of species dry radius */
179  std::vector<amrex::Real> m_radius_species_geom_std;
180  /*! Initial distribution type for species */
181  std::vector<SDDistributionType> m_species_init_type;
182 
183  /*! Minimum aerosol mass */
184  std::vector<amrex::Real> m_mass_aerosol_min;
185  /*! Maximum aerosol mass */
186  std::vector<amrex::Real> m_mass_aerosol_max;
187  /*! Mean aerosol mass */
188  std::vector<amrex::Real> m_mass_aerosol_mean;
189  /*! Minimum aerosol dry radius */
190  std::vector<amrex::Real> m_radius_aerosol_min;
191  /*! Maximum aerosol dry radius */
192  std::vector<amrex::Real> m_radius_aerosol_max;
193  /*! Mean aerosol dry radius */
194  std::vector<amrex::Real> m_radius_aerosol_mean;
195  /*! Standard deviation of aerosol dry radius */
196  std::vector<amrex::Real> m_radius_aerosol_geom_std;
197  /*! Initial distribution type for aerosol */
198  std::vector<SDDistributionType> m_aerosol_init_type;
199 
200  /*! Number of species */
201  int m_num_species = 0;
202  /*! Number of aerosols */
203  int m_num_aerosols = 0;
204 
205  /*! box within which to place particles*/
206  amrex::RealBox m_particle_domain;
207  /*! Particle distribution shape parameters
208  Box shape, p1 -> lo end, p2 -> hi end
209  Bubble shape, p1 -> center, p2 -> radius */
210  amrex::Vector<amrex::Real> m_init_particle_p1;
211  amrex::Vector<amrex::Real> m_init_particle_p2;
212 
213  /*! multiplicity type */
214  SDMultiplicityType m_mult_type;
215 
216  /*! \brief Set default values for initialization parameters
217  * \param[in] a_geom Simulation geometry information
218  * \param[in] a_species_mat Vector of species material properties
219  * \param[in] a_aerosol_mat Vector of aerosol material properties
220  */
221  virtual void setDefaults ( const amrex::Geometry& a_geom,
222  const MatVec& a_species_mat,
223  const MatVec& a_aerosol_mat );
224 
225  /*! \brief Read super-droplets initialization parameters from input file
226  * \param[in] a_prefix Prefix for parameter parser
227  * \param[in] a_key Key identifier for initialization parameters
228  * \param[in] a_geom Simulation geometry information
229  * \param[in] a_species_mat Vector of species material properties
230  * \param[in] a_aerosol_mat Vector of aerosol material properties
231  */
232  virtual void readInputs ( const std::string& a_prefix,
233  const std::string& a_key,
234  const amrex::Geometry& a_geom,
235  const MatVec& a_species_mat,
236  const MatVec& a_aerosol_mat );
237 
238  /*! \brief Print super-droplets initialization parameters to screen
239  * \param[in] a_species_mat Vector of species material properties
240  * \param[in] a_aerosol_mat Vector of aerosol material properties
241  */
242  virtual void printParameters ( const MatVec& a_species_mat,
243  const MatVec& a_aerosol_mat ) const;
244 
245  /*! \brief Get a distribution with constant multiplicity
246  * \param[out] a_mass Output vector of particle masses
247  * \param[in] a_np Number of particles
248  * \param[in] a_density Density of the particle material
249  * \param[in] a_init_type Type of initialization distribution
250  * \param[in] a_mass_min Minimum mass value
251  * \param[in] a_mass_max Maximum mass value
252  * \param[in] a_mass_mean Mean mass value
253  * \param[in] a_radius_min Minimum radius value
254  * \param[in] a_radius_max Maximum radius value
255  * \param[in] a_radius_mean Mean radius value
256  * \param[in] a_radius_gstd Geometric standard deviation for radius
257  * \param[in,out] a_rng Random number generator
258  */
259  void getDistribution( amrex::Vector<amrex::Real>& a_mass,
260  int a_np,
261  amrex::Real a_density,
262  SDDistributionType a_init_type,
263  amrex::Real a_mass_min,
264  amrex::Real a_mass_max,
265  amrex::Real a_mass_mean,
266  amrex::Real a_radius_min,
267  amrex::Real a_radius_max,
268  amrex::Real a_radius_mean,
269  amrex::Real a_radius_gstd,
270  std::mt19937& a_rng ) const;
271 
272  /*! \brief Get a distribution with sampled multiplicity
273  * \param[out] a_mass Output vector of particle masses
274  * \param[out] a_mult Output vector of particle multiplicities
275  * \param[in] a_dV Cell volume
276  * \param[in] a_np Number of particles
277  * \param[in] a_density Density of the particle material
278  * \param[in] a_init_type Type of initialization distribution
279  * \param[in] a_mass_min Minimum mass value
280  * \param[in] a_mass_max Maximum mass value
281  * \param[in] a_mass_mean Mean mass value
282  * \param[in] a_radius_min Minimum radius value
283  * \param[in] a_radius_max Maximum radius value
284  * \param[in] a_radius_mean Mean radius value
285  * \param[in] a_radius_gstd Geometric standard deviation for radius
286  * \param[in,out] a_rng Random number generator
287  */
288  void getDistribution( amrex::Vector<amrex::Real>& a_mass,
289  amrex::Vector<amrex::Real>& a_mult,
290  amrex::Real a_dV,
291  int a_np,
292  amrex::Real a_density,
293  SDDistributionType a_init_type,
294  amrex::Real a_mass_min,
295  amrex::Real a_mass_max,
296  amrex::Real a_mass_mean,
297  amrex::Real a_radius_min,
298  amrex::Real a_radius_max,
299  amrex::Real a_radius_mean,
300  amrex::Real a_radius_gstd,
301  std::mt19937& a_rng ) const;
302 
303  /*! \brief Compute the aerosol mass distribution
304  * \param[out] a_mass Output vector of aerosol masses
305  * \param[in] a_idx Aerosol species index
306  * \param[in] a_np Number of particles
307  * \param[in] a_density Density of the aerosol material
308  * \param[in,out] a_rng Random number generator
309  */
310  void getAerosolDistribution ( amrex::Vector<amrex::Real>& a_mass,
311  const int a_idx,
312  const int a_np,
313  const amrex::Real a_density,
314  std::mt19937& a_rng ) const
315  {
316  getDistribution( a_mass,
317  a_np,
318  a_density,
319  m_aerosol_init_type[a_idx],
320  m_mass_aerosol_min[a_idx],
321  m_mass_aerosol_max[a_idx],
322  m_mass_aerosol_mean[a_idx],
323  m_radius_aerosol_min[a_idx],
324  m_radius_aerosol_max[a_idx],
325  m_radius_aerosol_mean[a_idx],
327  a_rng);
328  }
329 
330  /*! \brief Compute the aerosol mass distribution with sampled multiplicity
331  * \param[out] a_mass Output vector of aerosol masses
332  * \param[out] a_mult Output vector of particle multiplicities
333  * \param[in] a_dV Cell volume for scaling multiplicity
334  * \param[in] a_idx Aerosol species index
335  * \param[in] a_np Number of particles to generate
336  * \param[in] a_density Density of the aerosol material
337  * \param[in,out] a_rng Random number generator
338  */
339  void getAerosolDistribution ( amrex::Vector<amrex::Real>& a_mass,
340  amrex::Vector<amrex::Real>& a_mult,
341  amrex::Real a_dV,
342  int a_idx,
343  int a_np,
344  amrex::Real a_density,
345  std::mt19937& a_rng ) const
346  {
347  getDistribution( a_mass,
348  a_mult,
349  a_dV,
350  a_np,
351  a_density,
352  m_aerosol_init_type[a_idx],
353  m_mass_aerosol_min[a_idx],
354  m_mass_aerosol_max[a_idx],
355  m_mass_aerosol_mean[a_idx],
356  m_radius_aerosol_min[a_idx],
357  m_radius_aerosol_max[a_idx],
358  m_radius_aerosol_mean[a_idx],
360  a_rng);
361  }
362 
363  /*! \brief Compute the species mass distribution with constant multiplicity
364  * \param[out] a_mass Output vector of species masses
365  * \param[in] a_idx Species index
366  * \param[in] a_np Number of particles to generate
367  * \param[in] a_density Density of the species material
368  * \param[in,out] a_rng Random number generator
369  */
370  void getSpeciesDistribution ( amrex::Vector<amrex::Real>& a_mass,
371  const int a_idx,
372  const int a_np,
373  const amrex::Real a_density,
374  std::mt19937& a_rng ) const
375  {
376  getDistribution( a_mass,
377  a_np,
378  a_density,
379  m_species_init_type[a_idx],
380  m_mass_species_min[a_idx],
381  m_mass_species_max[a_idx],
382  m_mass_species_mean[a_idx],
383  m_radius_species_min[a_idx],
384  m_radius_species_max[a_idx],
385  m_radius_species_mean[a_idx],
387  a_rng);
388  }
389 
390  /*! \brief Compute the species mass distribution with sampled multiplicity
391  * \param[out] a_mass Output vector of species masses
392  * \param[out] a_mult Output vector of particle multiplicities
393  * \param[in] a_dV Cell volume for scaling multiplicity
394  * \param[in] a_idx Species index
395  * \param[in] a_np Number of particles to generate
396  * \param[in] a_density Density of the species material
397  * \param[in,out] a_rng Random number generator
398  */
399  void getSpeciesDistribution ( amrex::Vector<amrex::Real>& a_mass,
400  amrex::Vector<amrex::Real>& a_mult,
401  amrex::Real a_dV,
402  int a_idx,
403  int a_np,
404  amrex::Real a_density,
405  std::mt19937& a_rng ) const
406  {
407  getDistribution( a_mass,
408  a_mult,
409  a_dV,
410  a_np,
411  a_density,
412  m_species_init_type[a_idx],
413  m_mass_species_min[a_idx],
414  m_mass_species_max[a_idx],
415  m_mass_species_mean[a_idx],
416  m_radius_species_min[a_idx],
417  m_radius_species_max[a_idx],
418  m_radius_species_mean[a_idx],
420  a_rng);
421  }
422 
423  /*! \brief Get GPU-compatible distribution parameters for a species
424  * \param[in] a_idx Species index
425  * \param[in] a_density Density of the species material
426  * \param[in] a_cell_volume Cell volume for multiplicity scaling
427  * \param[in] a_sampled_mult Whether using sampled multiplicity mode
428  * \return SDDistributionParams structure for GPU use
429  */
431  int a_idx,
432  amrex::Real a_density,
433  amrex::Real a_cell_volume,
434  bool a_sampled_mult) const
435  {
436  return makeDistributionParams(
437  m_species_init_type[a_idx],
438  m_mass_species_min[a_idx],
439  m_mass_species_max[a_idx],
440  m_mass_species_mean[a_idx],
441  m_radius_species_min[a_idx],
442  m_radius_species_max[a_idx],
443  m_radius_species_mean[a_idx],
445  a_density,
446  a_cell_volume,
447  a_sampled_mult);
448  }
449 
450  /*! \brief Get GPU-compatible distribution parameters for an aerosol
451  * \param[in] a_idx Aerosol species index
452  * \param[in] a_density Density of the aerosol material
453  * \param[in] a_cell_volume Cell volume for multiplicity scaling
454  * \param[in] a_sampled_mult Whether using sampled multiplicity mode
455  * \return SDDistributionParams structure for GPU use
456  */
458  int a_idx,
459  amrex::Real a_density,
460  amrex::Real a_cell_volume,
461  bool a_sampled_mult) const
462  {
463  return makeDistributionParams(
464  m_aerosol_init_type[a_idx],
465  m_mass_aerosol_min[a_idx],
466  m_mass_aerosol_max[a_idx],
467  m_mass_aerosol_mean[a_idx],
468  m_radius_aerosol_min[a_idx],
469  m_radius_aerosol_max[a_idx],
470  m_radius_aerosol_mean[a_idx],
472  a_density,
473  a_cell_volume,
474  a_sampled_mult);
475  }
476 
477  /*! \brief Create GPU-compatible distribution parameters structure
478  * \param[in] a_init_type Distribution type
479  * \param[in] a_mass_min Minimum mass
480  * \param[in] a_mass_max Maximum mass
481  * \param[in] a_mass_mean Mean mass
482  * \param[in] a_radius_min Minimum radius
483  * \param[in] a_radius_max Maximum radius
484  * \param[in] a_radius_mean Mean radius
485  * \param[in] a_radius_gstd Geometric standard deviation
486  * \param[in] a_density Material density
487  * \param[in] a_cell_volume Cell volume
488  * \param[in] a_sampled_mult Whether using sampled multiplicity mode
489  * \return SDDistributionParams structure
490  */
492  SDDistributionType a_init_type,
493  amrex::Real a_mass_min,
494  amrex::Real a_mass_max,
495  amrex::Real a_mass_mean,
496  amrex::Real a_radius_min,
497  amrex::Real a_radius_max,
498  amrex::Real a_radius_mean,
499  amrex::Real a_radius_gstd,
500  amrex::Real a_density,
501  amrex::Real a_cell_volume,
502  bool a_sampled_mult) const;
503 
504  /*! \brief Determine whether multiplicity is sampled or constant
505  * \return True if multiplicity is sampled, false if constant
506  */
507  [[nodiscard]] inline bool sampledMultiplicity() const
508  {
509  return (m_mult_type == SDMultiplicityType::sampled);
510  }
511 
512  /*! \brief Calculate the volume of the particle domain
513  *
514  * For uniform distribution type, returns the box volume.
515  * For bubble distribution type, returns the volume of the bubble.
516  *
517  * \return Volume of the particle domain in cubic meters
518  */
519  [[nodiscard]] inline amrex::Real volume() const
520  {
521  amrex::Real vol = zero;
522  if (m_type == SDInitShape::uniform) {
523  vol = m_particle_domain.volume();
524  } else if (m_type == SDInitShape::bubble) {
525  const auto& radius = m_particle_domain.hi();
526  vol = four_thirds_pi*radius[0]*radius[1]*radius[2];
527  }
528  return vol;
529  }
530 
531  virtual int numSDPerCell (const amrex::Real) const = 0;
532  virtual amrex::Real numParticlesPerCell (const amrex::Real) const = 0;
533 };
534 
535 /*! \brief Super-droplets initialization structure */
537 {
538  public:
539 
540  virtual ~SDInjection() = default;
541 
542  /*!< Injection rate (number of physical particles per meter^3 second) */
544  /*!< Injection rate (number of SDs per meter^3 second) */
546 
547  /*!< Initial number density of super-droplets */
549 
550  /*!< Injection domain velocity */
551  amrex::Vector<amrex::Real> m_domain_vel = {zero,zero,zero};
552 
553  /*!< Start time for injection */
555 
556  /*!< Stop time for injection */
558 
559  /*! \brief Update time-dependent quantities for particle injection
560  *
561  * This function updates:
562  * 1. Number density based on injection rate and timestep
563  * 2. Super-droplet number density based on SD injection rate
564  * 3. Position of the injection domain based on domain velocity
565  *
566  * \param[in] a_dt Timestep size in seconds
567  */
568  inline void updateDt (const amrex::Real a_dt)
569  {
570  this->m_numdens = m_inj_rate * a_dt;
571  m_numdens_sd = (m_sd_inj_rate>0 ? std::max(m_sd_inj_rate*a_dt, one) : -1);
572 
573  if (this->m_type == SDInitShape::uniform) {
574  amrex::Vector<amrex::Real> lo = {zero, zero, zero};
575  amrex::Vector<amrex::Real> hi = {zero, zero, zero};
576  for (int dir = 0; dir < AMREX_SPACEDIM; dir++) {
577  lo[dir] = this->m_particle_domain.lo(dir) + m_domain_vel[dir] * a_dt;
578  hi[dir] = this->m_particle_domain.hi(dir) + m_domain_vel[dir] * a_dt;
579  }
580  this->m_particle_domain.setLo(lo);
581  this->m_particle_domain.setHi(hi);
582  } else if (m_type == SDInitShape::bubble) {
583  amrex::Vector<amrex::Real> center = {zero, zero, zero};
584  for (int dir = 0; dir < AMREX_SPACEDIM; dir++) {
585  center[dir] = this->m_particle_domain.lo(dir) + m_domain_vel[dir] * a_dt;
586  }
587  this->m_particle_domain.setLo(center);
588  }
589  }
590 
591  /*! read super-droplets injection parameters */
592  void readInputs ( const std::string&,
593  const std::string&,
594  const amrex::Geometry&,
595  const MatVec&,
596  const MatVec& ) override
597  {
598  amrex::Abort("SDInjection::readInputs(): Do not use this interface");
599  }
600 
601  /*! \brief Read super-droplet injection parameters from input file
602  *
603  * This function reads injection-specific parameters like injection rate,
604  * timing parameters, and domain velocity.
605  *
606  * \param[in] a_prefix Prefix for parameter parser
607  * \param[in] a_geom Simulation geometry information
608  * \param[in] a_species_mat Vector of species material properties
609  * \param[in] a_aerosol_mat Vector of aerosol material properties
610  * \param[in] a_dt Current timestep size
611  */
612  void readInputs ( const std::string& a_prefix,
613  const amrex::Geometry& a_geom,
614  const MatVec& a_species_mat,
615  const MatVec& a_aerosol_mat,
616  const amrex::Real a_dt );
617 
618  /*! print super-droplets injection parameters to screen */
619  void printParameters ( const MatVec&, const MatVec& ) const override;
620 
621  /*! \brief Compute number of super-droplets to inject per grid cell
622  *
623  * Determines the number of super-droplets to inject based on either:
624  * 1. The super-droplet number density and cell volume, or
625  * 2. A constant number per cell (m_ppc) if number density is not set
626  *
627  * \param[in] a_dv Volume of the grid cell
628  * \return Number of super-droplets to inject in this cell
629  */
630  [[nodiscard]] inline int numSDPerCell (const amrex::Real a_dv) const override
631  {
632  int num_sd_per_cell = 0;
633  if (m_numdens_sd >= 0) {
634  num_sd_per_cell = static_cast<int>(std::ceil(m_numdens_sd*a_dv));
635  } else {
636  num_sd_per_cell = this->m_ppc;
637  }
638  return num_sd_per_cell;
639  }
640 
641  /*! Compute number of physical particles per grid cell */
642  [[nodiscard]] inline amrex::Real numParticlesPerCell (const amrex::Real a_dv) const override
643  {
644  amrex::Real num_par_per_cell = zero;
645  if (this->m_numdens >= 0) {
646  num_par_per_cell = std::ceil(this->m_numdens*a_dv);
647  } else {
648  num_par_per_cell = 1;
649  }
650  return num_par_per_cell;
651  }
652 
653 };
654 
655 /*! \brief Super-droplets initialization structure */
657 {
658  public:
659 
660  virtual ~SDInitialization() = default;
661 
662  /*!< Initial number density of super-droplets */
664 
665  /*! read super-droplets initialization parameters */
666  void readInputs ( const std::string&,
667  const std::string&,
668  const amrex::Geometry&,
669  const MatVec&,
670  const MatVec& ) override
671  {
672  amrex::Abort("SDInjection::readInputs(): Do not use this interface");
673  }
674 
675  /*! \brief Read super-droplet initialization parameters from input file
676  *
677  * This function reads initialization-specific parameters including
678  * distribution types, particle counts, and sizing parameters.
679  *
680  * \param[in] a_prefix Prefix for parameter parser
681  * \param[in] a_geom Simulation geometry information
682  * \param[in] a_species_mat Vector of species material properties
683  * \param[in] a_aerosol_mat Vector of aerosol material properties
684  */
685  void readInputs ( const std::string& a_prefix,
686  const amrex::Geometry& a_geom,
687  const MatVec& a_species_mat,
688  const MatVec& a_aerosol_mat );
689 
690  /*! print super-droplets initialization parameters to screen */
691  void printParameters ( const MatVec&, const MatVec& ) const override;
692 
693  /*! Compute number of super-droplets per grid cell */
694  [[nodiscard]] inline int numSDPerCell (const amrex::Real a_dv) const override
695  {
696  int num_sd_per_cell = 0;
697  if (m_numdens_sd_init >= 0) {
698  num_sd_per_cell = static_cast<int>(std::ceil(m_numdens_sd_init*a_dv));
699  } else {
700  num_sd_per_cell = this->m_ppc;
701  }
702  return num_sd_per_cell;
703  }
704 
705  /*! Compute number of physical particles per grid cell */
706  [[nodiscard]] inline amrex::Real numParticlesPerCell (const amrex::Real a_dv) const override
707  {
708  amrex::Real num_par_per_cell = zero;
709  if (this->m_numdens >= 0) {
710  num_par_per_cell = std::ceil(this->m_numdens*a_dv);
711  } else {
712  num_par_per_cell = 1;
713  }
714  return num_par_per_cell;
715  }
716 
717 };
718 
719 #endif
constexpr amrex::Real one
Definition: ERF_Constants.H:7
constexpr amrex::Real zero
Definition: ERF_Constants.H:6
constexpr amrex::Real PI
Definition: ERF_Constants.H:16
constexpr amrex::Real four_thirds_pi
Definition: ERF_Constants.H:18
AMREX_ENUM(SDInitShape, uniform, bubble, null)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real SD_sample_mass_gpu(const SDDistributionParams &params, const amrex::RandomEngine &engine, amrex::Real &mult_contribution)
Generate mass from distribution parameters on GPU.
Definition: ERF_SDInitialization.H:92
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real SD_erfinv_gpu(const amrex::Real x)
Inverse error function approximation for GPU.
Definition: ERF_SDInitialization.H:75
std::vector< std::unique_ptr< MaterialProperties > > MatVec
Definition: ERF_SDInitialization.cpp:4
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Super-droplets initial properties.
Definition: ERF_SDInitialization.H:150
amrex::Real m_numdens
Definition: ERF_SDInitialization.H:162
void getAerosolDistribution(amrex::Vector< amrex::Real > &a_mass, const int a_idx, const int a_np, const amrex::Real a_density, std::mt19937 &a_rng) const
Compute the aerosol mass distribution.
Definition: ERF_SDInitialization.H:310
amrex::Real volume() const
Calculate the volume of the particle domain.
Definition: ERF_SDInitialization.H:519
bool sampledMultiplicity() const
Determine whether multiplicity is sampled or constant.
Definition: ERF_SDInitialization.H:507
std::vector< amrex::Real > m_radius_aerosol_geom_std
Definition: ERF_SDInitialization.H:196
std::vector< amrex::Real > m_radius_species_max
Definition: ERF_SDInitialization.H:175
virtual void readInputs(const std::string &a_prefix, const std::string &a_key, const amrex::Geometry &a_geom, const MatVec &a_species_mat, const MatVec &a_aerosol_mat)
Read super-droplets initialization parameters from input file.
Definition: ERF_SDInitialization.cpp:76
void getAerosolDistribution(amrex::Vector< amrex::Real > &a_mass, amrex::Vector< amrex::Real > &a_mult, amrex::Real a_dV, int a_idx, int a_np, amrex::Real a_density, std::mt19937 &a_rng) const
Compute the aerosol mass distribution with sampled multiplicity.
Definition: ERF_SDInitialization.H:339
SDDistributionParams getSpeciesDistParams(int a_idx, amrex::Real a_density, amrex::Real a_cell_volume, bool a_sampled_mult) const
Get GPU-compatible distribution parameters for a species.
Definition: ERF_SDInitialization.H:430
SDMultiplicityType m_mult_type
Definition: ERF_SDInitialization.H:214
SDInitShape m_type
Definition: ERF_SDInitialization.H:159
virtual void printParameters(const MatVec &a_species_mat, const MatVec &a_aerosol_mat) const
Print super-droplets initialization parameters to screen.
Definition: ERF_SDInitialization.cpp:248
amrex::Vector< amrex::Real > m_init_particle_p1
Definition: ERF_SDInitialization.H:210
int m_num_species
Definition: ERF_SDInitialization.H:201
std::vector< SDDistributionType > m_species_init_type
Definition: ERF_SDInitialization.H:181
std::vector< amrex::Real > m_mass_species_max
Definition: ERF_SDInitialization.H:169
SDDistributionParams makeDistributionParams(SDDistributionType a_init_type, amrex::Real a_mass_min, amrex::Real a_mass_max, amrex::Real a_mass_mean, amrex::Real a_radius_min, amrex::Real a_radius_max, amrex::Real a_radius_mean, amrex::Real a_radius_gstd, amrex::Real a_density, amrex::Real a_cell_volume, bool a_sampled_mult) const
Create GPU-compatible distribution parameters structure.
Definition: ERF_SDInitialization.cpp:513
std::vector< amrex::Real > m_radius_species_mean
Definition: ERF_SDInitialization.H:177
int m_ppc
Definition: ERF_SDInitialization.H:156
amrex::Vector< amrex::Real > m_init_particle_p2
Definition: ERF_SDInitialization.H:211
std::vector< amrex::Real > m_radius_aerosol_min
Definition: ERF_SDInitialization.H:190
int m_num_aerosols
Definition: ERF_SDInitialization.H:203
void getSpeciesDistribution(amrex::Vector< amrex::Real > &a_mass, amrex::Vector< amrex::Real > &a_mult, amrex::Real a_dV, int a_idx, int a_np, amrex::Real a_density, std::mt19937 &a_rng) const
Compute the species mass distribution with sampled multiplicity.
Definition: ERF_SDInitialization.H:399
std::vector< amrex::Real > m_radius_aerosol_max
Definition: ERF_SDInitialization.H:192
std::vector< amrex::Real > m_radius_species_geom_std
Definition: ERF_SDInitialization.H:179
std::vector< amrex::Real > m_mass_species_min
Definition: ERF_SDInitialization.H:167
SDDistributionParams getAerosolDistParams(int a_idx, amrex::Real a_density, amrex::Real a_cell_volume, bool a_sampled_mult) const
Get GPU-compatible distribution parameters for an aerosol.
Definition: ERF_SDInitialization.H:457
virtual int numSDPerCell(const amrex::Real) const =0
std::vector< SDDistributionType > m_aerosol_init_type
Definition: ERF_SDInitialization.H:198
amrex::Real m_max_multiplicity
Definition: ERF_SDInitialization.H:164
virtual void setDefaults(const amrex::Geometry &a_geom, const MatVec &a_species_mat, const MatVec &a_aerosol_mat)
Set default values for initialization parameters.
Definition: ERF_SDInitialization.cpp:6
std::vector< amrex::Real > m_mass_species_mean
Definition: ERF_SDInitialization.H:171
std::vector< amrex::Real > m_radius_aerosol_mean
Definition: ERF_SDInitialization.H:194
std::vector< amrex::Real > m_radius_species_min
Definition: ERF_SDInitialization.H:173
virtual amrex::Real numParticlesPerCell(const amrex::Real) const =0
std::vector< amrex::Real > m_mass_aerosol_min
Definition: ERF_SDInitialization.H:184
std::vector< std::unique_ptr< MaterialProperties > > MatVec
Definition: ERF_SDInitialization.H:155
std::vector< amrex::Real > m_mass_aerosol_mean
Definition: ERF_SDInitialization.H:188
std::vector< amrex::Real > m_mass_aerosol_max
Definition: ERF_SDInitialization.H:186
void getDistribution(amrex::Vector< amrex::Real > &a_mass, int a_np, amrex::Real a_density, SDDistributionType a_init_type, amrex::Real a_mass_min, amrex::Real a_mass_max, amrex::Real a_mass_mean, amrex::Real a_radius_min, amrex::Real a_radius_max, amrex::Real a_radius_mean, amrex::Real a_radius_gstd, std::mt19937 &a_rng) const
Get a distribution with constant multiplicity.
Definition: ERF_SDInitialization.cpp:351
amrex::RealBox m_particle_domain
Definition: ERF_SDInitialization.H:206
void getSpeciesDistribution(amrex::Vector< amrex::Real > &a_mass, const int a_idx, const int a_np, const amrex::Real a_density, std::mt19937 &a_rng) const
Compute the species mass distribution with constant multiplicity.
Definition: ERF_SDInitialization.H:370
Super-droplets initialization structure.
Definition: ERF_SDInitialization.H:657
amrex::Real m_numdens_sd_init
Definition: ERF_SDInitialization.H:663
int numSDPerCell(const amrex::Real a_dv) const override
Definition: ERF_SDInitialization.H:694
void printParameters(const MatVec &, const MatVec &) const override
Definition: ERF_SDInitialization.cpp:328
virtual ~SDInitialization()=default
void readInputs(const std::string &, const std::string &, const amrex::Geometry &, const MatVec &, const MatVec &) override
Definition: ERF_SDInitialization.H:666
amrex::Real numParticlesPerCell(const amrex::Real a_dv) const override
Definition: ERF_SDInitialization.H:706
Super-droplets initialization structure.
Definition: ERF_SDInitialization.H:537
amrex::Real m_numdens_sd
Definition: ERF_SDInitialization.H:548
amrex::Real m_tstop
Definition: ERF_SDInitialization.H:557
amrex::Real m_sd_inj_rate
Definition: ERF_SDInitialization.H:545
amrex::Real m_tstart
Definition: ERF_SDInitialization.H:554
void updateDt(const amrex::Real a_dt)
Update time-dependent quantities for particle injection.
Definition: ERF_SDInitialization.H:568
void readInputs(const std::string &, const std::string &, const amrex::Geometry &, const MatVec &, const MatVec &) override
Definition: ERF_SDInitialization.H:592
void printParameters(const MatVec &, const MatVec &) const override
Definition: ERF_SDInitialization.cpp:337
amrex::Real m_inj_rate
Definition: ERF_SDInitialization.H:543
int numSDPerCell(const amrex::Real a_dv) const override
Compute number of super-droplets to inject per grid cell.
Definition: ERF_SDInitialization.H:630
virtual ~SDInjection()=default
amrex::Real numParticlesPerCell(const amrex::Real a_dv) const override
Definition: ERF_SDInitialization.H:642
amrex::Vector< amrex::Real > m_domain_vel
Definition: ERF_SDInitialization.H:551
List of super-droplet initializations.
Definition: ERF_SDInitialization.H:35
const int num_aerosols_max
Definition: ERF_SDInitialization.H:40
const int num_species_max
Definition: ERF_SDInitialization.H:37
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
GPU-compatible structure holding distribution parameters.
Definition: ERF_SDInitialization.H:48
amrex::Real numdens
Definition: ERF_SDInitialization.H:58
amrex::Real mass_mean
Definition: ERF_SDInitialization.H:52
amrex::Real sigma
Definition: ERF_SDInitialization.H:63
amrex::Real delta
Definition: ERF_SDInitialization.H:66
amrex::Real cdf_max
Definition: ERF_SDInitialization.H:62
amrex::Real radius_mean
Definition: ERF_SDInitialization.H:55
amrex::Real mass_max
Definition: ERF_SDInitialization.H:51
amrex::Real lnmin
Definition: ERF_SDInitialization.H:65
amrex::Real cell_volume
Definition: ERF_SDInitialization.H:59
amrex::Real lnrng
Definition: ERF_SDInitialization.H:64
amrex::Real radius_gstd
Definition: ERF_SDInitialization.H:56
amrex::Real density
Definition: ERF_SDInitialization.H:57
amrex::Real radius_min
Definition: ERF_SDInitialization.H:53
amrex::Real radius_max
Definition: ERF_SDInitialization.H:54
int sampled_mult
Definition: ERF_SDInitialization.H:67
SDDistributionType dist_type
Definition: ERF_SDInitialization.H:49
amrex::Real cdf_min
Definition: ERF_SDInitialization.H:61
amrex::Real mass_min
Definition: ERF_SDInitialization.H:50