ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SuperDropletPCDefinitions.H
Go to the documentation of this file.
1 #ifndef SUPERDROPLET_PC_DEFN_H_
2 #define SUPERDROPLET_PC_DEFN_H_
3 
4 #ifdef ERF_USE_PARTICLES
5 
6 #include <AMReX_Enum.H>
7 #include <AMReX_Array.H>
8 #include <AMReX_REAL.H>
9 #include <AMReX_Particles.H>
10 #include "ERF_IndexDefines.H"
11 #include "ERF_Constants.H"
12 #include "ERFPC.H"
13 #include "ERF_SDInitialization.H"
14 
15 namespace SDPCDefn {
16  using SDSpeciesMassArr = amrex::GpuArray<amrex::ParticleReal*,SupDropInit::num_species_max>;
17  using SDAerosolMassArr = amrex::GpuArray<amrex::ParticleReal*,SupDropInit::num_aerosols_max>;
18 
19  /*! \brief Real-type array-of-struct attributes of a super-droplet */
20  using SuperDropletsRealIdxAoS = ERFParticlesRealIdxAoS;
21 
22  /*! \brief Int-type array-of-struct attributes of a super-droplet */
23  using SuperDropletsIntIdxAoS = ERFParticlesIntIdxAoS;
24 
25  /*! \brief Real-type struct-of-array attributes of a super-droplet */
26  using SuperDropletsRealIdxSoA = ERFParticlesRealIdxSoA;
27 
28  /*! \brief Int-type struct-of-array attributes of a super-droplet */
29  using SuperDropletsIntIdxSoA = ERFParticlesIntIdxSoA;
30 
31  /*! \brief Int-type struct-of-array attributes added during runtime */
32  struct SuperDropletsIntIdxSoA_RT
33  {
34  enum {
35  active = 0, /*!< Active/inactive */
36  ncomps
37  };
38  };
39 
40  /*! \brief Real-type struct-of-array attributes added during runtime */
41  struct SuperDropletsRealIdxSoA_RT
42  {
43  enum {
44  radius = 0, /*!< Radius of physical particles */
45  multiplicity, /*!< Number of droplets that this super-droplet represents
46  (Real type to handle large values) */
47  term_vel, /*!< Terminal velocity */
48 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
49  cond_tendency, /*!< Condensation/evaporation tendency */
50 #endif
51  uid, /*!< unique ID */
52  ncomps
53  };
54  };
55 }
56 
57 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
58 static int ridx_a(const int a_i, /*!< Species index */
59  const int a_num_a, /*!< Number of aerosols */
60  const int a_num_s /*!< Number of species */)
61 {
62  amrex::ignore_unused(a_num_a);
63  amrex::ignore_unused(a_num_s);
64  return SDPCDefn::SuperDropletsRealIdxSoA_RT::ncomps
65  + a_i;
66 }
67 
68 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
69 static int ridx_s(const int a_i, /*!< Species index */
70  const int a_num_a, /*!< Number of aerosols */
71  const int a_num_s /*!< Number of species */)
72 {
73  amrex::ignore_unused(a_num_s);
74  return SDPCDefn::SuperDropletsRealIdxSoA_RT::ncomps
75  + a_num_a
76  + a_i;
77 }
78 
79 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
80 static int idx_a(const int a_i, /*!< Species index */
81  const int a_num_a, /*!< Number of aerosols */
82  const int a_num_s /*!< Number of species */)
83 {
84  return SDPCDefn::SuperDropletsRealIdxSoA::ncomps + ridx_a(a_i,a_num_a,a_num_s);
85 }
86 
87 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
88 static int idx_s(const int a_i, /*!< Species index */
89  const int a_num_a, /*!< Number of aerosols */
90  const int a_num_s /*!< Number of species */)
91 {
92  return SDPCDefn::SuperDropletsRealIdxSoA::ncomps + ridx_s(a_i,a_num_a,a_num_s);
93 }
94 
95 /*! \brief Compute total mass of a droplet from its components */
96 AMREX_GPU_DEVICE AMREX_FORCE_INLINE
97 static amrex::ParticleReal SD_total_mass( const int a_idx, /*!< Particle index */
98  const int a_num_sp, /*!< number of species */
99  const int a_num_ae, /*!< number of aerosols */
100  const SDPCDefn::SDSpeciesMassArr& a_sp_mass, /*!< species masses */
101  const SDPCDefn::SDAerosolMassArr& a_ae_mass /*!< aerosol masses */ )
102 {
103  amrex::ParticleReal retval = zero;
104  for (int j = 0; j < a_num_sp; j++) {
105  retval += a_sp_mass[j][a_idx];
106  }
107  for (int j = 0; j < a_num_ae; j++) {
108  retval += a_ae_mass[j][a_idx];
109  }
110  return retval;
111 }
112 
113 /*! \brief Compute effective radius of a droplet from its components */
114 AMREX_GPU_DEVICE AMREX_FORCE_INLINE
115 static amrex::ParticleReal SD_effective_radius( const int a_idx, /*!< Particle index */
116  const int a_idx_w, /*!< Species index of water */
117  amrex::ParticleReal a_rho_w, /*!< density of water */
118  const int a_num_sp, /*!< number of species */
119  const int a_num_ae, /*!< number of aerosols */
120  const int* const a_sp_sol_arr, /*!< solubility of species */
121  const int* const a_ae_sol_arr, /*!< solubility of aerosols */
122  const SDPCDefn::SDSpeciesMassArr& a_sp_mass, /*!< species masses */
123  const SDPCDefn::SDAerosolMassArr& a_ae_mass, /*!< aerosol masses */
124  const amrex::ParticleReal* const a_sp_rho, /*!< species densities */
125  const amrex::ParticleReal* const a_ae_rho /*!< aerosol densities */ )
126 {
127  amrex::ParticleReal m_w = a_sp_mass[a_idx_w][a_idx];
128  amrex::ParticleReal m_s = zero;
129  amrex::ParticleReal m_p = zero;
130  amrex::ParticleReal rho_p = zero;
131  for (int j = 0; j < a_num_sp; j++) {
132  if (j != a_idx_w) {
133  if (a_sp_sol_arr[j]) {
134  m_s += a_sp_mass[j][a_idx];
135  } else {
136  m_p += a_sp_mass[j][a_idx];
137  rho_p += a_sp_rho[j]*a_sp_mass[j][a_idx];
138  }
139  }
140  }
141  for (int j = 0; j < a_num_ae; j++) {
142  if (a_ae_sol_arr[j]) {
143  m_s += a_ae_mass[j][a_idx];
144  } else {
145  m_p += a_ae_mass[j][a_idx];
146  rho_p += a_ae_rho[j]*a_ae_mass[j][a_idx];
147  }
148  }
149  if (m_p > zero) { rho_p /= m_p; }
150  else { rho_p = one; }
151  auto m_t = m_w + m_s + (a_rho_w/rho_p)*m_p;
152  auto r_eff = std::cbrt(m_t / (four_thirds_pi*a_rho_w));
153  return r_eff;
154 }
155 
156 /*! \brief Compute "dry" radius of a droplet from its insoluble components */
157 AMREX_GPU_DEVICE AMREX_FORCE_INLINE
158 static amrex::ParticleReal SD_dry_radius( const int a_idx, /*!< Particle index */
159  const int a_num_sp, /*!< number of species */
160  const int a_num_ae, /*!< number of aerosols */
161  const int* const a_sp_sol_arr, /*!< solubility of species */
162  const int* const a_ae_sol_arr, /*!< solubility of aerosols */
163  const SDPCDefn::SDSpeciesMassArr& a_sp_mass, /*!< species masses */
164  const SDPCDefn::SDAerosolMassArr& a_ae_mass, /*!< aerosol masses */
165  const amrex::ParticleReal* const a_sp_rho, /*!< species densities */
166  const amrex::ParticleReal* const a_ae_rho /*!< aerosol densities */ )
167 {
168  amrex::ParticleReal m_p = zero;
169  amrex::ParticleReal rho_p = zero;
170  for (int j = 0; j < a_num_sp; j++) {
171  if (!a_sp_sol_arr[j]) {
172  m_p += a_sp_mass[j][a_idx];
173  rho_p += a_sp_rho[j]*a_sp_mass[j][a_idx];
174  }
175  }
176  for (int j = 0; j < a_num_ae; j++) {
177  if (!a_ae_sol_arr[j]) {
178  m_p += a_ae_mass[j][a_idx];
179  rho_p += a_ae_rho[j]*a_ae_mass[j][a_idx];
180  }
181  }
182  if (m_p > zero) { rho_p /= m_p; }
183  else { rho_p = one; }
184  auto r_dry = std::cbrt(m_p / (four_thirds_pi*rho_p));
185  return r_dry;
186 }
187 
188 /*! \brief Types of terminal velocity models */
189 AMREX_ENUM(SDTerminalVelocityType,
190  RogersYau,
191  AtlasUlbrich,
192  CloudRainShima
193 );
194 
195 /*! \brief Types of coalescence kernels */
196 enum struct SDCoalescenceKernelType {
197  golovin,
198  sedimentation,
199  Longs,
200  Halls
201 };
202 
203 /*! \brief Types of phase change ODE time integrator */
204 enum struct SDMassChangeTIMethod {
205  RK3BS, RK4, BE, CN, DIRK2
206 };
207 
208 #endif
209 #endif
constexpr amrex::Real one
Definition: ERF_Constants.H:7
constexpr amrex::Real zero
Definition: ERF_Constants.H:6
constexpr amrex::Real four_thirds_pi
Definition: ERF_Constants.H:18
AMREX_ENUM(InitType, None, Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, ConstantDensity, ConstantDensityLinearTheta, Isentropic, MoistBaseState, HindCast)