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

#include <ERF_WaterVaporSaturation.H>

Collaboration diagram for WaterVaporSat:

Static Public Member Functions

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real svp_water (const amrex::Real &t)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real svp_ice (const amrex::Real &t)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real svp_trans (const amrex::Real &t)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real tq_enthalpy (const amrex::Real &t, const amrex::Real &q, const amrex::Real &hltalt)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void no_ip_hltalt (const amrex::Real &t, amrex::Real &hltalt)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void calc_hltalt (const amrex::Real &t, amrex::Real &hltalt, amrex::Real *tterm=nullptr)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void deriv_outputs (const amrex::Real &t, const amrex::Real &p, const amrex::Real &es, const amrex::Real &qs, const amrex::Real &hltalt, const amrex::Real &tterm, amrex::Real &gam, amrex::Real &dqsdt)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void qsat (const amrex::Real &t, const amrex::Real &p, amrex::Real &es, amrex::Real &qs, amrex::Real *gam=nullptr, amrex::Real *dqsdt=nullptr, amrex::Real *enthalpy=nullptr)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void qsat_water (const amrex::Real &t, const amrex::Real &p, amrex::Real &es, amrex::Real &qs, amrex::Real *gam=nullptr, amrex::Real *dqsdt=nullptr, amrex::Real *enthalpy=nullptr)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void qsat_ice (const amrex::Real &t, const amrex::Real &p, amrex::Real &es, amrex::Real &qs, amrex::Real &gam, amrex::Real &dqsdt, amrex::Real &enthalpy)
 
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void findsp (const amrex::Real &q, const amrex::Real &t, const amrex::Real &p, const bool &use_ice, amrex::Real &tsp, amrex::Real &qsp, int &status)
 

Static Public Attributes

static constexpr amrex::Real tmin = 127.16
 
static constexpr amrex::Real tmax = 375.16
 
static constexpr int npcf = 5
 
static constexpr const amrex::Real pcf [npcf]
 

Member Function Documentation

◆ calc_hltalt()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void WaterVaporSat::calc_hltalt ( const amrex::Real &  t,
amrex::Real &  hltalt,
amrex::Real *  tterm = nullptr 
)
inlinestatic
92  {
93  amrex::Real tc, weight;
94  no_ip_hltalt(t, hltalt);
95  if (t < tmelt) {
96  // Weighting of hlat accounts for transition from water to ice.
97  tc = t - tmelt;
98  if (tc >= -ttrice) {
99  weight = -tc/ttrice;
100 
101  // polynomial expression approximates difference between es
102  // over water and es over ice from 0 to -ttrice (C) (max of
103  // ttrice is 40): required for accurate estimate of es
104  // derivative in transition range from ice to water
105 
106  if (tterm)
107  {
108  for(auto i = npcf-1; i > 0; --i) *tterm = pcf[i] + tc*(*tterm);
109  *tterm = *tterm/ttrice;
110  }
111  }
112  else {
113  weight = 1.0;
114  }
115 
116  hltalt = hltalt + weight*lat_ice;
117  }
118  }
constexpr amrex::Real tmelt
Definition: ERF_Constants.H:88
constexpr amrex::Real ttrice
Definition: ERF_Constants.H:91
constexpr amrex::Real lat_ice
Definition: ERF_Constants.H:86
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void no_ip_hltalt(const amrex::Real &t, amrex::Real &hltalt)
Definition: ERF_WaterVaporSaturation.H:76
static constexpr int npcf
Definition: ERF_WaterVaporSaturation.H:39
static constexpr const amrex::Real pcf[npcf]
Definition: ERF_WaterVaporSaturation.H:40

Referenced by findsp(), and qsat().

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

◆ deriv_outputs()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void WaterVaporSat::deriv_outputs ( const amrex::Real &  t,
const amrex::Real &  p,
const amrex::Real &  es,
const amrex::Real &  qs,
const amrex::Real &  hltalt,
const amrex::Real &  tterm,
amrex::Real &  gam,
amrex::Real &  dqsdt 
)
inlinestatic
129  {
130 
131  // Local variables
132  amrex::Real desdt; // d(es)/dt
133  amrex::Real dqsdt_loc; // local copy of dqsdt
134 
135  if (qs == 1.0) {
136  dqsdt_loc = 0.;
137  }
138  else {
139  desdt = hltalt*es/(R_v*t*t) + tterm;
140  dqsdt_loc = qs*p*desdt/(es*(p-omeps*es));
141  }
142 
143  dqsdt = dqsdt_loc;
144  gam = dqsdt_loc * (hltalt/Cp_d);
145  }
constexpr amrex::Real R_v
Definition: ERF_Constants.H:11
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:12
constexpr amrex::Real omeps
Definition: ERF_Constants.H:93

