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"
11 #include <AMReX_StructOfArrays.H>
12 
13 class SuperDropletPC : public ERFPC
14 {
15  using MFPtr = std::unique_ptr<amrex::MultiFab>;
16  using BCTypeArr = amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2>;
17 
18  public:
19 
20  /*! \brief Constructor */
21  SuperDropletPC ( amrex::ParGDBBase* a_gdb,
22  const std::vector<Species::Name>& a_species_mat,
23  const std::vector<Species::Name>& a_aerosol_mat,
24  const amrex::Real a_dt,
25  const std::string& a_name = "super_droplets" )
26  : ERFPC (a_gdb, a_name)
27  {
28  define( a_species_mat,
29  a_aerosol_mat,
30  a_gdb->ParticleBoxArray(0),
31  a_gdb->ParticleDistributionMap(0),
32  a_dt );
33  }
34 
35  /*! \brief Constructor */
36  SuperDropletPC ( const amrex::Geometry& a_geom,
37  const amrex::DistributionMapping& a_dmap,
38  const amrex::BoxArray& a_ba,
39  const std::vector<Species::Name>& a_species_mat,
40  const std::vector<Species::Name>& a_aerosol_mat,
41  const amrex::Real a_dt,
42  const std::string& a_name = "super_droplets" )
43  : ERFPC (a_geom, a_dmap, a_ba, a_name)
44  {
45  define(a_species_mat, a_aerosol_mat, a_ba, a_dmap, a_dt);
46  }
47 
48  /*! \brief Destructor */
49  ~SuperDropletPC()
50  {
51  if (m_mass_change_logging) {
52  fclose(m_mass_change_log);
53  }
54  }
55 
56  /*! \brief Set vapour species material */
57  AMREX_FORCE_INLINE
58  virtual void setSpeciesMaterial ( const Species::Name& a_name )
59  {
60  if (a_name == Species::Name::H2O) { m_idx_w = m_species_mat.size(); }
61  m_species_mat.push_back(std::make_unique<MaterialProperties>(a_name));
62  m_device_props_initialized = false;
63  }
64 
65  /*! \brief Set species material */
66  AMREX_FORCE_INLINE
67  virtual void setSpeciesMaterial ( const std::vector<Species::Name>& a_names )
68  {
69  for (auto& name : a_names) { setSpeciesMaterial(name); }
70  }
71 
72  /*! \brief Get vapour material */
73  AMREX_FORCE_INLINE
74  virtual const MaterialProperties& getSpeciesMaterial(const Species::Name& a_name) const
75  {
76  for (auto& species : m_species_mat) {
77  if (species->m_name == a_name) { return *species; }
78  }
79  amrex::Abort("SuperDropletPC::getSpeciesMaterial() - species not found");
80  return *m_species_mat[0];
81  }
82 
83  /*! \brief Set aerosol material */
84  AMREX_FORCE_INLINE
85  virtual void setAerosolMaterial ( const Species::Name& a_name )
86  {
87  m_aerosol_mat.push_back(std::make_unique<MaterialProperties>(a_name));
88  m_device_props_initialized = false;
89  }
90 
91  /*! \brief Set aerosol material */
92  AMREX_FORCE_INLINE
93  virtual void setAerosolMaterial ( const std::vector<Species::Name>& a_names )
94  {
95  for (auto& name : a_names) { setAerosolMaterial(name); }
96  }
97 
98  /*! \brief Update device properties if material properties change */
99  void updateDeviceProperties();
100 
101  /*! \brief Setup species and aerosol mass pointers from SOA */
102  template<typename SOAType>
103  void setupMassPointers(SOAType& soa, SDPCDefn::SDSpeciesMassArr& sp_mass_ptrs,
104  SDPCDefn::SDAerosolMassArr& ae_mass_ptrs) const
105  {
106  for (int i = 0; i < m_num_species; i++) {
107  sp_mass_ptrs[i] = soa.GetRealData(idx_s(i, m_num_aerosols, m_num_species)).data();
108  }
109  for (int i = 0; i < m_num_aerosols; i++) {
110  ae_mass_ptrs[i] = soa.GetRealData(idx_a(i, m_num_aerosols, m_num_species)).data();
111  }
112  }
113 
114  /*! \brief Update particle radius and total mass from species/aerosol masses */
115  AMREX_GPU_DEVICE AMREX_FORCE_INLINE
116  static void updateParticleAttributes(
117  int particle_idx,
118  amrex::ParticleReal* radius_ptr,
119  amrex::ParticleReal* mass_ptr,
120  int idx_w,
121  amrex::ParticleReal rho_w,
122  int num_sp, int num_ae,
123  const int* sp_sol_arr,
124  const int* ae_sol_arr,
125  const SDPCDefn::SDSpeciesMassArr sp_mass_ptrs,
126  const SDPCDefn::SDAerosolMassArr ae_mass_ptrs,
127  const amrex::ParticleReal* sp_rho_arr,
128  const amrex::ParticleReal* ae_rho_arr)
129  {
130  // Update effective radius
131  radius_ptr[particle_idx] = SD_effective_radius(
132  particle_idx, idx_w, rho_w,
133  num_sp, num_ae,
134  sp_sol_arr, ae_sol_arr,
135  sp_mass_ptrs, ae_mass_ptrs,
136  sp_rho_arr, ae_rho_arr);
137 
138  // Update total mass
139  mass_ptr[particle_idx] = SD_total_mass(
140  particle_idx, num_sp, num_ae,
141  sp_mass_ptrs, ae_mass_ptrs);
142  }
143 
144  /*! \brief Get real-type particle attribute names */
145  [[nodiscard]] virtual amrex::Vector<std::string> varNames () const override;
146 
147  /*! \brief Get Eulerian plot variable names */
148  [[nodiscard]] virtual amrex::Vector<std::string> meshPlotVarNames () const override;
149 
150  /*! \brief Compute mesh variable from particles */
151  virtual void computeMeshVar( const std::string&,
152  amrex::MultiFab&,
153  const amrex::MultiFab&,
154  const int ) const override;
155 
156  /*! \brief Initialize super-droplets in domain at AMR level a_lev */
157  void InitializeParticles (const int a_lev, const amrex::Real a_t, const MFPtr& a_ptr);
158 
159  using ERFPC::InitializeParticles;
160 
161  /*! \brief Inject super-droplets in domain */
162  virtual void InjectParticles (const amrex::Real, const MFPtr& a_ptr, const amrex::Real);
163 
164  /*! \brief add particles for a given set of initialization parameters */
165  void addParticles ( int a_lev, const MFPtr&, const SDInitProperties& );
166 
167  /*! \brief Set initial number of superdroplets per cell as a box with uniform density */
168  void setNumSDBoxDistribution( int a_lev,
169  amrex::iMultiFab&,
170  const int,
171  const MFPtr&,
172  const amrex::RealBox&,
173  const bool );
174 
175  /*! \brief Set initial number of superdroplets per cell as a bubble with uniform density */
176  void setNumSDBubbleDistribution( int a_lev,
177  amrex::iMultiFab&,
178  const int,
179  const MFPtr&,
180  const amrex::RealBox&,
181  const bool );
182 
183  /*! \brief Set super-droplets attributes from a given condensate mass density
184  * \param[in] a_mf Multifab containing the initial condensate mass density
185  */
186  virtual void SetAttributes ( amrex::MultiFab& a_mf );
187 
188  /*! \brief Scale the SDM number density with air density
189  * \param[in] a_mf Multifab containing the air density field
190  */
191  virtual void DensityScaling ( const amrex::MultiFab& a_mf );
192 
193  /*! \brief Evolve particles for one time step */
194  virtual void EvolveParticles ( int,
195  amrex::Real,
196  amrex::Vector<amrex::Vector<amrex::MultiFab>>&,
197  const amrex::Vector<MFPtr>& ) override
198  {
199  amrex::Abort("SuperDropletPC::EvolveParticles() is intentionally disabled.");
200  }
201 
202  /*! \brief Advect particles for one time step */
203  virtual void AdvectParticles ( int a_lev,
204  amrex::Real a_time,
205  amrex::Real a_dt,
206  const amrex::MultiFab* const a_flow_vel,
207  const amrex::MultiFab& a_density,
208  const amrex::MultiFab& a_pressure,
209  const amrex::MultiFab& a_temperature,
210  const amrex::Vector<MFPtr>& a_z_phys_nd,
211  const BCTypeArr& a_bctypes,
212  const bool a_recycle);
213 
214  /*! \brief Grow/shrink particles for one time step */
215  virtual void MassChange ( int a_lev,
216  amrex::Real a_dt,
217  const Species::Name& a_vap_name,
218  const amrex::MultiFab& a_temperature,
219  const amrex::MultiFab& a_pressure,
220  const amrex::MultiFab& a_sat_pressure,
221  const amrex::MultiFab& a_sat_ratio,
222  const amrex::Vector<MFPtr>& a_z_phys_nd,
223  const bool a_is_water);
224 
225  /*! \brief Coalescence of super-droplets */
226  virtual void Coalescence ( int a_lev,
227  amrex::Real a_dt,
228  const amrex::MultiFab& a_pressure,
229  const amrex::MultiFab& a_temperature);
230 
231  /*! \brief Recycle super-droplets */
232  virtual void Recycle ( const int a_lev,
233  const amrex::Vector<MFPtr>& a_z_phys_nd,
234  const int a_iter,
235  const amrex::Real a_dt,
236  const bool a_recycle);
237 
238  /*! \brief Return the number of super-droplets
239  This returns the number of AMReX particles being used in the simulation. */
240  [[nodiscard]] inline virtual amrex::Long NumSuperDroplets ()
241  {
242  return ERFPC::TotalNumberOfParticles();
243  }
244 
245  /*! \brief Return the total number of physical particles */
246  [[nodiscard]] virtual amrex::Real TotalNumberOfParticles ();
247 
248  /*! \brief Return the number of deactivated super-droplets */
249  [[nodiscard]] virtual amrex::Long NumSDDeactivated ();
250 
251  /*! \brief Compute and print diagnostics */
252  virtual void Diagnostics (int, int, amrex::Real, bool);
253  /*! \brief Compute mass density distribution */
254  virtual void ComputeDistributions ( int, int,
255  amrex::ParticleReal,
256  amrex::ParticleReal );
257 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
258  /*! \brief Compute binned size distributions */
259  virtual void ComputeBinnedDistributions ( int, int );
260  /*! \brief Compute cell-wise binned size distributions */
261  virtual void ComputeBinnedDistributionsCell ( int, int, amrex::Real );
262 #endif
263 
264  /*! \brief Compute the SD number density on a mesh */
265  virtual void SDNumberDensity ( amrex::MultiFab&, const amrex::MultiFab& a_z_phys_nd, int a_lev, const int a_comp=0 ) const;
266  /*! \brief Compute the particle number density on a mesh */
267  virtual void numberDensity ( amrex::MultiFab&, const amrex::MultiFab& a_z_phys_nd, int a_lev, const int a_comp=0 ) const;
268  /*! \brief Compute the particle mass density on a mesh */
269  virtual void massDensity ( amrex::MultiFab&, const amrex::MultiFab& a_z_phys_nd, const int& a_lev, const int& a_comp=0 ) const override;
270  /*! \brief Compute the mass flux component on a mesh */
271  virtual void massFlux ( amrex::MultiFab&, const amrex::MultiFab& a_z_phys_nd, int a_lev, const int, const int a_comp=0 ) const;
272 
273  /*! \brief Compute the species mass density on a mesh */
274  virtual void speciesMassDensity ( amrex::MultiFab&,
275  const amrex::MultiFab& a_z_phys_nd,
276  int a_lev,
277  int,
278  const int a_comp = 0) const;
279 
280  /*! \brief Compute the cloud/rain mass density on a mesh */
281  virtual void cloudRainDensity ( amrex::MultiFab&,
282  const amrex::MultiFab& a_z_phys_nd,
283  int a_lev,
284  amrex::Real,
285  amrex::Real,
286  const int a_comp = 0) const;
287 
288  /*! \brief Compute the species mass flux component on a mesh */
289  virtual void speciesMassFlux ( amrex::MultiFab&, const amrex::MultiFab& a_z_phys_nd, int a_lev, const int, const int, const int a_comp=0 ) const;
290 
291  /*! \brief Compute the aerosol mass density on a mesh */
292  virtual void aerosolMassDensity ( amrex::MultiFab&, const amrex::MultiFab& a_z_phys_nd, int a_lev, const int, const int a_comp=0 ) const;
293  /*! \brief Compute the aerosol mass flux component on a mesh */
294  virtual void aerosolMassFlux ( amrex::MultiFab&, const amrex::MultiFab& a_z_phys_nd, int a_lev, const int, const int, const int a_comp=0 ) const;
295 
296  /*! \brief Compute the particle effective radius on a mesh */
297  virtual void effectiveRadius ( amrex::MultiFab&, const amrex::MultiFab& a_z_phys_nd, int a_lev, const int a_comp=0 ) const;
298 
299  /*! \brief Applies boundary treatment to the particle container */
300  virtual void applyBoundaryTreatment ( int, const amrex::Vector<MFPtr>&, const BCTypeArr&, const bool );
301 
302  protected:
303 
304  SDCoalescenceKernelType m_coalescence_kernel; /*!< Coalescence kernel */
305  bool m_include_brownian_coalescence; /*!< Include Brownian coalescence? */
306 
307  SDTerminalVelocityType m_term_vel_type_w; /*!< Terminal velocity model for water droplets */
308 
309  int m_num_sd_per_cell; /*!< Number of super-droplets per cell */
310  bool m_density_scaling; /*!< Scale initial number density with air density */
311  bool m_nucleate_particles; /*!< nucleate new superdroplets from vapour */
312  bool m_prescribed_advection; /*!< move particles with prescribed vertical velocity */
313 
314  int m_num_species; /*!< Number of vapour/condensate species */
315  std::vector<std::unique_ptr<MaterialProperties>> m_species_mat; /*!< Vapour/condensate material */
316  int m_num_aerosols; /*!< Number of aerosols */
317  std::vector<std::unique_ptr<MaterialProperties>> m_aerosol_mat; /*!< Aerosol materials */
318 
319  /* Mass change equation Newton solver parameters */
320  amrex::Real m_newton_rtol; /*!< Newton solver - relative tolerance */
321  amrex::Real m_newton_atol; /*!< Newton solver - absolute tolerance */
322  amrex::Real m_newton_stol; /*!< Newton solver - step tolerance */
323  int m_newton_maxits; /*!< Newton solver - maximum iterations */
324 
325  /* Mass change equation (un)convergence logs */
326  bool m_mass_change_logging; /*!< Whether to log unconverged particles */
327  FILE* m_mass_change_log; /*!< File handle for log with unconverged info */
328  std::string m_mass_change_log_fname; /*!< Name of unconverged info log file */
329 
330  amrex::Real m_mass_change_cfl; /*!< CFL for phase change equation */
331  SDMassChangeTIMethod m_mass_change_ti; /*!< time integrator for mass change ODE */
332  long m_num_unconverged_particles; /*!< total number of unconverged particles */
333 
334  amrex::IntVect m_coalescence_bin_size; /*!< bin size for coalescence */
335 
336  int m_distribution_grid_size; /*!< Size of 1D grid to compute distributions on */
337 
338  amrex::MultiFab m_mf_buf;
339 
340 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
341  amrex::Real m_bindist_rmin; /*!< min radius for binned distribution */
342  amrex::Real m_bindist_rmax; /*!< max radius for binned distribution */
343 
344  /*! Cell-wise mass distribution */
345  amrex::MultiFab m_mass_ln_R_mf;
346  /*! Cell-wise number distribution */
347  amrex::MultiFab m_num_ln_R_mf;
348 #endif
349 
350  /*! maximum coalescence time scale */
351  amrex::Real m_t_coalescence;
352 
353  /*! Initialization parameters objects */
354  int m_num_initializations = 1;
355  /*! vector of initializations */
356  std::vector< std::unique_ptr<SDInitialization> > m_initializations;
357 
358  /*! Injection parameters objects */
359  int m_num_injections = 0;
360  /*! vector of injections */
361  std::vector< std::unique_ptr<SDInjection> > m_injections;
362 
363  /*! sigma_0 parameter for mass distribution calculation */
364  amrex::Real m_sigma0;
365 
366  /*! place the initial SDs randomly within cells */
367  bool m_place_randomly_in_cells;
368 
369  /*! random engine */
370  std::mt19937 m_rndeng;
371 
372  /*! species index of water */
373  int m_idx_w = -1;
374 
375  /*! inactive particles threshold */
376  amrex::Real m_deac_threshold;
377 
378  /*! save inactive particles to file */
379  bool m_save_inactive;
380 
381  /*! Persistent device vectors for material properties */
382  amrex::Gpu::DeviceVector<amrex::ParticleReal> m_sp_density;
383  amrex::Gpu::DeviceVector<int> m_sp_solubility;
384  amrex::Gpu::DeviceVector<amrex::ParticleReal> m_sp_ionization;
385  amrex::Gpu::DeviceVector<amrex::ParticleReal> m_sp_mol_weight;
386 
387  amrex::Gpu::DeviceVector<amrex::ParticleReal> m_ae_density;
388  amrex::Gpu::DeviceVector<int> m_ae_solubility;
389  amrex::Gpu::DeviceVector<amrex::ParticleReal> m_ae_ionization;
390  amrex::Gpu::DeviceVector<amrex::ParticleReal> m_ae_mol_weight;
391 
392  /*! Flag to track if device properties are initialized */
393  bool m_device_props_initialized = false;
394 
395  /* recycled particle position bounds */
396  amrex::Real m_recyc_xmin;
397  amrex::Real m_recyc_xmax;
398  amrex::Real m_recyc_ymin;
399  amrex::Real m_recyc_ymax;
400  amrex::Real m_recyc_zmin;
401  amrex::Real m_recyc_zmax;
402 
403  /*! Method to initialize device properties */
404  void initializeDeviceProperties();
405 
406  /*! \brief Build ProcessContext with geometry and species info */
407  SDProcess::ProcessContext buildProcessContext(int a_lev) const
408  {
409  SDProcess::ProcessContext ctx;
410  const amrex::Geometry& geom = m_gdb->Geom(a_lev);
411  ctx.plo = geom.ProbLoArray();
412  ctx.phi = geom.ProbHiArray();
413  ctx.dxi = geom.InvCellSizeArray();
414  ctx.dx = geom.CellSizeArray();
415  ctx.domain = geom.Domain();
416  for (int d = 0; d < AMREX_SPACEDIM; d++) {
417  ctx.is_periodic[d] = geom.isPeriodic(d) ? 1 : 0;
418  }
419  const auto cell_size = geom.CellSize();
420  ctx.cell_volume = AMREX_D_TERM(cell_size[0], *cell_size[1], *cell_size[2]);
421  ctx.num_species = m_num_species;
422  ctx.num_aerosols = m_num_aerosols;
423  ctx.idx_water = m_idx_w;
424  ctx.rho_water = m_species_mat[m_idx_w]->m_density;
425  return ctx;
426  }
427 
428  /*! \brief Setup particle attribute pointers for a tile */
429  template<typename SOAType, typename AOSType>
430  void setupParticlePointers(
431  SOAType& soa,
432  AOSType& aos,
433  SDProcess::ParticlePointers& ptrs) const
434  {
435  using namespace SDPCDefn;
436 
437  constexpr int rtoff_i = SuperDropletsIntIdx::ncomps;
438  constexpr int rtoff_r = SuperDropletsRealIdx::ncomps;
439 
440  ptrs.num_particles = aos.numParticles();
441  ptrs.mass_ptr = soa.GetRealData(SuperDropletsRealIdx::mass).data();
442  ptrs.radius_ptr = soa.GetRealData(rtoff_r + SuperDropletsRealIdxSoA_RT::radius).data();
443  ptrs.active_ptr = soa.GetIntData(rtoff_i + SuperDropletsIntIdxSoA_RT::active).data();
444  ptrs.v_ptr[0] = soa.GetRealData(SuperDropletsRealIdx::vx).data();
445  ptrs.v_ptr[1] = soa.GetRealData(SuperDropletsRealIdx::vy).data();
446  ptrs.v_ptr[2] = soa.GetRealData(SuperDropletsRealIdx::vz).data();
447  ptrs.vterm_ptr = soa.GetRealData(rtoff_r + SuperDropletsRealIdxSoA_RT::term_vel).data();
448  ptrs.mult_ptr = soa.GetRealData(rtoff_r + SuperDropletsRealIdxSoA_RT::multiplicity).data();
449  setupMassPointers(soa, ptrs.sp_mass_ptrs, ptrs.ae_mass_ptrs);
450  if (!m_device_props_initialized) {
451  const_cast<SuperDropletPC*>(this)->initializeDeviceProperties();
452  }
453  ptrs.sp_rho_arr = m_sp_density.data();
454  ptrs.sp_sol_arr = m_sp_solubility.data();
455  ptrs.sp_ion_arr = m_sp_ionization.data();
456  ptrs.sp_mw_arr = m_sp_mol_weight.data();
457  ptrs.ae_rho_arr = m_ae_density.data();
458  ptrs.ae_sol_arr = m_ae_solubility.data();
459  ptrs.ae_ion_arr = m_ae_ionization.data();
460  ptrs.ae_mw_arr = m_ae_mol_weight.data();
461  }
462 
463  /*! \brief Common body for forEachParticleTile iterations */
464  template<typename TileFunc>
465  void forEachParticleTileBody(
466  ParIterType& pti, int a_lev,
467  const SDProcess::ProcessContext& ctx,
468  TileFunc&& func)
469  {
470  int grid = pti.index();
471  auto& ptile = ParticlesAt(a_lev, pti);
472  auto& aos = ptile.GetArrayOfStructs();
473  auto& soa = ptile.GetStructOfArrays();
474  if (aos.numParticles() == 0) { return; }
475  auto* p_pbox = aos().data();
476  SDProcess::ParticlePointers ptrs;
477  setupParticlePointers(soa, aos, ptrs);
478  func(pti, grid, p_pbox, ptrs, ctx);
479  }
480 
481  /*! \brief Iterate over particle tiles with common setup (parallel) */
482  template<typename TileFunc>
483  AMREX_FORCE_INLINE
484  void forEachParticleTile(
485  int a_lev,
486  const SDProcess::ProcessContext& ctx,
487  TileFunc&& func)
488  {
489 #ifdef AMREX_USE_OMP
490 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
491 #endif
492  for (ParIterType pti(*this, a_lev); pti.isValid(); ++pti) {
493  forEachParticleTileBody(pti, a_lev, ctx, std::forward<TileFunc>(func));
494  }
495  }
496 
497  /*! \brief Iterate over particle tiles WITHOUT OpenMP (serial)
498  * Use when per-tile operations are not thread-safe (e.g., DenseBins).
499  */
500  template<typename TileFunc>
501  AMREX_FORCE_INLINE
502  void forEachParticleTileSerial(int a_lev, const SDProcess::ProcessContext& ctx, TileFunc&& func)
503  {
504  for (ParIterType pti(*this, a_lev); pti.isValid(); ++pti) {
505  forEachParticleTileBody(pti, a_lev, ctx, std::forward<TileFunc>(func));
506  }
507  }
508 
509  /*! \brief Lightweight iteration (no ProcessContext) */
510  template<typename TileFunc>
511  void forEachParticleTile(int a_lev, TileFunc&& func)
512  {
513 #ifdef AMREX_USE_OMP
514 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
515 #endif
516  for (ParIterType pti(*this, a_lev); pti.isValid(); ++pti) {
517  int grid = pti.index();
518  auto& ptile = ParticlesAt(a_lev, pti);
519  auto& aos = ptile.GetArrayOfStructs();
520  auto& soa = ptile.GetStructOfArrays();
521  const int num_particles = aos.numParticles();
522  if (num_particles == 0) { continue; }
523  auto* p_pbox = aos().data();
524  SDProcess::ParticlePointers ptrs;
525  setupParticlePointers(soa, aos, ptrs);
526  func(pti, grid, p_pbox, ptrs, num_particles);
527  }
528  }
529 
530  /*! \brief read inputs from file */
531  virtual void readInputs () override
532  {
533  amrex::Abort("SuperDropletPC::readInputs(): Do not use this interface.");
534  }
535 
536  /*! \brief read inputs from file */
537  virtual void readInputs (const amrex::Real);
538 
539  /*! \brief Particle initialization - null (no particles are initialized) */
540  void initializeParticlesNull (const MFPtr&) { }
541 
542  private:
543 
544  /*! \brief define super-droplets */
545  void define ( const std::vector<Species::Name>&,
546  const std::vector<Species::Name>&,
547  const amrex::BoxArray&,
548  const amrex::DistributionMapping&,
549  const amrex::Real );
550 
551  /*! \brief add super-droplet method-specific particle attributes */
552  void add_superdroplet_attributes();
553 
554 };
555 
556 #endif
557 #endif
int m_num_species
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:28
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Common data structures for SuperDroplet physical processes.
Super-droplets initial properties.
Definition: ERF_SDInitialization.H:150
Definition: ERF_MaterialProperties.H:171