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