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