ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SuperDropletsMoist.H
Go to the documentation of this file.
1 #ifndef SUPERDROPLETSMOIST_H
2 #define SUPERDROPLETSMOIST_H
3 
4 #ifdef ERF_USE_PARTICLES
5 
6 #include <limits>
7 #include <string>
8 #include <AMReX_Enum.H>
9 #include <AMReX_Geometry.H>
11 #include "ERF_SuperDropletPC.H"
12 
13 namespace MicVar_SD {
14  enum {
15  rho = 0, /*!< Density */
16  theta, /*!< Potential temperature */
17  temperature, /*!< Temperature */
18  pressure, /*!< Pressure */
19  q_t, /*!< Total (vapour + cloud) */
20  q_v, /*!< Water vapour */
21  q_c, /*!< Cloud condensate */
22  dqcdt, /*!< Condensation rate */
23  q_r, /*!< Rain */
24  rh, /*!< relative humidity */
25  rain_accum, /*!< rain accumulation (mm) */
26  NumVars
27  };
28 }
29 
30 namespace MicVar_SD_Species {
31  enum {
32  q_t = 0, /*!< Total density ratio */
33  q_v, /*!< Vapour density ratio */
34  q_c, /*!< Condensate density ratio */
35  sr, /*!< Saturation ratio */
36  accum, /*!< Ground accumulation */
37  NumVars
38  };
39 }
40 
41 namespace MicVar_SD_Aerosols {
42  enum {
43  accum = 0, /*!< Ground accumulation */
44  NumVars
45  };
46 }
47 
48 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
49 static int s_qt_idx (const int a_i /*!< species index */ )
50 {
51  AMREX_ALWAYS_ASSERT(a_i > 0);
52  return MicVar_SD::NumVars
54  + MicVar_SD_Species::q_t;
55 }
56 
57 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
58 static int s_qv_idx (const int a_i /*!< species index */ )
59 {
60  AMREX_ALWAYS_ASSERT(a_i > 0);
61  return MicVar_SD::NumVars
63  + MicVar_SD_Species::q_v;
64 }
65 
66 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
67 static int s_qc_idx (const int a_i /*!< species index */ )
68 {
69  AMREX_ALWAYS_ASSERT(a_i > 0);
70  return MicVar_SD::NumVars
72  + MicVar_SD_Species::q_c;
73 }
74 
75 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
76 static int s_sr_idx (const int a_i /*!< species index */ )
77 {
78  AMREX_ALWAYS_ASSERT(a_i > 0);
79  return MicVar_SD::NumVars
81  + MicVar_SD_Species::sr;
82 }
83 
84 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
85 static int s_accum_idx (const int a_i /*!< species index */ )
86 {
87  AMREX_ALWAYS_ASSERT(a_i > 0);
88  return MicVar_SD::NumVars
90  + MicVar_SD_Species::accum;
91 }
92 
93 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
94 static int a_accum_idx (const int a_ns, /*!< number of species */
95  const int a_i /*!< aerosol index */ )
96 {
97  AMREX_ALWAYS_ASSERT(a_i >= 0);
98  return MicVar_SD::NumVars
101  + MicVar_SD_Aerosols::accum;
102 }
103 
104 /*! \brief List of super-droplet moisture model initializations */
105 AMREX_ENUM(SDMoistInit,
106  uniform,
107  condensate_density
108 );
109 
110 AMREX_ENUM(SDMSimulationDim,
111  one_d_z, two_d_xz, two_d_yz, three_d
112 );
113 
114 class SuperDropletsMoist : public NullMoistLagrangian {
115 
116  using FabPtr = std::shared_ptr<amrex::MultiFab>;
117  using MFPtr = std::unique_ptr<amrex::MultiFab>;
118  using BCTypeArr = amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2>;
119 
120  public:
121 
122  /*! \brief Constructor */
123  SuperDropletsMoist()
124  {
125  m_qmoist_size = 7;
126  m_qstate_moist_size = 3; // qv, qc, qr
127  m_qstate_nonmoist_size = -1; // intentional
128  m_name = "super_droplets_moisture";
129  m_idx_w = -1;
130  m_num_species = 0;
131  m_num_aerosols = 0;
132  readInputs();
133  }
134 
135  /*! \brief Destructor */
136  virtual ~SuperDropletsMoist() = default;
137 
138  /*! \brief Define super-droplet moisture model parameters */
139  virtual void Define (SolverChoice&) override;
140 
141  /*! \brief Initialize super-droplet moisture model data structures */
142  virtual void Init ( const amrex::MultiFab&,
143  const amrex::BoxArray&,
144  const amrex::Geometry&,
145  const amrex::Real&,
146  MFPtr&,
147  MFPtr& ) override;
148 
149  /*! \brief Initialize particles */
150  virtual void InitParticles ( MFPtr& ) override;
151 
152  /*! \brief Restart particles */
153  virtual void RestartParticles ( amrex::ParGDBBase*, const std::string& ) override;
154 
155  /*! \brief finish initializations */
156  virtual void FinishInit(const int&,
157  amrex::MultiFab&,
158  const amrex::Vector<MFPtr>&) override;
159 
160  void Advance ( const amrex::Real&, const SolverChoice& ) override
161  {
162  amrex::Abort("Do not use this advance() for Lagrangian microphysics.");
163  }
164 
165  /*! \brief Advance for one timestep
166  * \param[in] dt Timestep
167  * \param[in] iteration Current iteration number
168  * \param[in] time Current simulation time
169  * \param[in,out] cons_vars Array of conserved variables
170  * \param[in] mf_array Array of additional multifabs
171  * \param[in] bc_arr Array of boundary conditions
172  */
173  virtual void Advance (const amrex::Real& dt,
174  const int& iteration,
175  const amrex::Real& time,
176  amrex::Vector<amrex::Vector<amrex::MultiFab>>& cons_vars,
177  const amrex::Vector<MFPtr>& mf_array,
178  const BCTypeArr& bc_arr) override;
179 
180  /*! \brief Update microphysics variables
181  * \param[in] a_cons_vars Conservative variables multifab
182  */
183  virtual void Update_Micro_Vars (amrex::MultiFab& a_cons_vars) override;
184 
185  /*! \brief Update state variables from microphysics variables
186  * \param[in,out] a_cons_vars Conservative variables multifab to update
187  */
188  virtual void Update_State_Vars (amrex::MultiFab& a_cons_vars) override;
189 
190  /*! \brief Copy moisture model vars from state to member multifabs
191  * \param[in] a_state State multifab to copy from
192  */
193  virtual void Copy_State_to_Micro (const amrex::MultiFab& a_state) override;
194 
195  /*! \brief Copy moisture model vars to state from member multifabs
196  * \param[out] a_state State multifab to copy to
197  */
198  virtual void Copy_Micro_to_State (amrex::MultiFab& a_state) override;
199 
200  /*! \brief returns the moisture variable asked for */
201  inline virtual amrex::MultiFab* Qmoist_Ptr (const int& a_idx) override
202  {
203  AMREX_ALWAYS_ASSERT( a_idx < m_qmoist_size );
204  return m_mic_fab_vars[m_mic_var_map[a_idx]].get();
205  }
206 
207  /*! \brief returns number of variables in this moisture model */
208  inline virtual int Qmoist_Size () override
209  {
210  return m_qmoist_size;
211  }
212 
213  /*! \brief returns number of moist conserved variables */
214  inline virtual int Qstate_Moist_Size () override
215  {
216  return m_qstate_moist_size;
217  }
218 
219  /*! \brief returns number of non-water species conserved variables */
220  inline virtual int Qstate_NonMoist_Size () override
221  {
222  AMREX_ALWAYS_ASSERT(m_qstate_nonmoist_size >= 0);
223  return m_qstate_nonmoist_size;
224  }
225 
226  /*! \brief returns pointer to super-droplets particle container */
227  inline virtual ERFPC* getParticleContainer() override
228  {
229  return m_super_droplets;
230  }
231 
232  inline virtual const std::string& getName() const override
233  {
234  return m_name;
235  }
236 
237  /*! \brief compute cloud/rain mixing ratio */
238  virtual void computeQcQrWater ();
239 
240  /*! \brief compute condensate for all non-water species */
241  virtual void computeQcSpecies ()
242  {
243  for (int is = 1; is < m_num_species; is++) { computeQcSpecies(is); }
244  }
245 
246  /*! \brief compute condensate mixing ratio for a non-water species */
247  virtual void computeQcSpecies (const int a_i);
248 
249  /*! \brief compute condensate mixing ratio for a species */
250  virtual void computeQc (const int a_i)
251  {
252  if (a_i == m_idx_w) { computeQcQrWater(); }
253  else { computeQcSpecies(a_i); }
254  }
255 
256  /*! \brief compute total water mixing ratio */
257  virtual void computeQtWater ();
258 
259  /*! \brief compute qt (total) for all non-water species */
260  virtual void computeQtSpecies ()
261  {
262  for (int is = 1; is < m_num_species; is++) { computeQtSpecies(is); }
263  }
264 
265  /*! \brief compute qt (total) for a non-water species */
266  virtual void computeQtSpecies (const int a_i);
267 
268  /*! \brief compute qt (total) for a species */
269  virtual void computeQt (const int a_i)
270  {
271  if (a_i == m_idx_w) { computeQtWater(); }
272  else { computeQtSpecies(a_i); }
273  }
274 
275  /*! \brief Compute rain accumulation */
276  virtual void rainAccumulation ();
277 
278  /*! \brief Compute non-water species accumulation */
279  virtual void speciesAccumulation ();
280 
281  /*! \brief Compute aerosol accumulation */
282  virtual void aerosolAccumulation ();
283 
284  /*! \brief Convert a multifab containing density of something to its mixing ratio */
285  void densityToRatio ( amrex::MultiFab&, const int a_comp = 0 );
286  /*! \brief Convert a multifab containing the mixing ratio of something to its density */
287  void ratioToDensity ( amrex::MultiFab&, const int a_comp = 0 );
288 
289  /*! \brief Compute phase changes (vapour <--> cloud water)
290  * \param[in] a_dt Timestep for phase change calculation
291  * \param[in] a_z Array of terrain heights
292  * \param[in] a_update_qv Flag to enable updating vapour mixing ratio
293  */
294  virtual void phaseChange ( const amrex::Real& a_dt,
295  const amrex::Vector<MFPtr>& a_z,
296  const bool a_update_qv);
297 
298  virtual void GetPlotVarNames (amrex::Vector<std::string>& a_names) const override
299  {
300  for (int v = 1; v < m_num_species; v++) {
301  a_names.push_back("qv_"+amrex::getEnumNameString(m_species[v]));
302  a_names.push_back("qc_"+amrex::getEnumNameString(m_species[v]));
303  a_names.push_back("qt_"+amrex::getEnumNameString(m_species[v]));
304  a_names.push_back("sat_ratio_"+amrex::getEnumNameString(m_species[v]));
305  a_names.push_back("accum_"+amrex::getEnumNameString(m_species[v]));
306  }
307  for (int v = 0; v < m_num_aerosols; v++) {
308  a_names.push_back("accum_"+amrex::getEnumNameString(m_aerosols[v]));
309  }
310  }
311 
312  virtual void GetPlotVar (const std::string& a_name,
313  amrex::MultiFab& a_mf ) const override
314  {
315  AMREX_ASSERT(a_mf.nComp() >= 1);
316  for (int v = 1; v < m_num_species; v++) {
317  {
318  std::string varname = "qv_" + amrex::getEnumNameString(m_species[v]);
319  if (a_name == varname) {
320  amrex::MultiFab::Copy( a_mf,
321  *m_mic_fab_vars[s_qv_idx(v)],
322  0, 0, 1, amrex::IntVect::TheZeroVector() );
323  return;
324  }
325  }
326  {
327  std::string varname = "qc_" + amrex::getEnumNameString(m_species[v]);
328  if (a_name == varname) {
329  amrex::MultiFab::Copy( a_mf,
330  *m_mic_fab_vars[s_qc_idx(v)],
331  0, 0, 1, amrex::IntVect::TheZeroVector() );
332  return;
333  }
334  }
335  {
336  std::string varname = "qt_" + amrex::getEnumNameString(m_species[v]);
337  if (a_name == varname) {
338  amrex::MultiFab::Copy( a_mf,
339  *m_mic_fab_vars[s_qt_idx(v)],
340  0, 0, 1, amrex::IntVect::TheZeroVector() );
341  return;
342  }
343  }
344  {
345  std::string varname = "sat_ratio_" + amrex::getEnumNameString(m_species[v]);
346  if (a_name == varname) {
347  amrex::MultiFab::Copy( a_mf,
348  *m_mic_fab_vars[s_sr_idx(v)],
349  0, 0, 1, amrex::IntVect::TheZeroVector() );
350  return;
351  }
352  }
353  {
354  std::string varname = "accum_" + amrex::getEnumNameString(m_species[v]);
355  if (a_name == varname) {
356  amrex::MultiFab::Copy( a_mf,
357  *m_mic_fab_vars[s_accum_idx(v)],
358  0, 0, 1, amrex::IntVect::TheZeroVector() );
359  return;
360  }
361  }
362  }
363  for (int v = 0; v < m_num_aerosols; v++) {
364  {
365  std::string varname = "accum_" + amrex::getEnumNameString(m_aerosols[v]);
366  if (a_name == varname) {
367  amrex::MultiFab::Copy( a_mf,
368  *m_mic_fab_vars[a_accum_idx(m_num_species,v)],
369  0, 0, 1, amrex::IntVect::TheZeroVector() );
370  return;
371  }
372  }
373  }
374  amrex::Abort("SuperDropletsMoist::GetPlotVar() called with invalid name");
375  return;
376  }
377 
378  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
379  int q_qv_idx (const int a_i /*!< species index */ )
380  {
381  AMREX_ALWAYS_ASSERT(a_i > 0);
382  return RhoQ1_comp + m_qstate_moist_size + 2*(a_i-1) + 0;
383  }
384 
385  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
386  int q_qc_idx (const int a_i /*!< species index */ )
387  {
388  AMREX_ALWAYS_ASSERT(a_i > 0);
389  return RhoQ1_comp + m_qstate_moist_size + 2*(a_i-1) + 1;
390  }
391 
392  protected:
393 
394  bool m_flag_phase_change; /*!< Enable/disable phase change */
395  bool m_flag_advection; /*!< Enable/disable advection */
396  bool m_flag_coalescence; /*!< Enable/disable coalescence */
397 
398  amrex::Real m_Cp; /*!< specific heat at constant pressure for dry air */
399 
400  amrex::Real m_r_rain; /*!< minimum radius to be considered rain */
401 
402  /*! let initial superdroplets "relax" to a physically-appropriate size? */
403  bool m_init_phase_change;
404  /*! time (in seconds) of initial relaxation */
405  amrex::Real m_init_phase_change_time;
406 
407  int m_diagnostics_iter; /*!< number of iterations between computing diagnostics */
408 
409  /*! initialization type */
410  SDMoistInit m_init_type;
411 
412  /*! name of model and its particle container */
413  std::string m_name;
414  /*! particle container for super-droplets */
415  SuperDropletPC* m_super_droplets;
416 
417  /*! Geometry object */
418  amrex::Geometry m_geom;
419 
420  /*! number of microphysics variables */
421  int m_qmoist_size;
422  /*! number of water-related state variables for this moisture model */
423  int m_qstate_moist_size;
424  /*! number of non-water-related state variables for this moisture model */
425  int m_qstate_nonmoist_size;
426 
427  amrex::Real m_dt; /*!< timestep */
428  amrex::Vector<int> m_mic_var_map; /*!< moisture model variables map */
429 
430  /*! moisture model variables */
431  amrex::Vector<FabPtr> m_mic_fab_vars;
432 
433  /*! names of vapour/condensate species */
434  std::vector<Species::Name> m_species;
435  int m_num_species;
436 
437  /*! names of aerosols */
438  std::vector<Species::Name> m_aerosols;
439  int m_num_aerosols;
440 
441  /*! number of substeps for phase change */
442  int m_num_substeps_phase_change;
443 
444  /*! kinematic mode? */
445  bool m_kinematic_mode;
446 
447  /*! Dimensionality of simulation*/
448  SDMSimulationDim m_dimensionality;
449 
450  /*! recycle particles */
451  bool m_recycle_particles;
452 
453  /*! species index of water */
454  int m_idx_w;
455 
456  /*! \brief read inputs */
457  virtual void readInputs();
458 
459  private:
460 
461 };
462 
463 #endif
464 #endif
AMREX_ENUM(InitType, None, Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, HindCast)
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42
Contains the Lagrangian moisture model base class.
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ NumVars
Definition: ERF_MM5.H:21
@ theta
Definition: ERF_MM5.H:20
@ rho
Definition: ERF_Kessler.H:22
@ rain_accum
Definition: ERF_Kessler.H:33
Definition: ERF_DataStruct.H:129