ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
Kessler Class Reference

#include <ERF_Kessler.H>

Inheritance diagram for Kessler:
Collaboration diagram for Kessler:

Public Member Functions

 Kessler ()
 
virtual ~Kessler ()=default
 
void AdvanceKessler (const SolverChoice &solverChoice)
 
void Define (SolverChoice &sc) override
 
void Init (const amrex::MultiFab &cons_in, const amrex::BoxArray &grids, const amrex::Geometry &geom, const amrex::Real &dt_advance, std::unique_ptr< amrex::MultiFab > &z_phys_nd, std::unique_ptr< amrex::MultiFab > &detJ_cc) override
 
void Set_dzmin (const amrex::Real dz_min) override
 
void Copy_State_to_Micro (const amrex::MultiFab &cons_in) override
 
void Copy_State_to_Micro (const amrex::MultiFab &cons_in, const amrex::MultiFab *base_state)
 
void Update_Micro_Vars (amrex::MultiFab &cons_in, const amrex::MultiFab *base_state) override
 
void Copy_Micro_to_State (amrex::MultiFab &cons_in) override
 
void Update_Micro_Vars (amrex::MultiFab &cons_in) override
 
void Update_State_Vars (amrex::MultiFab &cons_in, const amrex::MultiFab &) override
 
void Advance (const amrex::Real &dt_advance, const SolverChoice &solverChoice) override
 
amrex::MultiFab * Qmoist_Ptr (const int &varIdx) override
 
int Qmoist_Size () override
 
int Qstate_Moist_Size () override
 
int Qstate_Moist_NumConc_Size () override
 
void Qmoist_Restart_Vars (const SolverChoice &, std::vector< int > &a_idx, std::vector< std::string > &a_names) const override
 
SurfacePrecipAccumulationSources Get_Surface_Precip_Accumulation_Ptrs (const int &) const override
 
- Public Member Functions inherited from NullMoist
 NullMoist ()
 
virtual ~NullMoist ()=default
 
virtual int Qstate_NonMoist_Size ()
 
virtual void GetPlotVarNames (amrex::Vector< std::string > &a_vec) const
 
virtual void GetPlotVar (const std::string &, amrex::MultiFab &) const
 
virtual void GetPlotVar (const std::string &a_name, amrex::MultiFab &a_mf, const int) const
 
virtual void SetCurrentLevel (const int &lev)
 
virtual void InitLevel (const int, const amrex::MultiFab &)
 
virtual int getDiagnosticsInterval () const
 
virtual void Set_Lmask (amrex::iMultiFab *)
 Import ERF's land/water mask. Only schemes whose physics branches on land vs water need to override this. More...
 
virtual void Set_RealWidth (const int)
 

Private Types

using FabPtr = std::shared_ptr< amrex::MultiFab >
 

Private Attributes

int m_qmoist_size = 1
 
int n_qstate_moist_size = 3
 
int n_qstate_moist_numconc_size = 0
 
amrex::Vector< int > MicVarMap
 
amrex::Geometry m_geom
 
amrex::Real dt
 
amrex::Real m_dzmin {0.0}
 
int nlev
 
int zlo
 
int zhi
 
amrex::Real m_fac_cond
 
amrex::Real m_rdOcp {RdoCp}
 
bool m_do_cond
 
MoistureType m_moisture_type = MoistureType::None
 
amrex::MultiFab * m_z_phys_nd
 
amrex::MultiFab * m_detJ_cc
 
amrex::Array< FabPtr, MicVar_Kess::NumVarsmic_fab_vars
 

Static Private Attributes

static constexpr amrex::Real CFL_MAX = kessler_sedimentation_cfl_max
 

Additional Inherited Members

- Protected Member Functions inherited from NullMoist
void set_anelastic_reference_pressure_mode (const SolverChoice &sc)
 
void assert_base_state_available (const amrex::MultiFab *base_state) const
 
- Protected Attributes inherited from NullMoist
int m_level {0}
 
bool m_use_anelastic_reference_pressure {false}
 

Member Typedef Documentation

◆ FabPtr

using Kessler::FabPtr = std::shared_ptr<amrex::MultiFab>
private

Constructor & Destructor Documentation

◆ Kessler()

Kessler::Kessler ( )
inline
84 {}

◆ ~Kessler()

virtual Kessler::~Kessler ( )
virtualdefault

Member Function Documentation

◆ Advance()

void Kessler::Advance ( const amrex::Real dt_advance,
const SolverChoice solverChoice 
)
inlineoverridevirtual

