ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_KesslerUtils.H
Go to the documentation of this file.
1 #ifndef ERF_KESSLER_UTILS_H_
2 #define ERF_KESSLER_UTILS_H_
3 
4 #include <algorithm>
5 #include <cmath>
6 #include <limits>
7 
8 #include <AMReX_GpuQualifiers.H>
9 #include <AMReX_REAL.H>
10 
11 #include <ERF_Constants.H>
12 #include <ERF_MicrophysicsUtils.H>
13 
19 };
20 
24 };
25 
29 };
30 
31 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
33  const amrex::Real qp) noexcept
34 {
35  // MUST MATCH: current AdvanceKessler terminal-velocity coefficients.
36  return amrex::Real(36.34)
37  * std::pow(rho * amrex::Real(0.001) * qp, amrex::Real(0.1346))
38  * std::pow(rho / amrex::Real(1.16), -myhalf);
39 }
40 
41 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
43  const amrex::Real terminal_velocity,
44  const amrex::Real qp) noexcept
45 {
46  return rho * terminal_velocity * qp;
47 }
48 
49 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
50 int kessler_num_sedimentation_substeps (const amrex::Real current_reduced_value,
51  const amrex::Real dt,
52  const amrex::Real dzmin) noexcept
53 {
54  // MUST MATCH: current AdvanceKessler CFL_MAX precipitation substep formula.
55  return static_cast<int>(std::ceil((current_reduced_value + std::numeric_limits<amrex::Real>::epsilon())
56  * (dt / dzmin) / myhalf));
57 }
58 
59 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
61 {
62  // MUST MATCH: current AdvanceKessler sedimentation zero threshold literal.
63  return std::fabs(value) < 1e-14;
64 }
65 
66 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
68  const amrex::Real qc,
69  const amrex::Real qsat,
70  const amrex::Real dtqsat,
71  const bool do_cond) noexcept
72 {
74 
75  // MUST MATCH: current AdvanceKessler latent-heat saturation factor.
76  const amrex::Real fac = (L_v / Cp_d) * dtqsat;
77 
78  // MUST MATCH: current AdvanceKessler condensation branch behavior.
79  if ((qv > qsat) && do_cond) {
80  source_terms.dq_vapor_to_cloud = std::min(qv, (qv - qsat) / (amrex::Real(1) + fac));
81  }
82 
83  // MUST MATCH: current AdvanceKessler cloud-evaporation branch behavior.
84  if ((qv < qsat) && (qc > amrex::Real(0)) && do_cond) {
85  source_terms.dq_cloud_to_vapor = std::min(qc, (qsat - qv) / (amrex::Real(1) + fac));
86  }
87 
88  return source_terms;
89 }
90 
91 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
93  const int k_lo,
94  const int k_hi,
95  const amrex::Real rho_km1,
96  const amrex::Real rho_k,
97  const amrex::Real qp_km1,
98  const amrex::Real qp_k) noexcept
99 {
100  KesslerFaceState face_state{amrex::Real(0), amrex::Real(0)};
101 
102  // MUST MATCH: current AdvanceKessler bottom/top face boundary behavior.
103  if (k == k_lo) {
104  face_state.rho = rho_k;
105  face_state.qp = qp_k;
106  } else if (k == k_hi + 1) {
107  face_state.rho = rho_km1;
108  face_state.qp = qp_km1;
109  } else {
110  face_state.rho = myhalf * (rho_km1 + rho_k);
111  face_state.qp = myhalf * (qp_km1 + qp_k);
112  }
113 
114  // MUST MATCH: current AdvanceKessler nonnegative face qp clipping.
115  face_state.qp = std::max(amrex::Real(0), face_state.qp);
116  return face_state;
117 }
118 
119 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
121  const amrex::Real fz_lo,
122  const amrex::Real rho,
123  const amrex::Real dJinv,
124  const amrex::Real coef) noexcept
125 {
126  // MUST MATCH: current AdvanceKessler sedimentation tendency arithmetic order.
127  return dJinv * (amrex::Real(1) / rho) * (fz_hi - fz_lo) * coef;
128 }
129 
130 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
132  const amrex::Real qc,
133  const amrex::Real qp,
134  const amrex::Real rho,
135  const amrex::Real pressure_current_units,
136  const amrex::Real qsat,
137  const amrex::Real dtqsat,
138  const amrex::Real dt,
139  const bool do_cond) noexcept
140 {
141  // Units must match current AdvanceKessler: q* are mass fractions, rho is in
142  // the production density units currently carried by Kessler, pressure is in
143  // the current production mbar units, and dt is in seconds.
144  const KesslerSaturationAdjustment saturation_adjustment =
145  kessler_saturation_adjustment(qv, qc, qsat, dtqsat, do_cond);
146  KesslerSourceTerms source_terms{
147  saturation_adjustment.dq_vapor_to_cloud,
148  saturation_adjustment.dq_cloud_to_vapor,
149  amrex::Real(0),
150  amrex::Real(0)};
151 
152  if ((qp > amrex::Real(0)) && (qv < qsat)) {
153  // MUST MATCH: current AdvanceKessler rain-evaporation coefficients and exponents.
154  const amrex::Real coeff = amrex::Real(1.6)
155  + amrex::Real(124.9) * std::pow(amrex::Real(0.001) * rho * qp, amrex::Real(0.2046));
156  source_terms.dq_rain_to_vapor = amrex::Real(1) / (amrex::Real(0.001) * rho)
157  * (amrex::Real(1) - qv / qsat)
158  * coeff
159  * std::pow(amrex::Real(0.001) * rho * qp, amrex::Real(0.525))
160  / (amrex::Real(5.4e5) + amrex::Real(2.55e6) / (pressure_current_units * qsat))
161  * dt;
162  source_terms.dq_rain_to_vapor = std::min({qp, source_terms.dq_rain_to_vapor});
163  }
164 
165  if (qc > amrex::Real(0)) {
166  const amrex::Real qcc = qc;
167  amrex::Real auto_r = amrex::Real(0);
168  if (qcc > qcw0) {
169  // MUST MATCH: current AdvanceKessler autoconversion trigger.
170  auto_r = alphaelq;
171  }
172 
173  // MUST MATCH: current AdvanceKessler accretion coefficient and exponent.
174  amrex::Real accrr = amrex::Real(0);
175  accrr = amrex::Real(2.2) * std::pow(qp, amrex::Real(0.875));
176  source_terms.dq_cloud_to_rain = dt * (accrr * qcc + auto_r * (qcc - qcw0));
177  source_terms.dq_cloud_to_rain = std::min(source_terms.dq_cloud_to_rain, qc);
178  }
179 
180  return source_terms;
181 }
182 
183 #endif
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:23
constexpr amrex::Real alphaelq
Definition: ERF_Constants.H:59
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:11
constexpr amrex::Real qcw0
Definition: ERF_Constants.H:57
constexpr amrex::Real L_v
Definition: ERF_Constants.H:27
amrex::Real value
Definition: ERF_HurricaneDiagnostics.H:20
rho
Definition: ERF_InitCustomPert_Bubble.H:106
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) noexcept
Definition: ERF_KesslerUtils.H:67
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:50
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) noexcept
Definition: ERF_KesslerUtils.H:131
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE KesslerFaceState kessler_face_state(const int k, const int k_lo, 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:92
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:120
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:32
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:42
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool kessler_is_small_sedimentation_value(const amrex::Real value) noexcept
Definition: ERF_KesslerUtils.H:60
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ qp
Definition: ERF_Kessler.H:31
@ qv
Definition: ERF_Kessler.H:28
@ qc
Definition: ERF_SatAdj.H:36
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
Definition: ERF_KesslerUtils.H:26
amrex::Real rho
Definition: ERF_KesslerUtils.H:27
amrex::Real qp
Definition: ERF_KesslerUtils.H:28
Definition: ERF_KesslerUtils.H:21
amrex::Real dq_cloud_to_vapor
Definition: ERF_KesslerUtils.H:23
amrex::Real dq_vapor_to_cloud
Definition: ERF_KesslerUtils.H:22
Definition: ERF_KesslerUtils.H:14
amrex::Real dq_rain_to_vapor
Definition: ERF_KesslerUtils.H:18
amrex::Real dq_cloud_to_vapor
Definition: ERF_KesslerUtils.H:16
amrex::Real dq_cloud_to_rain
Definition: ERF_KesslerUtils.H:17
amrex::Real dq_vapor_to_cloud
Definition: ERF_KesslerUtils.H:15