Referenced by qsat(), qsat_ice(), and qsat_water().

Here is the caller graph for this function:

◆ findsp()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void WaterVaporSat::findsp ( const amrex::Real &  q,
const amrex::Real &  t,
const amrex::Real &  p,
const bool &  use_ice,
amrex::Real &  tsp,
amrex::Real &  qsp,
int &  status 
)
inlinestatic
268  {
269 
270  //
271  // local variables
272  //
273  int iter = 8; // max number of times to iterate the calculation
274 
275  amrex::Real es; // sat. vapor pressure
276  amrex::Real gam; // change in sat spec. hum. wrt temperature (times hltalt/cpair)
277  amrex::Real dgdt; // work variable
278  amrex::Real g; // work variable
279  amrex::Real hltalt; // lat. heat. of vap.
280  amrex::Real qs; // spec. hum. of water vapor
281 
282  // work variables
283  amrex::Real t1, q1, dt, dq;
284  amrex::Real qvd;
285  amrex::Real r1b, c1, c2, c3;
286  constexpr amrex::Real dttol = 1.e-4; // the relative temp error tolerance required to quit the iteration
287  constexpr amrex::Real dqtol = 1.e-4; // the relative moisture error tolerance required to quit the iteration
288  amrex::Real enin, enout;
289 
290  c3 = 287.04*(7.5*log(10.))/Cp_d;
291 
292  // Saturation specific humidity at this temperature
293  if (use_ice) {
294  qsat(t, p, es, qs);
295  }
296  else {
297  qsat_water(t, p, es, qs);
298  }
299 
300  // make sure a meaningful calculation is possible
301  if (p <= 5.*es || qs <= 0. || qs >= 0.5 || t < tmin || t > tmax) {
302  status = 1;
303  // Keep initial parameters when conditions aren't suitable
304  tsp = t;
305  qsp = q;
306  enin = 1.;
307  enout = 1.;
308  return;
309  }
310 
311  // Prepare to iterate
312  status = 2;
313 
314  // Get initial enthalpy
315  if (use_ice)
316  calc_hltalt(t,hltalt);
317  else
318  no_ip_hltalt(t,hltalt);
319 
320  enin = tq_enthalpy(t, q, hltalt);
321 
322  // make a guess at the wet bulb temp using a UKMO algorithm (from J. Petch)
323  c1 = hltalt*c3;
324  c2 = std::pow(t + 36., 2);
325  r1b = c2/(c2 + c1*qs);
326  qvd = r1b * (q - qs);
327  tsp = t + ((hltalt/Cp_d)*qvd);
328 
329  // Generate qsp, gam, and enout from tsp.
330  if (use_ice)
331  qsat(tsp, p, es, qsp, &gam, &enout);
332  else
333  qsat_water(tsp, p, es, qsp, &gam, &enout);
334 
335  // iterate on first guess
336  for(auto l = 1; l < iter; ++l) {
337 
338  g = enin - enout;
339  dgdt = -Cp_d * (1 + gam);
340 
341  // New tsp
342  t1 = tsp - g/dgdt;
343  dt = abs(t1 - tsp)/t1;
344  tsp = t1;
345 
346  // bail out if past end of temperature range
347  if ( tsp < tmin ) {
348  tsp = tmin;
349  // Get latent heat and set qsp to a value
350  // that preserves enthalpy.
351  if (use_ice)
352  calc_hltalt(tsp,hltalt);
353  else
354  no_ip_hltalt(tsp,hltalt);
355 
356  qsp = (enin - Cp_d*tsp)/hltalt;
357  enout = tq_enthalpy(tsp, qsp, hltalt);
358  status = 4;
359  break;
360  }
361 
362  // Re-generate qsp, gam, and enout from new tsp.
363  if (use_ice)
364  qsat(tsp, p, es, q1, &gam, &enout);
365  else
366  qsat_water(tsp, p, es, q1, &gam, &enout);
367 
368  dq = abs(q1 - qsp)/std::max(q1,1.e-12);
369  qsp = q1;
370 
371  // if converged at this point, exclude it from more iterations
372  if (dt < dttol && dq < dqtol) {
373  status = 0;
374  break;
375  }
376  }
377  // Test for enthalpy conservation
378  if (abs((enin-enout)/(enin+enout)) > 1.e-4) status = 8;
379  return;
380  }
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void calc_hltalt(const amrex::Real &t, amrex::Real &hltalt, amrex::Real *tterm=nullptr)
Definition: ERF_WaterVaporSaturation.H:90
static constexpr amrex::Real tmax
Definition: ERF_WaterVaporSaturation.H:33
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void qsat(const amrex::Real &t, const amrex::Real &p, amrex::Real &es, amrex::Real &qs, amrex::Real *gam=nullptr, amrex::Real *dqsdt=nullptr, amrex::Real *enthalpy=nullptr)
Definition: ERF_WaterVaporSaturation.H:152
static constexpr amrex::Real tmin
Definition: ERF_WaterVaporSaturation.H:32
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void qsat_water(const amrex::Real &t, const amrex::Real &p, amrex::Real &es, amrex::Real &qs, amrex::Real *gam=nullptr, amrex::Real *dqsdt=nullptr, amrex::Real *enthalpy=nullptr)
Definition: ERF_WaterVaporSaturation.H:191
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real tq_enthalpy(const amrex::Real &t, const amrex::Real &q, const amrex::Real &hltalt)
Definition: ERF_WaterVaporSaturation.H:67
Here is the call graph for this function:

◆ no_ip_hltalt()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void WaterVaporSat::no_ip_hltalt ( const amrex::Real &  t,
amrex::Real &  hltalt 
)
inlinestatic
77  {
78  hltalt = lat_vap;
79  // Account for change of lat_vap with t above freezing where
80  // constant slope is given by -2369 j/(kg c) = cpv - cw
81  if (t >= tmelt) hltalt = hltalt - 2369.0*(t-tmelt);
82  }
constexpr amrex::Real lat_vap
Definition: ERF_Constants.H:85

Referenced by calc_hltalt(), findsp(), and qsat_water().

Here is the caller graph for this function:

◆ qsat()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void WaterVaporSat::qsat ( const amrex::Real &  t,
const amrex::Real &  p,
amrex::Real &  es,
amrex::Real &  qs,
amrex::Real *  gam = nullptr,
amrex::Real *  dqsdt = nullptr,
amrex::Real *  enthalpy = nullptr 
)
inlinestatic
158  {
159  // Local variables
160  amrex::Real hltalt; // Modified latent heat for T derivatives
161  amrex::Real tterm = 0.0; // Account for d(es)/dT in transition region
162 
163  es = svp_trans(t); //estblf(t);
164 
165  qs = SatMethods::wv_sat_svp_to_qsat(es, p);
166 
167  // Ensures returned es is consistent with limiters on qs.
168  es = std::min(es, p);
169 
170  // Calculate optional arguments.
171  // "generalized" analytic expression for t derivative of es
172  // accurate to within 1 percent for 173.16 < t < 373.16
173  calc_hltalt(t, hltalt, &tterm);
174 
175  if (enthalpy)
176  {
177  *enthalpy = tq_enthalpy(t, qs, hltalt);
178  }
179 
180  if (gam && dqsdt)
181  {
182  deriv_outputs(t, p, es, qs, hltalt, tterm, *gam, *dqsdt);
183  }
184  }
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real wv_sat_svp_to_qsat(const amrex::Real &es, const amrex::Real &p)
Definition: ERF_Sat_methods.H:42
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real svp_trans(const amrex::Real &t)
Definition: ERF_WaterVaporSaturation.H:60
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void deriv_outputs(const amrex::Real &t, const amrex::Real &p, const amrex::Real &es, const amrex::Real &qs, const amrex::Real &hltalt, const amrex::Real &tterm, amrex::Real &gam, amrex::Real &dqsdt)
Definition: ERF_WaterVaporSaturation.H:122

Referenced by AerRadProps::aer_rad_props_lw(), AerRadProps::aer_rad_props_sw(), findsp(), and ModalAeroWateruptake::modal_aero_wateruptake_dr().

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

◆ qsat_ice()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void WaterVaporSat::qsat_ice ( const amrex::Real &  t,
const amrex::Real &  p,
amrex::Real &  es,
amrex::Real &  qs,
amrex::Real &  gam,
amrex::Real &  dqsdt,
amrex::Real &  enthalpy 
)
inlinestatic
231  {
232  // Local variables
233  amrex::Real hltalt; // Modified latent heat for T derivatives
234 
235  SatMethods::wv_sat_qsat_ice(t, p, es, qs);
236 
237  // For pure ice, just add latent heats.
238  hltalt = lat_vap + lat_ice;
239 
240  enthalpy = tq_enthalpy(t, qs, hltalt);
241 
242  // For pure water/ice transition term is 0.
243  deriv_outputs(t, p, es, qs, hltalt, 0., gam, dqsdt);
244  }
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void wv_sat_qsat_ice(const amrex::Real &t, const amrex::Real &p, amrex::Real &es, amrex::Real &qs, const int idx=1)
Definition: ERF_Sat_methods.H:66
Here is the call graph for this function:

◆ qsat_water()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void WaterVaporSat::qsat_water ( const amrex::Real &  t,
const amrex::Real &  p,
amrex::Real &  es,
amrex::Real &  qs,
amrex::Real *  gam = nullptr,
amrex::Real *  dqsdt = nullptr,
amrex::Real *  enthalpy = nullptr 
)
inlinestatic
197  {
198  // Local variables
199  amrex::Real hltalt; // Modified latent heat for T derivatives
200 
201  SatMethods::wv_sat_qsat_water(t, p, es, qs);
202 
203  // "generalized" analytic expression for t derivative of es
204  // accurate to within 1 percent for 173.16 < t < 373.16
205 
206  no_ip_hltalt(t, hltalt);
207 
208  if (enthalpy)
209  {
210  *enthalpy = tq_enthalpy(t, qs, hltalt);
211  }
212 
213  if (gam && dqsdt)
214  {
215  // For pure water/ice transition term is 0.
216  deriv_outputs(t, p, es, qs, hltalt, 0., *gam, *dqsdt);
217  }
218  }
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void wv_sat_qsat_water(const amrex::Real &t, const amrex::Real &p, amrex::Real &es, amrex::Real &qs, const int idx=1)
Definition: ERF_Sat_methods.H:51

Referenced by findsp().

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

◆ svp_ice()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real WaterVaporSat::svp_ice ( const amrex::Real &  t)
inlinestatic
54  {
56  }
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real wv_sat_svp_ice(const amrex::Real &t, const int idx=1)
Definition: ERF_Sat_methods.H:114
Here is the call graph for this function:

◆ svp_trans()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real WaterVaporSat::svp_trans ( const amrex::Real &  t)
inlinestatic
60  {
62  }
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real wv_sat_svp_trans(const amrex::Real &t, const int idx=1)
Definition: ERF_Sat_methods.H:131

Referenced by qsat().

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

◆ svp_water()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real WaterVaporSat::svp_water ( const amrex::Real &  t)
inlinestatic
48  {
50  }
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real wv_sat_svp_water(const amrex::Real &t, const int idx=1)
Definition: ERF_Sat_methods.H:97
Here is the call graph for this function:

◆ tq_enthalpy()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real WaterVaporSat::tq_enthalpy ( const amrex::Real &  t,
const amrex::Real &  q,
const amrex::Real &  hltalt 
)
inlinestatic
69  {
70  return Cp_d * t + hltalt * q;
71  }

Referenced by findsp(), qsat(), qsat_ice(), and qsat_water().

Here is the caller graph for this function:

Member Data Documentation

◆ npcf

constexpr int WaterVaporSat::npcf = 5
staticconstexpr

Referenced by calc_hltalt().

◆ pcf

constexpr const amrex::Real WaterVaporSat::pcf[npcf]
staticconstexpr
Initial value:
= {5.04469588506e-01,
-5.47288442819e+00,
-3.67471858735e-01,
-8.95963532403e-03,
-7.78053686625e-05}

Referenced by calc_hltalt().

◆ tmax

constexpr amrex::Real WaterVaporSat::tmax = 375.16
staticconstexpr

Referenced by findsp().

◆ tmin

constexpr amrex::Real WaterVaporSat::tmin = 127.16
staticconstexpr

Referenced by findsp().


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