ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_MicrophysicsUtils.H
Go to the documentation of this file.
1 /*
2  * utility tools for microphysics
3  *
4  */
5 #ifndef ERF_Microphysics_Utils_H
6 #define ERF_Microphysics_Utils_H
7 
8 #include <cmath>
9 #include <vector>
10 #include <AMReX_REAL.H>
11 #include <AMReX_Array.H>
12 #include <ERF_Constants.H>
13 
14 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
16  return std::exp(lgamma(x));
17 }
18 
19 // Saturation vapor pressure of ice [mbar]
20 //
21 // From Flatau et al. (1992):
22 // https://doi.org/amrex::Real(10.1175)/1520-0450(1992)031<1507:PFTSVP>two.CO;2
23 // Coefficients come from Table 4 and the data is valid over a
24 // temperature range of [-90 0] C. Return 0 if above this temp range.
25 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
27  amrex::Real const a0 = amrex::Real(6.11147274);
28  amrex::Real const a1 = amrex::Real(0.503160820);
29  amrex::Real const a2 = amrex::Real(0.188439774e-1);
30  amrex::Real const a3 = amrex::Real(0.420895665e-3);
31  amrex::Real const a4 = amrex::Real(0.615021634e-5);
32  amrex::Real const a5 = amrex::Real(0.602588177e-7);
33  amrex::Real const a6 = amrex::Real(0.385852041e-9);
34  amrex::Real const a7 = amrex::Real(0.146898966e-11);
35  amrex::Real const a8 = amrex::Real(0.252751365e-14);
36 
37  amrex::Real dtt = t-amrex::Real(273.16);
38  AMREX_ALWAYS_ASSERT(dtt>-90);
39 
40  amrex::Real esati;
41  if (dtt > amrex::Real(0)) {
42  esati = amrex::Real(0);
43  } else {
44  esati = a0 + dtt*(a1+dtt*(a2+dtt*(a3+dtt*(a4+dtt*(a5+dtt*(a6+dtt*(a7+a8*dtt)))))));
45  }
46  return esati;
47 }
48 
49 // From Clausius-Clapeyron
50 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
52  constexpr amrex::Real svp1 = amrex::Real(0.6112);
53  constexpr amrex::Real svp2 = amrex::Real(17.67);
54  constexpr amrex::Real svp3 = amrex::Real(29.65);
55  constexpr amrex::Real svpt0 = amrex::Real(273.15);
56  // NOTE: units of
57  amrex::Real esatw = amrex::Real(10.0) * svp1 * std::exp(svp2 * (t - svpt0) / (t - svp3));
58  return esatw;
59 }
60 
61 // Saturation vapor pressure of water vapor [mbar]
62 //
63 // From Flatau et al. (1992):
64 // https://doi.org/amrex::Real(10.1175)/1520-0450(1992)031<1507:PFTSVP>two.CO;2
65 // Coefficients come from Table 4 and the data is valid over a
66 // temperature range of [-85 70] C. Assert we are in this temp range.
67 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
69 {
70  amrex::Real esatw;
71  if (use_empirical) {
72  esatw = exp(amrex::Real(34.494) - amrex::Real(4924.99)/(t - amrex::Real(273.15) + amrex::Real(237.1))) / std::pow(t - amrex::Real(273.15) + amrex::Real(105.0),amrex::Real(1.57));
73  } else {
74  amrex::Real const a0 = amrex::Real(6.11239921);
75  amrex::Real const a1 = amrex::Real(0.443987641);
76  amrex::Real const a2 = amrex::Real(0.142986287e-1);
77  amrex::Real const a3 = amrex::Real(0.264847430e-3);
78  amrex::Real const a4 = amrex::Real(0.302950461e-5);
79  amrex::Real const a5 = amrex::Real(0.206739458e-7);
80  amrex::Real const a6 = amrex::Real(0.640689451e-10);
81  amrex::Real const a7 = -amrex::Real(0.952447341e-13);
82  amrex::Real const a8 = -amrex::Real(0.976195544e-15);
83 
84  amrex::Real dtt = t-amrex::Real(273.16);
85  if (dtt>-85 && dtt<amrex::Real(70.0)) {
86  esatw = a0 + dtt*(a1+dtt*(a2+dtt*(a3+dtt*(a4+dtt*(a5+dtt*(a6+dtt*(a7+a8*dtt)))))));
87  } else {
88  esatw = erf_esatw_cc(t);
89  }
90  }
91  return esatw;
92 }
93 
94 // From Flatau et al. (1992):
95 // https://doi.org/amrex::Real(10.1175)/1520-0450(1992)031<1507:PFTSVP>two.CO;2
96 // Coefficients come from Table 4 and the data is valid over a
97 // temperature range of [-90 0] C. Return 0 if above this temp range.
98 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
100  amrex::Real const a0 = amrex::Real(0.503223089);
101  amrex::Real const a1 = amrex::Real(0.377174432e-1);
102  amrex::Real const a2 = amrex::Real(0.126710138e-2);
103  amrex::Real const a3 = amrex::Real(0.249065913e-4);
104  amrex::Real const a4 = amrex::Real(0.312668753e-6);
105  amrex::Real const a5 = amrex::Real(0.255653718e-8);
106  amrex::Real const a6 = amrex::Real(0.132073448e-10);
107  amrex::Real const a7 = amrex::Real(0.390204672e-13);
108  amrex::Real const a8 = amrex::Real(0.497275778e-16);
109 
110  amrex::Real dtt = t-amrex::Real(273.16);
111  AMREX_ALWAYS_ASSERT(dtt>-85);
112  amrex::Real dtesati;
113  if (dtt > amrex::Real(0)) {
114  dtesati = amrex::Real(0);
115  } else {
116  dtesati = a0 + dtt*(a1+dtt*(a2+dtt*(a3+dtt*(a4+dtt*(a5+dtt*(a6+dtt*(a7+a8*dtt)))))));
117  }
118  return dtesati;
119 }
120 
121 // From Clausius-Clapeyron
122 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
124  constexpr amrex::Real svp1 = amrex::Real(0.6112);
125  constexpr amrex::Real svp2 = amrex::Real(17.67);
126  constexpr amrex::Real svp3 = amrex::Real(29.65);
127  constexpr amrex::Real svpt0 = amrex::Real(273.15);
128  amrex::Real dtesatw = amrex::Real(10.0) * svp1 * svp2 * std::exp(svp2 * (t - svpt0) / (t - svp3))
129  * (svpt0 - svp3) / ((t - svp3) * (t - svp3));
130  return dtesatw;
131 }
132 
133 // From Flatau et al. (1992):
134 // https://doi.org/amrex::Real(10.1175)/1520-0450(1992)031<1507:PFTSVP>two.CO;2
135 // Coefficients come from Table 4 and the data is valid over a
136 // temperature range of [-85 70] C. Assert we are in this temp range.
137 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
139  amrex::Real const a0 = amrex::Real(0.443956472);
140  amrex::Real const a1 = amrex::Real(0.285976452e-1);
141  amrex::Real const a2 = amrex::Real(0.794747212e-3);
142  amrex::Real const a3 = amrex::Real(0.121167162e-4);
143  amrex::Real const a4 = amrex::Real(0.103167413e-6);
144  amrex::Real const a5 = amrex::Real(0.385208005e-9);
145  amrex::Real const a6 = -amrex::Real(0.604119582e-12);
146  amrex::Real const a7 = -amrex::Real(0.792933209e-14);
147  amrex::Real const a8 = -amrex::Real(0.599634321e-17);
148 
149  amrex::Real dtt = t-amrex::Real(273.16); // Goff-Gratch
150  amrex::Real dtesatw;
151  if (dtt>-amrex::Real(85.0) && dtt<amrex::Real(70.)) {
152  dtesatw = a0 + dtt*(a1+dtt*(a2+dtt*(a3+dtt*(a4+dtt*(a5+dtt*(a6+dtt*(a7+a8*dtt)))))));
153  } else {
154  dtesatw = erf_dtesatw_cc(t);
155  }
156  return dtesatw;
157 }
158 
159 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
161  amrex::Real esati;
162  esati = erf_esati(t);
163  qsati = Rd_on_Rv*esati/std::max(esati,p-esati);
164 }
165 
166 /* saturated water vapor mixing ratio
167  * t: temperature [K]
168  * p: pressure [mbar]
169  */
170 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
172  amrex::Real esatw;
173  esatw = erf_esatw(t);
174  qsatw = Rd_on_Rv*esatw/std::max(esatw,p-esatw);
175 }
176 
177 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
179  amrex::Real esati = erf_esati(t);
180  amrex::Real dtesati = erf_dtesati(t);
181  amrex::Real denom = p - esati;
182  dtqsati = Rd_on_Rv * dtesati * p / (denom * denom);
183 }
184 
185 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
187  amrex::Real esatw = erf_esatw(t);
188  amrex::Real dtesatw = erf_dtesatw(t);
189  amrex::Real denom = p - esatw;
190  dtqsatw = Rd_on_Rv * dtesatw * p / (denom * denom);
191 }
192 
193 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
195  amrex::Real vonk = amrex::Real(0.4);
196  amrex::Real eps = amrex::Real(1.0e-10);
197  amrex::Real am = amrex::Real(4.8);
198  amrex::Real bm = amrex::Real(19.3);
199  amrex::Real c1 = amrex::Real(3.14159)/two - three*log(two);
200  amrex::Real rlmo = -bflx*vonk/(ustar*ustar*ustar+eps);
201  amrex::Real zeta = std::min(amrex::Real(1),z*rlmo);
202  amrex::Real x;
203  amrex::Real psi1;
204  if(zeta >= amrex::Real(0)) {
205  psi1 = -am*zeta;
206  }
207  else {
208  x = std::sqrt(sqrt(amrex::Real(1)-bm*zeta));
209  psi1 = two*std::log(amrex::Real(1)+x) + std::log(amrex::Real(1)+x*x) -two*std::atan(x) + c1;
210  }
211  amrex::Real lnz = std::max(amrex::Real(0), vonk*wnd/(ustar+eps) +psi1);
212  z0 = z*std::exp(-lnz);
213 }
214 
215 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
217  amrex::Real vrain,
218  amrex::Real vsnow,
219  amrex::Real vgrau,
222 {
223  amrex::Real term_vel = amrex::Real(0);
224  if(qploc > qp_threshold) {
225  amrex::Real omp = std::max(amrex::Real(0),std::min(amrex::Real(1),(tabs-tprmin)*a_pr));
226  amrex::Real omg = std::max(amrex::Real(0),std::min(amrex::Real(1),(tabs-tgrmin)*a_gr));
227  amrex::Real qrr = omp*qploc;
228  amrex::Real qss = (amrex::Real(1)-omp)*(amrex::Real(1)-omg)*qploc;
229  amrex::Real qgg = (amrex::Real(1)-omp)*(omg)*qploc;
230  term_vel = omp*vrain*std::pow(rho*qrr,crain)
231  + (amrex::Real(1)-omp)*( (amrex::Real(1)-omg)*vsnow*std::pow(rho*qss,csnow)
232  + omg *vgrau*std::pow(rho*qgg,cgrau) );
233  }
234  return term_vel;
235 }
236 
237 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
239  return std::max(amrex::Real(0),y);
240 }
241 
242 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
244  return -std::min(amrex::Real(0),y);
245 }
246 #endif
constexpr amrex::Real csnow
Definition: ERF_Constants.H:92
constexpr amrex::Real three
Definition: ERF_Constants.H:9
constexpr amrex::Real a_gr
Definition: ERF_Constants.H:89
constexpr amrex::Real Rd_on_Rv
Definition: ERF_Constants.H:97
constexpr amrex::Real cgrau
Definition: ERF_Constants.H:93
constexpr amrex::Real two
Definition: ERF_Constants.H:8
constexpr amrex::Real tprmin
Definition: ERF_Constants.H:43
constexpr amrex::Real qp_threshold
Definition: ERF_Constants.H:70
constexpr amrex::Real crain
Definition: ERF_Constants.H:91
constexpr amrex::Real tgrmin
Definition: ERF_Constants.H:45
constexpr amrex::Real a_pr
Definition: ERF_Constants.H:88
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:8
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
rho
Definition: ERF_InitCustomPert_Bubble.H:106
bool use_empirical
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:25
Real * t
Definition: ERF_InitCustomPert_SquallLine.H:60
Real * p
Definition: ERF_InitCustomPert_SquallLine.H:61
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_dtesatw(amrex::Real t)
Definition: ERF_MicrophysicsUtils.H:138
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_dtqsatw(amrex::Real t, amrex::Real p, amrex::Real &dtqsatw)
Definition: ERF_MicrophysicsUtils.H:186
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_dtesati(amrex::Real t)
Definition: ERF_MicrophysicsUtils.H:99
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_esati(amrex::Real t)
Definition: ERF_MicrophysicsUtils.H:26
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pn(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:243
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void z0_est(amrex::Real z, amrex::Real bflx, amrex::Real wnd, amrex::Real ustar, amrex::Real &z0)
Definition: ERF_MicrophysicsUtils.H:194
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_dtesatw_cc(amrex::Real t)
Definition: ERF_MicrophysicsUtils.H:123
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_dtqsati(amrex::Real t, amrex::Real p, amrex::Real &dtqsati)
Definition: ERF_MicrophysicsUtils.H:178
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real term_vel_qp(amrex::Real qploc, amrex::Real vrain, amrex::Real vsnow, amrex::Real vgrau, amrex::Real rho, amrex::Real tabs)
Definition: ERF_MicrophysicsUtils.H:216
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsatw(amrex::Real t, amrex::Real p, amrex::Real &qsatw)
Definition: ERF_MicrophysicsUtils.H:171
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_gammafff(amrex::Real x)
Definition: ERF_MicrophysicsUtils.H:15
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsati(amrex::Real t, amrex::Real p, amrex::Real &qsati)
Definition: ERF_MicrophysicsUtils.H:160
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:238
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_esatw(amrex::Real t, bool use_empirical=false)
Definition: ERF_MicrophysicsUtils.H:68
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_esatw_cc(amrex::Real t)
Definition: ERF_MicrophysicsUtils.H:51
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ tabs
Definition: ERF_Kessler.H:24
real(c_double), parameter svp1
Definition: ERF_module_model_constants.F90:78
real(c_double), parameter a2
Definition: ERF_module_model_constants.F90:95
real(c_double), parameter a3
Definition: ERF_module_model_constants.F90:96
real(c_double), parameter svp3
Definition: ERF_module_model_constants.F90:80
real(c_double), parameter svp2
Definition: ERF_module_model_constants.F90:79
real(c_double), parameter a4
Definition: ERF_module_model_constants.F90:97
real(c_double), parameter svpt0
Definition: ERF_module_model_constants.F90:81
real(c_double), private c1
Definition: ERF_module_mp_morr_two_moment.F90:212