Reimplemented from NullMoist.

156  {
157  dt = dt_advance;
158 
159  this->AdvanceKessler(solverChoice);
160  }
amrex::Real dt
Definition: ERF_Kessler.H:222
void AdvanceKessler(const SolverChoice &solverChoice)
Definition: ERF_Kessler.cpp:14
Here is the call graph for this function:

◆ AdvanceKessler()

void Kessler::AdvanceKessler ( const SolverChoice solverChoice)

Compute Precipitation-related Microphysics quantities.

15 {
16  bool do_cond = m_do_cond;
18  auto domain = m_geom.Domain();
19  int k_lo = domain.smallEnd(2);
20  int k_hi = domain.bigEnd(2);
21  if (solverChoice.moisture_type == MoistureType::Kessler)
22  {
23  MultiFab fz;
24  auto ba = tabs->boxArray();
25  auto dm = tabs->DistributionMap();
26  fz.define(convert(ba, IntVect(0,0,1)), dm, 1, 0); // No ghost cells
27 
28  Real dtn = dt;
29  // NOTE: coef carries only the reference vertical spacing. The physical
30  // spacing is supplied by the inverse Jacobian in the tendency below,
31  // since detJ = dz_phys/CellSize(2). Dividing by m_dzmin here as well
32  // would apply the vertical metric twice. m_dzmin is still the correct
33  // length scale for the substep (CFL) count, which must bound the
34  // thinnest cell in the domain.
35  Real coef = dtn * m_geom.InvCellSize(2);
36 
37  for ( MFIter mfi(*tabs,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
38  auto qv_array = mic_fab_vars[MicVar_Kess::qv]->array(mfi);
39  auto qc_array = mic_fab_vars[MicVar_Kess::qcl]->array(mfi);
40  auto qp_array = mic_fab_vars[MicVar_Kess::qp]->array(mfi);
41  auto qt_array = mic_fab_vars[MicVar_Kess::qt]->array(mfi);
42  auto tabs_array = mic_fab_vars[MicVar_Kess::tabs]->array(mfi);
43  auto pres_array = mic_fab_vars[MicVar_Kess::pres]->array(mfi);
44  auto theta_array = mic_fab_vars[MicVar_Kess::theta]->array(mfi);
45  auto rho_array = mic_fab_vars[MicVar_Kess::rho]->array(mfi);
46 
47  auto tbx = mfi.tilebox();
48 
49  Real d_fac_cond = m_fac_cond;
50 
51  ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
52  {
53  qv_array(i,j,k) = std::max(Real(0), qv_array(i,j,k));
54  qc_array(i,j,k) = std::max(Real(0), qc_array(i,j,k));
55  qp_array(i,j,k) = std::max(Real(0), qp_array(i,j,k));
56 
57  Real qsat_local, dtqsat_local;
58  Real pressure = pres_array(i,j,k);
59  // Kessler stores pressure in mbar / hPa for the qsat helpers.
60  erf_qsatw(tabs_array(i,j,k), pressure, qsat_local);
61  erf_dtqsatw(tabs_array(i,j,k), pressure, dtqsat_local);
62 
63  if (qsat_local <= Real(0)) {
64  amrex::Warning("qsat computed as non-positive; setting to Real(0)!");
65  qsat_local = Real(0);
66  }
67 
68  const KesslerSourceTerms source_terms = kessler_warm_rain_sources(
69  qv_array(i,j,k), qc_array(i,j,k), qp_array(i,j,k), rho_array(i,j,k),
70  pressure, qsat_local, dtqsat_local, dtn, do_cond, d_fac_cond);
71 
72  qv_array(i,j,k) += -source_terms.dq_vapor_to_cloud
73  + source_terms.dq_cloud_to_vapor
74  + source_terms.dq_rain_to_vapor;
75  qc_array(i,j,k) += source_terms.dq_vapor_to_cloud
76  - source_terms.dq_cloud_to_vapor
77  - source_terms.dq_cloud_to_rain;
78  qp_array(i,j,k) += source_terms.dq_cloud_to_rain
79  - source_terms.dq_rain_to_vapor;
80 
81  Real theta_over_T = theta_array(i,j,k)/tabs_array(i,j,k);
82  theta_array(i,j,k) += theta_over_T * d_fac_cond
83  * (source_terms.dq_vapor_to_cloud
84  - source_terms.dq_cloud_to_vapor
85  - source_terms.dq_rain_to_vapor);
86 
87  qv_array(i,j,k) = std::max(Real(0), qv_array(i,j,k));
88  qc_array(i,j,k) = std::max(Real(0), qc_array(i,j,k));
89  qp_array(i,j,k) = std::max(Real(0), qp_array(i,j,k));
90 
91  qt_array(i,j,k) = qv_array(i,j,k) + qc_array(i,j,k);
92  });
93  }
94 
95  for ( MFIter mfi(fz, TilingIfNotGPU()); mfi.isValid(); ++mfi ){
96  auto rho_array = mic_fab_vars[MicVar_Kess::rho]->array(mfi);
97  auto qp_array = mic_fab_vars[MicVar_Kess::qp]->array(mfi);
98 
99  auto fz_array = fz.array(mfi);
100  const Box& tbz = mfi.tilebox();
101 
102  ParallelFor(tbz, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
103  {
104  const Real rho_km1 = (k == k_lo) ? rho_array(i,j,k) : rho_array(i,j,k-1);
105  const Real rho_k = (k == k_hi+1) ? rho_array(i,j,k-1) : rho_array(i,j,k);
106  const Real qp_km1 = (k == k_lo) ? qp_array(i,j,k) : qp_array(i,j,k-1);
107  const Real qp_k = (k == k_hi+1) ? qp_array(i,j,k-1) : qp_array(i,j,k);
108  const KesslerFaceState face_state =
109  kessler_face_state(k, k_hi, rho_km1, rho_k, qp_km1, qp_k);
110 
111  const Real terminal_velocity = kessler_terminal_velocity(face_state.rho, face_state.qp);
112  fz_array(i,j,k) = kessler_precip_flux(face_state.rho, terminal_velocity, face_state.qp);
113  });
114  }
115 
116  auto const& ma_rho_arr = mic_fab_vars[MicVar_Kess::rho]->const_arrays();
117  auto const& ma_qp_arr = mic_fab_vars[MicVar_Kess::qp]->const_arrays();
118  // The sedimentation CFL uses fall speed, not precipitating mass flux.
119  // fz stores rho * Vt * qp for the flux divergence below, so the reduction
120  // recomputes Vt from the same face state used for the flux.
121  GpuTuple<Real> max_terminal_velocity = ParReduce(TypeList<ReduceOpMax>{},
122  TypeList<Real>{},
123  fz, IntVect(0),
124  [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
125  -> GpuTuple<Real>
126  {
127  const auto& rho_arr = ma_rho_arr[box_no];
128  const auto& qp_arr = ma_qp_arr[box_no];
129  const Real rho_km1 = (k == k_lo) ? rho_arr(i,j,k) : rho_arr(i,j,k-1);
130  const Real rho_k = (k == k_hi+1) ? rho_arr(i,j,k-1) : rho_arr(i,j,k);
131  const Real qp_km1 = (k == k_lo) ? qp_arr(i,j,k) : qp_arr(i,j,k-1);
132  const Real qp_k = (k == k_hi+1) ? qp_arr(i,j,k-1) : qp_arr(i,j,k);
133  const KesslerFaceState face_state =
134  kessler_face_state(k, k_hi, rho_km1, rho_k, qp_km1, qp_k);
135  return { kessler_terminal_velocity(face_state.rho, face_state.qp) };
136  });
137  Real max_vt = get<0>(max_terminal_velocity);
138  //
139  // ParReduce over a MultiFab gives the local rank maximum here. Every rank must
140  // arrive at the SAME substep count: otherwise different parts of the domain
141  // advance with different effective timesteps, the answer depends on the number
142  // of ranks, and the ranks make different numbers of the collective FillBoundary
143  // calls in the substep loop below. A rank owning no boxes would also see
144  // ReduceOpMax's lowest() initial value here. (SAM's PrecipFall does this same
145  // reduction for the same reasons.)
146  //
147  ParallelDescriptor::ReduceRealMax(max_vt);
148 
149  // A zero minimum dz means Set_dzmin was never called (a restart path that
150  // skipped it): the substep count would be unbounded and the step never end.
152  "Kessler: the minimum cell height was never set (Set_dzmin), so the sedimentation substeps cannot be sized");
153  int n_substep = kessler_num_sedimentation_substeps(max_vt, dt, m_dzmin);
154  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(n_substep >= 1,
155  "Kessler: Number of precipitation substeps must be greater than 0!");
156  coef /= Real(n_substep);
157  dtn /= Real(n_substep);
158 
159  for (int nsub(0); nsub<n_substep; ++nsub)
160  {
161  // The face state and the donor-cap limiter read rho/qp at k-1, which is a ghost
162  // cell whenever a box boundary is interior in z. The previous substep updated qp
163  // in valid cells only, so refresh ghosts here; otherwise the two sides of a
164  // shared z face see different donor values and the column budget does not close.
165  mic_fab_vars[MicVar_Kess::qp]->FillBoundary(m_geom.periodicity());
166 
167  for ( MFIter mfi(*tabs, TileNoZ()); mfi.isValid(); ++mfi ){
168  auto rho_array = mic_fab_vars[MicVar_Kess::rho]->array(mfi);
169  auto qp_array = mic_fab_vars[MicVar_Kess::qp]->array(mfi);
170  auto rain_accum_array = mic_fab_vars[MicVar_Kess::rain_accum]->array(mfi);
171  auto fz_array = fz.array(mfi);
172 
173  const auto dJ_array = (m_detJ_cc) ? m_detJ_cc->const_array(mfi) : Array4<const Real>{};
174 
175  const Box& tbx = mfi.tilebox();
176  const Box& tbz = mfi.tilebox(IntVect(0,0,1),IntVect(0));
177 
178  ParallelFor(tbz, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
179  {
180  const Real rho_km1 = (k == k_lo) ? rho_array(i,j,k) : rho_array(i,j,k-1);
181  const Real rho_k = (k == k_hi+1) ? rho_array(i,j,k-1) : rho_array(i,j,k);
182  const Real qp_km1 = (k == k_lo) ? qp_array(i,j,k) : qp_array(i,j,k-1);
183  const Real qp_k = (k == k_hi+1) ? qp_array(i,j,k-1) : qp_array(i,j,k);
184  const int donor_k = kessler_face_donor_k(k, k_hi);
185  const KesslerFaceState face_state =
186  kessler_face_state(k, k_hi, rho_km1, rho_k, qp_km1, qp_k);
187 
188  const Real terminal_velocity = kessler_terminal_velocity(face_state.rho, face_state.qp);
189  const Real donor_rho = rho_array(i,j,donor_k);
190  const Real donor_qp = std::max(Real(0), qp_array(i,j,donor_k));
191  const Real donor_detJ = (dJ_array) ? dJ_array(i,j,donor_k) : Real(1);
192  // The face flux uses face rho and donor qp. The limiter uses donor rho,
193  // donor qp, and donor detJ because it caps how much rain can leave the donor
194  // cell in this substep.
195  // Cap outgoing flux by the donor cell's detJ-weighted available rain water:
196  // F * dt / dz <= rho_donor * qp_donor * detJ_donor.
197  // This keeps compressed cells from losing more rain than they contain.
198  const Real max_flux = donor_rho * donor_qp * donor_detJ / coef;
199  fz_array(i,j,k) = amrex::min(
200  kessler_precip_flux(face_state.rho, terminal_velocity, face_state.qp), max_flux);
201 
202  if(k==k_lo){
203  // Surface accumulation stores the bottom-face precipitation mass per area
204  // increment converted to liquid-water depth.
205  rain_accum_array(i,j,k) = rain_accum_array(i,j,k)
206  + kessler_rain_accumulation_increment(fz_array(i,j,k) * dtn);
207  }
208  });
209 
210  ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
211  {
212  Real dJinv = (dJ_array) ? Real(1)/dJ_array(i,j,k) : Real(1);
213 
214  // Threshold local face-flux copies only. Neighboring cells share fz
215  // faces, so the cell update must not mutate fz while applying the
216  // small-value cutoff.
217  Real f_hi = fz_array(i,j,k+1);
218  Real f_lo = fz_array(i,j,k );
219 
221  f_hi = Real(0);
222  }
224  f_lo = Real(0);
225  }
227  f_hi, f_lo, rho_array(i,j,k), dJinv, coef);
229  dq_sed = Real(0);
230  }
231 
232  qp_array(i,j,k) += dq_sed;
233  qp_array(i,j,k) = std::max(Real(0), qp_array(i,j,k));
234  });
235  }
236  }
237  }
238 
239  if (solverChoice.moisture_type == MoistureType::Kessler_NoRain) {
240  if (!do_cond) { return; }
241  for ( MFIter mfi(*tabs,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
242  auto qv_array = mic_fab_vars[MicVar_Kess::qv]->array(mfi);
243  auto qc_array = mic_fab_vars[MicVar_Kess::qcl]->array(mfi);
244  auto qt_array = mic_fab_vars[MicVar_Kess::qt]->array(mfi);
245  auto tabs_array = mic_fab_vars[MicVar_Kess::tabs]->array(mfi);
246  auto theta_array = mic_fab_vars[MicVar_Kess::theta]->array(mfi);
247  auto pres_array = mic_fab_vars[MicVar_Kess::pres]->array(mfi);
248 
249  auto tbx = mfi.tilebox();
250 
251  Real d_fac_cond = m_fac_cond;
252 
253  ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
254  {
255  qc_array(i,j,k) = std::max(Real(0), qc_array(i,j,k));
256 
257  Real qsat, dtqsat;
258 
259  Real pressure = pres_array(i,j,k);
260  // Kessler stores pressure in mbar / hPa for the qsat helpers.
261  erf_qsatw(tabs_array(i,j,k), pressure, qsat);
262  erf_dtqsatw(tabs_array(i,j,k), pressure, dtqsat);
263 
264  const KesslerSaturationAdjustment saturation_adjustment =
265  kessler_saturation_adjustment(qv_array(i,j,k), qc_array(i,j,k), qsat, dtqsat,
266  do_cond, d_fac_cond);
267 
268  qv_array(i,j,k) += -saturation_adjustment.dq_vapor_to_cloud
269  + saturation_adjustment.dq_cloud_to_vapor;
270  qc_array(i,j,k) += saturation_adjustment.dq_vapor_to_cloud
271  - saturation_adjustment.dq_cloud_to_vapor;
272 
273  Real theta_over_T = theta_array(i,j,k)/tabs_array(i,j,k);
274  theta_array(i,j,k) += theta_over_T * d_fac_cond
275  * (saturation_adjustment.dq_vapor_to_cloud - saturation_adjustment.dq_cloud_to_vapor);
276 
277  qv_array(i,j,k) = std::max(Real(0), qv_array(i,j,k));
278  qc_array(i,j,k) = std::max(Real(0), qc_array(i,j,k));
279 
280  qt_array(i,j,k) = qv_array(i,j,k) + qc_array(i,j,k);
281  });
282  }
283  }
284 }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE KesslerSaturationAdjustment kessler_saturation_adjustment(const amrex::Real qv, const amrex::Real qc, const amrex::Real qsat, const amrex::Real dtqsat, const bool do_cond, const amrex::Real latent_over_cp) noexcept
Definition: ERF_KesslerUtils.H:89
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int kessler_num_sedimentation_substeps(const amrex::Real current_reduced_value, const amrex::Real dt, const amrex::Real dzmin) noexcept
Definition: ERF_KesslerUtils.H:62
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE KesslerFaceState kessler_face_state(const int k, const int k_hi, const amrex::Real rho_km1, const amrex::Real rho_k, const amrex::Real qp_km1, const amrex::Real qp_k) noexcept
Definition: ERF_KesslerUtils.H:114
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE KesslerSourceTerms kessler_warm_rain_sources(const amrex::Real qv, const amrex::Real qc, const amrex::Real qp, const amrex::Real rho, const amrex::Real pressure_current_units, const amrex::Real qsat, const amrex::Real dtqsat, const amrex::Real dt, const bool do_cond, const amrex::Real latent_over_cp) noexcept
Definition: ERF_KesslerUtils.H:156
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real kessler_sedimentation_tendency(const amrex::Real fz_hi, const amrex::Real fz_lo, const amrex::Real rho, const amrex::Real dJinv, const amrex::Real coef) noexcept
Definition: ERF_KesslerUtils.H:145
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real kessler_terminal_velocity(const amrex::Real rho, const amrex::Real qp) noexcept
Definition: ERF_KesslerUtils.H:44
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real kessler_rain_accumulation_increment(const amrex::Real precip_mass_per_area) noexcept
Definition: ERF_KesslerUtils.H:72
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real kessler_precip_flux(const amrex::Real rho, const amrex::Real terminal_velocity, const amrex::Real qp) noexcept
Definition: ERF_KesslerUtils.H:54
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool kessler_is_small_sedimentation_value(const amrex::Real value) noexcept
Definition: ERF_KesslerUtils.H:82
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int kessler_face_donor_k(const int k, const int k_hi) noexcept
Definition: ERF_KesslerUtils.H:37
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_dtqsatw(amrex::Real t, amrex::Real p, amrex::Real &dtqsatw)
Definition: ERF_MicrophysicsUtils.H:280
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsatw(amrex::Real t, amrex::Real p, amrex::Real &qsatw)
Definition: ERF_MicrophysicsUtils.H:264
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
auto rho_arr
Definition: ERF_UpdateWSubsidence_SineMassFlux.H:3
amrex::Geometry m_geom
Definition: ERF_Kessler.H:219
amrex::MultiFab * m_detJ_cc
Definition: ERF_Kessler.H:238
amrex::Real m_dzmin
Definition: ERF_Kessler.H:225
amrex::Real m_fac_cond
Definition: ERF_Kessler.H:231
bool m_do_cond
Definition: ERF_Kessler.H:233
amrex::Array< FabPtr, MicVar_Kess::NumVars > mic_fab_vars
Definition: ERF_Kessler.H:241
@ qp
Definition: ERF_Kessler.H:34
@ qcl
Definition: ERF_Kessler.H:32
@ tabs
Definition: ERF_Kessler.H:27
@ pres
Definition: ERF_Kessler.H:28
@ rho
Definition: ERF_Kessler.H:25
@ theta
Definition: ERF_Kessler.H:26
@ qt
Definition: ERF_Kessler.H:30
@ rain_accum
Definition: ERF_Kessler.H:36
@ qv
Definition: ERF_Kessler.H:31
Definition: ERF_KesslerUtils.H:27
amrex::Real rho
Definition: ERF_KesslerUtils.H:28
amrex::Real qp
Definition: ERF_KesslerUtils.H:29
Definition: ERF_KesslerUtils.H:22
amrex::Real dq_cloud_to_vapor
Definition: ERF_KesslerUtils.H:24
amrex::Real dq_vapor_to_cloud
Definition: ERF_KesslerUtils.H:23
Definition: ERF_KesslerUtils.H:15
amrex::Real dq_rain_to_vapor
Definition: ERF_KesslerUtils.H:19
amrex::Real dq_cloud_to_vapor
Definition: ERF_KesslerUtils.H:17
amrex::Real dq_cloud_to_rain
Definition: ERF_KesslerUtils.H:18
amrex::Real dq_vapor_to_cloud
Definition: ERF_KesslerUtils.H:16
MoistureType moisture_type
Moisture or microphysics model.
Definition: ERF_DataStruct.H:2237

