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 = amrex::Real(0.147);
78  amrex::Real term = std::log(amrex::Real(1) - x * x + eps);
79  amrex::Real p1 = amrex::Real(2) / (PI * a) + term / amrex::Real(2);
80  amrex::Real p2 = term / a;
81  amrex::Real sign = (x >= 0) ? amrex::Real(1) : amrex::Real(-1);
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  /(amrex::Real(2)*params.sigma*params.sigma));
131  mult_contribution = (params.numdens * params.cell_volume) / (params.sigma * std::sqrt(amrex::Real(2)*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(amrex::Real(2) * u_trunc - amrex::Real(1)) * std::sqrt(amrex::Real(2));
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  virtual ~SDInitProperties() = default;
154 
155  using MatVec = std::vector<std::unique_ptr<MaterialProperties>>;
156 
157  /*!< Initial number of super-droplets per cell */
158  int m_ppc = 1;
159 
160  /*! Initial distribution type */
161  SDInitShape m_type = SDInitShape::uniform;
162 
163  /*!< Initial number density (m^{-3}) of physical particles */
165  /*!< Maximum multiplicity */
167 
168  /*! Minimum species mass */
169  std::vector<amrex::Real> m_mass_species_min;
170  /*! Maximum species mass */
171  std::vector<amrex::Real> m_mass_species_max;
172  /*! Mean species mass */
173  std::vector<amrex::Real> m_mass_species_mean;
174  /*! Minimum species dry radius */
175  std::vector<amrex::Real> m_radius_species_min;
176  /*! Maximum species dry radius */
177  std::vector<amrex::Real> m_radius_species_max;
178  /*! Mean species dry radius */
179  std::vector<amrex::Real> m_radius_species_mean;
180  /*! Standard deviation of species dry radius */
181  std::vector<amrex::Real> m_radius_species_geom_std;
182  /*! Initial distribution type for species */
183  std::vector<SDDistributionType> m_species_init_type;
184 
185  /*! Minimum aerosol mass */
186  std::vector<amrex::Real> m_mass_aerosol_min;
187  /*! Maximum aerosol mass */
188  std::vector<amrex::Real> m_mass_aerosol_max;
189  /*! Mean aerosol mass */
190  std::vector<amrex::Real> m_mass_aerosol_mean;
191  /*! Minimum aerosol dry radius */
192  std::vector<amrex::Real> m_radius_aerosol_min;
193  /*! Maximum aerosol dry radius */
194  std::vector<amrex::Real> m_radius_aerosol_max;
195  /*! Mean aerosol dry radius */
196  std::vector<amrex::Real> m_radius_aerosol_mean;
197  /*! Standard deviation of aerosol dry radius */
198  std::vector<amrex::Real> m_radius_aerosol_geom_std;
199  /*! Initial distribution type for aerosol */
200  std::vector<SDDistributionType> m_aerosol_init_type;
201 
202  /*! Number of species */
203  int m_num_species = 0;
204  /*! Number of aerosols */
205  int m_num_aerosols = 0;
206 
207  /*! box within which to place particles*/
208  amrex::RealBox m_particle_domain;
209  /*! Particle distribution shape parameters
210  Box shape, p1 -> lo end, p2 -> hi end
211  Bubble shape, p1 -> center, p2 -> radius */
212  amrex::Vector<amrex::Real> m_init_particle_p1;
213  amrex::Vector<amrex::Real> m_init_particle_p2;
214 
215  /*! multiplicity type */
216  SDMultiplicityType m_mult_type;
217 
218  /*! \brief Set default values for initialization parameters
219  * \param[in] a_geom Simulation geometry information
220  * \param[in] a_species_mat Vector of species material properties
221  * \param[in] a_aerosol_mat Vector of aerosol material properties
222  */
223  virtual void setDefaults ( const amrex::Geometry& a_geom,
224  const MatVec& a_species_mat,
225  const MatVec& a_aerosol_mat );
226 
227  /*! \brief Read super-droplets initialization parameters from input file
228  * \param[in] a_prefix Prefix for parameter parser
229  * \param[in] a_key Key identifier for initialization parameters
230  * \param[in] a_geom Simulation geometry information
231  * \param[in] a_species_mat Vector of species material properties
232  * \param[in] a_aerosol_mat Vector of aerosol material properties
233  */
234  virtual void readInputs ( const std::string& a_prefix,
235  const std::string& a_key,
236  const amrex::Geometry& a_geom,
237  const MatVec& a_species_mat,
238  const MatVec& a_aerosol_mat );
239 
240  /*! \brief Print super-droplets initialization parameters to screen
241  * \param[in] a_species_mat Vector of species material properties
242  * \param[in] a_aerosol_mat Vector of aerosol material properties
243  */
244  virtual void printParameters ( const MatVec& a_species_mat,
245  const MatVec& a_aerosol_mat ) const;
246 
247  /*! \brief Get a distribution with constant multiplicity
248  * \param[out] a_mass Output vector of particle masses
249  * \param[in] a_np Number of particles
250  * \param[in] a_density Density of the particle material
251  * \param[in] a_init_type Type of initialization distribution
252  * \param[in] a_mass_min Minimum mass value
253  * \param[in] a_mass_max Maximum mass value
254  * \param[in] a_mass_mean Mean mass value
255  * \param[in] a_radius_min Minimum radius value
256  * \param[in] a_radius_max Maximum radius value
257  * \param[in] a_radius_mean Mean radius value
258  * \param[in] a_radius_gstd Geometric standard deviation for radius
259  * \param[in,out] a_rng Random number generator
260  */
261  void getDistribution( amrex::Vector<amrex::Real>& a_mass,
262  int a_np,
263  amrex::Real a_density,
264  SDDistributionType a_init_type,
265  amrex::Real a_mass_min,
266  amrex::Real a_mass_max,
267  amrex::Real a_mass_mean,
268  amrex::Real a_radius_min,
269  amrex::Real a_radius_max,
270  amrex::Real a_radius_mean,
271  amrex::Real a_radius_gstd,
272  std::mt19937& a_rng ) const;
273 
274  /*! \brief Get a distribution with sampled multiplicity
275  * \param[out] a_mass Output vector of particle masses
276  * \param[out] a_mult Output vector of particle multiplicities
277  * \param[in] a_dV Cell volume
278  * \param[in] a_np Number of particles
279  * \param[in] a_density Density of the particle material
280  * \param[in] a_init_type Type of initialization distribution
281  * \param[in] a_mass_min Minimum mass value
282  * \param[in] a_mass_max Maximum mass value
283  * \param[in] a_mass_mean Mean mass value
284  * \param[in] a_radius_min Minimum radius value
285  * \param[in] a_radius_max Maximum radius value
286  * \param[in] a_radius_mean Mean radius value
287  * \param[in] a_radius_gstd Geometric standard deviation for radius
288  * \param[in,out] a_rng Random number generator
289  */
290  void getDistribution( amrex::Vector<amrex::Real>& a_mass,
291  amrex::Vector<amrex::Real>& a_mult,
292  amrex::Real a_dV,
293  int a_np,
294  amrex::Real a_density,
295  SDDistributionType a_init_type,
296  amrex::Real a_mass_min,
297  amrex::Real a_mass_max,
298  amrex::Real a_mass_mean,
299  amrex::Real a_radius_min,
300  amrex::Real a_radius_max,
301  amrex::Real a_radius_mean,
302  amrex::Real a_radius_gstd,
303  std::mt19937& a_rng ) const;
304 
305  /*! \brief Compute the aerosol mass distribution
306  * \param[out] a_mass Output vector of aerosol masses
307  * \param[in] a_idx Aerosol species index
308  * \param[in] a_np Number of particles
309  * \param[in] a_density Density of the aerosol material
310  * \param[in,out] a_rng Random number generator
311  */
312  void getAerosolDistribution ( amrex::Vector<amrex::Real>& a_mass,
313  const int a_idx,
314  const int a_np,
315  const amrex::Real a_density,
316  std::mt19937& a_rng ) const
317  {
318  getDistribution( a_mass,
319  a_np,
320  a_density,
321  m_aerosol_init_type[a_idx],
322  m_mass_aerosol_min[a_idx],
323  m_mass_aerosol_max[a_idx],
324  m_mass_aerosol_mean[a_idx],
325  m_radius_aerosol_min[a_idx],
326  m_radius_aerosol_max[a_idx],
327  m_radius_aerosol_mean[a_idx],
329  a_rng);
330  }
331 
332  /*! \brief Compute the aerosol mass distribution with sampled multiplicity
333  * \param[out] a_mass Output vector of aerosol masses
334  * \param[out] a_mult Output vector of particle multiplicities
335  * \param[in] a_dV Cell volume for scaling multiplicity
336  * \param[in] a_idx Aerosol species index
337  * \param[in] a_np Number of particles to generate
338  * \param[in] a_density Density of the aerosol material
339  * \param[in,out] a_rng Random number generator
340  */
341  void getAerosolDistribution ( amrex::Vector<amrex::Real>& a_mass,
342  amrex::Vector<amrex::Real>& a_mult,
343  amrex::Real a_dV,
344  int a_idx,
345  int a_np,
346  amrex::Real a_density,
347  std::mt19937& a_rng ) const
348  {
349  getDistribution( a_mass,
350  a_mult,
351  a_dV,
352  a_np,
353  a_density,
354  m_aerosol_init_type[a_idx],
355  m_mass_aerosol_min[a_idx],
356  m_mass_aerosol_max[a_idx],
357  m_mass_aerosol_mean[a_idx],
358  m_radius_aerosol_min[a_idx],
359  m_radius_aerosol_max[a_idx],
360  m_radius_aerosol_mean[a_idx],
362  a_rng);
363  }
364 
365  /*! \brief Compute the species mass distribution with constant multiplicity
366  * \param[out] a_mass Output vector of species masses
367  * \param[in] a_idx Species index
368  * \param[in] a_np Number of particles to generate
369  * \param[in] a_density Density of the species material
370  * \param[in,out] a_rng Random number generator
371  */
372  void getSpeciesDistribution ( amrex::Vector<amrex::Real>& a_mass,
373  const int a_idx,
374  const int a_np,
375  const amrex::Real a_density,
376  std::mt19937& a_rng ) const
377  {
378  getDistribution( a_mass,
379  a_np,
380  a_density,
381  m_species_init_type[a_idx],
382  m_mass_species_min[a_idx],
383  m_mass_species_max[a_idx],
384  m_mass_species_mean[a_idx],
385  m_radius_species_min[a_idx],
386  m_radius_species_max[a_idx],
387  m_radius_species_mean[a_idx],
389  a_rng);
390  }
391 
392  /*! \brief Compute the species mass distribution with sampled multiplicity
393  * \param[out] a_mass Output vector of species masses
394  * \param[out] a_mult Output vector of particle multiplicities
395  * \param[in] a_dV Cell volume for scaling multiplicity
396  * \param[in] a_idx Species index
397  * \param[in] a_np Number of particles to generate
398  * \param[in] a_density Density of the species material
399  * \param[in,out] a_rng Random number generator
400  */
401  void getSpeciesDistribution ( amrex::Vector<amrex::Real>& a_mass,
402  amrex::Vector<amrex::Real>& a_mult,
403  amrex::Real a_dV,
404  int a_idx,
405  int a_np,
406  amrex::Real a_density,
407  std::mt19937& a_rng ) const
408  {
409  getDistribution( a_mass,
410  a_mult,
411  a_dV,
412  a_np,
413  a_density,
414  m_species_init_type[a_idx],
415  m_mass_species_min[a_idx],
416  m_mass_species_max[a_idx],
417  m_mass_species_mean[a_idx],
418  m_radius_species_min[a_idx],
419  m_radius_species_max[a_idx],
420  m_radius_species_mean[a_idx],
422  a_rng);
423  }
424 
425  /*! \brief Get GPU-compatible distribution parameters for a species
426  * \param[in] a_idx Species index
427  * \param[in] a_density Density of the species material
428  * \param[in] a_cell_volume Cell volume for multiplicity scaling
429  * \param[in] a_sampled_mult Whether using sampled multiplicity mode
430  * \return SDDistributionParams structure for GPU use
431  */
433  int a_idx,
434  amrex::Real a_density,
435  amrex::Real a_cell_volume,
436  bool a_sampled_mult) const
437  {
438  return makeDistributionParams(
439  m_species_init_type[a_idx],
440  m_mass_species_min[a_idx],
441  m_mass_species_max[a_idx],
442  m_mass_species_mean[a_idx],
443  m_radius_species_min[a_idx],
444  m_radius_species_max[a_idx],
445  m_radius_species_mean[a_idx],
447  a_density,
448  a_cell_volume,
449  a_sampled_mult);
450  }
451 
452  /*! \brief Get GPU-compatible distribution parameters for an aerosol
453  * \param[in] a_idx Aerosol species index
454  * \param[in] a_density Density of the aerosol material
455  * \param[in] a_cell_volume Cell volume for multiplicity scaling
456  * \param[in] a_sampled_mult Whether using sampled multiplicity mode
457  * \return SDDistributionParams structure for GPU use
458  */
460  int a_idx,
461  amrex::Real a_density,
462  amrex::Real a_cell_volume,
463  bool a_sampled_mult) const
464  {
465  return makeDistributionParams(
466  m_aerosol_init_type[a_idx],
467  m_mass_aerosol_min[a_idx],
468  m_mass_aerosol_max[a_idx],
469  m_mass_aerosol_mean[a_idx],
470  m_radius_aerosol_min[a_idx],
471  m_radius_aerosol_max[a_idx],
472  m_radius_aerosol_mean[a_idx],
474  a_density,
475  a_cell_volume,
476  a_sampled_mult);
477  }
478 
479  /*! \brief Create GPU-compatible distribution parameters structure
480  * \param[in] a_init_type Distribution type
481  * \param[in] a_mass_min Minimum mass
482  * \param[in] a_mass_max Maximum mass
483  * \param[in] a_mass_mean Mean mass
484  * \param[in] a_radius_min Minimum radius
485  * \param[in] a_radius_max Maximum radius
486  * \param[in] a_radius_mean Mean radius
487  * \param[in] a_radius_gstd Geometric standard deviation
488  * \param[in] a_density Material density
489  * \param[in] a_cell_volume Cell volume
490  * \param[in] a_sampled_mult Whether using sampled multiplicity mode
491  * \return SDDistributionParams structure
492  */
494  SDDistributionType a_init_type,
495  amrex::Real a_mass_min,
496  amrex::Real a_mass_max,
497  amrex::Real a_mass_mean,
498  amrex::Real a_radius_min,
499  amrex::Real a_radius_max,
500  amrex::Real a_radius_mean,
501  amrex::Real a_radius_gstd,
502  amrex::Real a_density,
503  amrex::Real a_cell_volume,
504  bool a_sampled_mult) const;
505 
506  /*! \brief Determine whether multiplicity is sampled or constant
507  * \return True if multiplicity is sampled, false if constant
508  */
509  [[nodiscard]] inline bool sampledMultiplicity() const
510  {
511  return (m_mult_type == SDMultiplicityType::sampled);
512  }
513 
514  /*! \brief Calculate the volume of the particle domain
515  *
516  * For uniform distribution type, returns the box volume.
517  * For bubble distribution type, returns the volume of the bubble.
518  *
519  * \return Volume of the particle domain in cubic meters
520  */
521  [[nodiscard]] inline amrex::Real volume() const
522  {
523  amrex::Real vol = zero;
524  if (m_type == SDInitShape::uniform) {
525  vol = m_particle_domain.volume();
526  } else if (m_type == SDInitShape::bubble) {
527  const auto& radius = m_particle_domain.hi();
528  vol = four_thirds_pi*radius[0]*radius[1]*radius[2];
529  }
530  return vol;
531  }
532 
533  virtual int numSDPerCell (const amrex::Real) const = 0;
534  virtual amrex::Real numParticlesPerCell (const amrex::Real) const = 0;
535 };
536 
537 /*! \brief Super-droplets initialization structure */
539 {
540  public:
541 
542  virtual ~SDInjection() = default;
543 
544  /*!< Injection rate (number of physical particles per meter^3 second) */
546  /*!< Injection rate (number of SDs per meter^3 second) */
548 
549  /*!< Initial number density of super-droplets */
551 
552  /*!< Injection domain velocity */
553  amrex::Vector<amrex::Real> m_domain_vel = {zero,zero,zero};
554 
555  /*!< Start time for injection */
557 
558  /*!< Stop time for injection */
560 
561  /*! \brief Update time-dependent quantities for particle injection
562  *
563  * This function updates:
564  * 1. Number density based on injection rate and timestep
565  * 2. Super-droplet number density based on SD injection rate
566  * 3. Position of the injection domain based on domain velocity
567  *
568  * \param[in] a_dt Timestep size in seconds
569  */
570  inline void updateDt (const amrex::Real a_dt)
571  {
572  this->m_numdens = m_inj_rate * a_dt;
573  m_numdens_sd = (m_sd_inj_rate>0 ? std::max(m_sd_inj_rate*a_dt, one) : -1);
574 
575  if (this->m_type == SDInitShape::uniform) {
576  amrex::Vector<amrex::Real> lo = {zero, zero, zero};
577  amrex::Vector<amrex::Real> hi = {zero, zero, zero};
578  for (int dir = 0; dir < AMREX_SPACEDIM; dir++) {
579  lo[dir] = this->m_particle_domain.lo(dir) + m_domain_vel[dir] * a_dt;
580  hi[dir] = this->m_particle_domain.hi(dir) + m_domain_vel[dir] * a_dt;
581  }
582  this->m_particle_domain.setLo(lo);
583  this->m_particle_domain.setHi(hi);
584  } else if (m_type == SDInitShape::bubble) {
585  amrex::Vector<amrex::Real> center = {zero, zero, zero};
586  for (int dir = 0; dir < AMREX_SPACEDIM; dir++) {
587  center[dir] = this->m_particle_domain.lo(dir) + m_domain_vel[dir] * a_dt;
588  }
589  this->m_particle_domain.setLo(center);
590  }
591  }
592 
593  /*! read super-droplets injection parameters */
594  void readInputs ( const std::string&,
595  const std::string&,
596  const amrex::Geometry&,
597  const MatVec&,
598  const MatVec& ) override
599  {
600  amrex::Abort("SDInjection::readInputs(): Do not use this interface");
601  }
602 
603  /*! \brief Read super-droplet injection parameters from input file
604  *
605  * This function reads injection-specific parameters like injection rate,
606  * timing parameters, and domain velocity.
607  *
608  * \param[in] a_prefix Prefix for parameter parser
609  * \param[in] a_geom Simulation geometry information
610  * \param[in] a_species_mat Vector of species material properties
611  * \param[in] a_aerosol_mat Vector of aerosol material properties
612  * \param[in] a_dt Current timestep size
613  */
614  void readInputs ( const std::string& a_prefix,
615  const amrex::Geometry& a_geom,
616  const MatVec& a_species_mat,
617  const MatVec& a_aerosol_mat,
618  const amrex::Real a_dt );
619 
620  /*! print super-droplets injection parameters to screen */
621  void printParameters ( const MatVec&, const MatVec& ) const override;
622 
623  /*! \brief Compute number of super-droplets to inject per grid cell
624  *
625  * Determines the number of super-droplets to inject based on either:
626  * 1. The super-droplet number density and cell volume, or
627  * 2. A constant number per cell (m_ppc) if number density is not set
628  *
629  * \param[in] a_dv Volume of the grid cell
630  * \return Number of super-droplets to inject in this cell
631  */
632  [[nodiscard]] inline int numSDPerCell (const amrex::Real a_dv) const override
633  {
634  int num_sd_per_cell = 0;
635  if (m_numdens_sd >= 0) {
636  num_sd_per_cell = static_cast<int>(std::ceil(m_numdens_sd*a_dv));
637  } else {
638  num_sd_per_cell = this->m_ppc;
639  }
640  return num_sd_per_cell;
641  }
642 
643  /*! Compute number of physical particles per grid cell */
644  [[nodiscard]] inline amrex::Real numParticlesPerCell (const amrex::Real a_dv) const override
645  {
646  amrex::Real num_par_per_cell = zero;
647  if (this->m_numdens >= 0) {
648  num_par_per_cell = std::ceil(this->m_numdens*a_dv);
649  } else {
650  num_par_per_cell = 1;
651  }
652  return num_par_per_cell;
653  }
654 
655 };
656 
657 /*! \brief Super-droplets initialization structure */
659 {
660  public:
661 
662  virtual ~SDInitialization() = default;
663 
664  /*!< Initial number density of super-droplets */
666 
667  /*! read super-droplets initialization parameters */
668  void readInputs ( const std::string&,
669  const std::string&,
670  const amrex::Geometry&,
671  const MatVec&,
672  const MatVec& ) override
673  {
674  amrex::Abort("SDInjection::readInputs(): Do not use this interface");
675  }
676 
677  /*! \brief Read super-droplet initialization parameters from input file
678  *
679  * This function reads initialization-specific parameters including
680  * distribution types, particle counts, and sizing parameters.
681  *
682  * \param[in] a_prefix Prefix for parameter parser
683  * \param[in] a_geom Simulation geometry information
684  * \param[in] a_species_mat Vector of species material properties
685  * \param[in] a_aerosol_mat Vector of aerosol material properties
686  */
687  void readInputs ( const std::string& a_prefix,
688  const amrex::Geometry& a_geom,
689  const MatVec& a_species_mat,
690  const MatVec& a_aerosol_mat );
691 
692  /*! print super-droplets initialization parameters to screen */
693  void printParameters ( const MatVec&, const MatVec& ) const override;
694 
695  /*! Compute number of super-droplets per grid cell */
696  [[nodiscard]] inline int numSDPerCell (const amrex::Real a_dv) const override
697  {
698  int num_sd_per_cell = 0;
699  if (m_numdens_sd_init >= 0) {
700  num_sd_per_cell = static_cast<int>(std::ceil(m_numdens_sd_init*a_dv));
701  } else {
702  num_sd_per_cell = this->m_ppc;
703  }
704  return num_sd_per_cell;
705  }
706 
707  /*! Compute number of physical particles per grid cell */
708  [[nodiscard]] inline amrex::Real numParticlesPerCell (const amrex::Real a_dv) const override
709  {
710  amrex::Real num_par_per_cell = zero;
711  if (this->m_numdens >= 0) {
712  num_par_per_cell = std::ceil(this->m_numdens*a_dv);
713  } else {
714  num_par_per_cell = 1;
715  }
716  return num_par_per_cell;
717  }
718 
719 };
720 
721 #endif
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real PI
Definition: ERF_Constants.H:37
constexpr amrex::Real four_thirds_pi
Definition: ERF_Constants.H:39
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:164
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:312
amrex::Real volume() const
Calculate the volume of the particle domain.
Definition: ERF_SDInitialization.H:521
bool sampledMultiplicity() const
Determine whether multiplicity is sampled or constant.
Definition: ERF_SDInitialization.H:509
std::vector< amrex::Real > m_radius_aerosol_geom_std
Definition: ERF_SDInitialization.H:198
std::vector< amrex::Real > m_radius_species_max
Definition: ERF_SDInitialization.H:177
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:341
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:432
SDMultiplicityType m_mult_type
Definition: ERF_SDInitialization.H:216
SDInitShape m_type
Definition: ERF_SDInitialization.H:161
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:212
int m_num_species
Definition: ERF_SDInitialization.H:203
std::vector< SDDistributionType > m_species_init_type
Definition: ERF_SDInitialization.H:183
std::vector< amrex::Real > m_mass_species_max
Definition: ERF_SDInitialization.H:171
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:179
int m_ppc
Definition: ERF_SDInitialization.H:158
amrex::Vector< amrex::Real > m_init_particle_p2
Definition: ERF_SDInitialization.H:213
std::vector< amrex::Real > m_radius_aerosol_min
Definition: ERF_SDInitialization.H:192
int m_num_aerosols
Definition: ERF_SDInitialization.H:205
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:401
std::vector< amrex::Real > m_radius_aerosol_max
Definition: ERF_SDInitialization.H:194
std::vector< amrex::Real > m_radius_species_geom_std
Definition: ERF_SDInitialization.H:181
virtual ~SDInitProperties()=default
std::vector< amrex::Real > m_mass_species_min
Definition: ERF_SDInitialization.H:169
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:459
virtual int numSDPerCell(const amrex::Real) const =0
std::vector< SDDistributionType > m_aerosol_init_type
Definition: ERF_SDInitialization.H:200
amrex::Real m_max_multiplicity
Definition: ERF_SDInitialization.H:166
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:173
std::vector< amrex::Real > m_radius_aerosol_mean
Definition: ERF_SDInitialization.H:196
std::vector< amrex::Real > m_radius_species_min
Definition: ERF_SDInitialization.H:175
virtual amrex::Real numParticlesPerCell(const amrex::Real) const =0
std::vector< amrex::Real > m_mass_aerosol_min
Definition: ERF_SDInitialization.H:186
std::vector< std::unique_ptr< MaterialProperties > > MatVec
Definition: ERF_SDInitialization.H:157
std::vector< amrex::Real > m_mass_aerosol_mean
Definition: ERF_SDInitialization.H:190
std::vector< amrex::Real > m_mass_aerosol_max
Definition: ERF_SDInitialization.H:188
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:208
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:372
Super-droplets initialization structure.
Definition: ERF_SDInitialization.H:659
amrex::Real m_numdens_sd_init
Definition: ERF_SDInitialization.H:665
int numSDPerCell(const amrex::Real a_dv) const override
Definition: ERF_SDInitialization.H:696
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:668
amrex::Real numParticlesPerCell(const amrex::Real a_dv) const override
Definition: ERF_SDInitialization.H:708
Super-droplets initialization structure.
Definition: ERF_SDInitialization.H:539
amrex::Real m_numdens_sd
Definition: ERF_SDInitialization.H:550
amrex::Real m_tstop
Definition: ERF_SDInitialization.H:559
amrex::Real m_sd_inj_rate
Definition: ERF_SDInitialization.H:547
amrex::Real m_tstart
Definition: ERF_SDInitialization.H:556
void updateDt(const amrex::Real a_dt)
Update time-dependent quantities for particle injection.
Definition: ERF_SDInitialization.H:570
void readInputs(const std::string &, const std::string &, const amrex::Geometry &, const MatVec &, const MatVec &) override
Definition: ERF_SDInitialization.H:594
void printParameters(const MatVec &, const MatVec &) const override
Definition: ERF_SDInitialization.cpp:337
amrex::Real m_inj_rate
Definition: ERF_SDInitialization.H:545
int numSDPerCell(const amrex::Real a_dv) const override
Compute number of super-droplets to inject per grid cell.
Definition: ERF_SDInitialization.H:632
virtual ~SDInjection()=default
amrex::Real numParticlesPerCell(const amrex::Real a_dv) const override
Definition: ERF_SDInitialization.H:644
amrex::Vector< amrex::Real > m_domain_vel
Definition: ERF_SDInitialization.H:553
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