Referenced by Advance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Copy_Micro_to_State()

void Kessler::Copy_Micro_to_State ( amrex::MultiFab &  cons_in)
overridevirtual

Updates conserved and microphysics variables in the provided MultiFabs from the internal MultiFabs that store Microphysics module data.

Parameters
[out]consConserved variables
[out]qmoistqv, qc, qi, qr, qs, qg

Reimplemented from NullMoist.

15 {
16  // Get the temperature, density, theta, qt and qp from input
17  for ( MFIter mfi(cons,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
18  const auto& box3d = mfi.tilebox();
19 
20  auto states_arr = cons.array(mfi);
21 
22  auto rho_arr = mic_fab_vars[MicVar_Kess::rho]->array(mfi);
23  auto theta_arr = mic_fab_vars[MicVar_Kess::theta]->array(mfi);
24  auto qv_arr = mic_fab_vars[MicVar_Kess::qv]->array(mfi);
25  auto qc_arr = mic_fab_vars[MicVar_Kess::qcl]->array(mfi);
26  auto qp_arr = mic_fab_vars[MicVar_Kess::qp]->array(mfi);
27 
28  // get potential total density, temperature, qt, qp
29  ParallelFor( box3d, [=] AMREX_GPU_DEVICE (int i, int j, int k)
30  {
31  states_arr(i,j,k,RhoTheta_comp) = rho_arr(i,j,k)*theta_arr(i,j,k);
32  states_arr(i,j,k,RhoQ1_comp) = rho_arr(i,j,k)*qv_arr(i,j,k);
33  states_arr(i,j,k,RhoQ2_comp) = rho_arr(i,j,k)*qc_arr(i,j,k);
34  states_arr(i,j,k,RhoQ3_comp) = rho_arr(i,j,k)*qp_arr(i,j,k);
35  });
36  }
37 
38  // Fill interior ghost cells and periodic boundaries
39  cons.FillBoundary(m_geom.periodicity());
40 }
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:40
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:46
#define RhoQ3_comp
Definition: ERF_IndexDefines.H:47
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:45
auto qv_arr
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:210
@ cons
Definition: ERF_IndexDefines.H:214

Referenced by Update_State_Vars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Copy_State_to_Micro() [1/2]

void Kessler::Copy_State_to_Micro ( const amrex::MultiFab &  cons_in)
overridevirtual

Reimplemented from NullMoist.

Referenced by Update_Micro_Vars().

Here is the caller graph for this function:

◆ Copy_State_to_Micro() [2/2]

void Kessler::Copy_State_to_Micro ( const amrex::MultiFab &  cons_in,
const amrex::MultiFab *  base_state 
)

◆ Define()

void Kessler::Define ( SolverChoice sc)
inlineoverridevirtual

Reimplemented from NullMoist.

95  {
97  // Use one latent-over-cp factor for both the saturation solve and theta
98  // update. L_v comes from ERF_Constants.H; c_p comes from SolverChoice.
99  m_fac_cond = L_v / sc.c_p;
100  m_rdOcp = sc.rdOcp;
101  m_do_cond = (!sc.uses_shoc_family());
103  }
constexpr amrex::Real L_v
Definition: ERF_Constants.H:51
MoistureType m_moisture_type
Definition: ERF_Kessler.H:234
amrex::Real m_rdOcp
Definition: ERF_Kessler.H:232
void set_anelastic_reference_pressure_mode(const SolverChoice &sc)
Definition: ERF_NullMoist.H:155
amrex::Real rdOcp
Ratio of dry-air gas constant to c_p.
Definition: ERF_DataStruct.H:2062
bool uses_shoc_family() const noexcept
Query whether any SHOC-family PBL scheme is active.
Definition: ERF_DataStruct.H:2177
amrex::Real c_p
Specific heat at constant pressure for dry air [J/(kg-K)].
Definition: ERF_DataStruct.H:2061
Here is the call graph for this function:

◆ Get_Surface_Precip_Accumulation_Ptrs()

SurfacePrecipAccumulationSources Kessler::Get_Surface_Precip_Accumulation_Ptrs ( const int &  ) const
inlineoverridevirtual

Reimplemented from NullMoist.

192  {
193  if (m_moisture_type == MoistureType::Kessler_NoRain) {
194  return {};
195  }
196 
198  sources.rain = {mic_fab_vars[MicVar_Kess::rain_accum].get(), rhor / amrex::Real(1000.0)};
199  return sources;
200  }
constexpr amrex::Real rhor
Definition: ERF_MicrophysicsConstants.H:39
Definition: ERF_SurfacePrecipitation.H:34
SurfacePrecipAccumulationSource rain
Definition: ERF_SurfacePrecipitation.H:36

◆ Init()

void Kessler::Init ( const amrex::MultiFab &  cons_in,
const amrex::BoxArray &  grids,
const amrex::Geometry &  geom,
const amrex::Real dt_advance,
std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
std::unique_ptr< amrex::MultiFab > &  detJ_cc 
)
overridevirtual

Initializes the Microphysics module.

Parameters
[in]cons_inConserved variables input
[in]qc_inCloud variables input
[in,out]qv_inVapor variables input
[in]qi_inIce variables input
[in]gridsThe boxes on which we will evolve the solution
[in]geomGeometry associated with these MultiFabs and grids
[in]dt_advanceTimestep for the advance

Reimplemented from NullMoist.

27 {
28  dt = dt_advance;
29  m_geom = geom;
30 
31  m_z_phys_nd = z_phys_nd.get();
32  m_detJ_cc = detJ_cc.get();
33 
34  MicVarMap.resize(m_qmoist_size);
36 
37  // initialize microphysics variables
38  for (auto ivar = 0; ivar < MicVar_Kess::NumVars; ++ivar) {
39  mic_fab_vars[ivar] = std::make_shared<MultiFab>(cons_in.boxArray(), cons_in.DistributionMap(),
40  1, cons_in.nGrowVect());
41  mic_fab_vars[ivar]->setVal(0.);
42  }
43 
44  // Set class data members
45  for ( MFIter mfi(cons_in, TileNoZ()); mfi.isValid(); ++mfi) {
46  const auto& box3d = mfi.tilebox();
47 
48  const auto& lo = lbound(box3d);
49  const auto& hi = ubound(box3d);
50 
51  nlev = box3d.length(2);
52  zlo = lo.z;
53  zhi = hi.z;
54  }
55 }
int zlo
Definition: ERF_Kessler.H:228
amrex::Vector< int > MicVarMap
Definition: ERF_Kessler.H:216
int zhi
Definition: ERF_Kessler.H:228
int nlev
Definition: ERF_Kessler.H:228
amrex::MultiFab * m_z_phys_nd
Definition: ERF_Kessler.H:237
int m_qmoist_size
Definition: ERF_Kessler.H:204
@ NumVars
Definition: ERF_Kessler.H:37
Here is the call graph for this function:

◆ Qmoist_Ptr()

amrex::MultiFab* Kessler::Qmoist_Ptr ( const int &  varIdx)
inlineoverridevirtual

Reimplemented from NullMoist.

164  {
166  return mic_fab_vars[MicVarMap[varIdx]].get();
167  }
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
Here is the call graph for this function:

◆ Qmoist_Restart_Vars()

void Kessler::Qmoist_Restart_Vars ( const SolverChoice ,
std::vector< int > &  a_idx,
std::vector< std::string > &  a_names 
) const
inlineoverridevirtual

Reimplemented from NullMoist.

182  {
183  a_idx.clear();
184  a_names.clear();
185 
186  // NOTE: These are the indices to access into qmoist (not mic_fab_vars)
187  a_idx.push_back(0); a_names.push_back("RainAccum");
188  }

◆ Qmoist_Size()

int Kessler::Qmoist_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

170 { return Kessler::m_qmoist_size; }

◆ Qstate_Moist_NumConc_Size()

int Kessler::Qstate_Moist_NumConc_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

int n_qstate_moist_numconc_size
Definition: ERF_Kessler.H:210

◆ Qstate_Moist_Size()

int Kessler::Qstate_Moist_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

int n_qstate_moist_size
Definition: ERF_Kessler.H:207

◆ Set_dzmin()

void Kessler::Set_dzmin ( const amrex::Real  dz_min)
inlineoverridevirtual

Reimplemented from NullMoist.

117  {
118  m_dzmin = dz_min;
119  }

◆ Update_Micro_Vars() [1/2]

void Kessler::Update_Micro_Vars ( amrex::MultiFab &  cons_in)
inlineoverridevirtual

Reimplemented from NullMoist.

140  {
141  this->Copy_State_to_Micro(cons_in);
142  }
void Copy_State_to_Micro(const amrex::MultiFab &cons_in) override
Here is the call graph for this function:

◆ Update_Micro_Vars() [2/2]

void Kessler::Update_Micro_Vars ( amrex::MultiFab &  cons_in,
const amrex::MultiFab *  base_state 
)
overridevirtual

Reimplemented from NullMoist.

◆ Update_State_Vars()

void Kessler::Update_State_Vars ( amrex::MultiFab &  cons_in,
const amrex::MultiFab &   
)
inlineoverridevirtual

Reimplemented from NullMoist.

148  {
149  this->Copy_Micro_to_State(cons_in);
150  }
void Copy_Micro_to_State(amrex::MultiFab &cons_in) override
Definition: ERF_UpdateKessler.cpp:14
Here is the call graph for this function:

Member Data Documentation

◆ CFL_MAX

constexpr amrex::Real Kessler::CFL_MAX = kessler_sedimentation_cfl_max
staticconstexprprivate

◆ dt

amrex::Real Kessler::dt
private

Referenced by Advance().

◆ m_detJ_cc

amrex::MultiFab* Kessler::m_detJ_cc
private

◆ m_do_cond

bool Kessler::m_do_cond
private

Referenced by Define().

◆ m_dzmin

amrex::Real Kessler::m_dzmin {0.0}
private

Referenced by Set_dzmin().

◆ m_fac_cond

amrex::Real Kessler::m_fac_cond
private

Referenced by Define().

◆ m_geom

amrex::Geometry Kessler::m_geom
private

◆ m_moisture_type

MoistureType Kessler::m_moisture_type = MoistureType::None
private

◆ m_qmoist_size

int Kessler::m_qmoist_size = 1
private

Referenced by Qmoist_Ptr(), and Qmoist_Size().

◆ m_rdOcp

amrex::Real Kessler::m_rdOcp {RdoCp}
private

Referenced by Define().

◆ m_z_phys_nd

amrex::MultiFab* Kessler::m_z_phys_nd
private

◆ mic_fab_vars

amrex::Array<FabPtr, MicVar_Kess::NumVars> Kessler::mic_fab_vars
private

◆ MicVarMap

amrex::Vector<int> Kessler::MicVarMap
private

Referenced by Qmoist_Ptr().

◆ n_qstate_moist_numconc_size

int Kessler::n_qstate_moist_numconc_size = 0
private

◆ n_qstate_moist_size

int Kessler::n_qstate_moist_size = 3
private

Referenced by Qstate_Moist_Size().

◆ nlev

int Kessler::nlev
private

◆ zhi

int Kessler::zhi
private

◆ zlo

int Kessler::zlo
private

The documentation for this class was generated from the following files: