ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_AdvanceMorrison.cpp File Reference
#include <string>
#include <vector>
#include <memory>
#include <complex>
#include <cmath>
#include <AMReX_Math.H>
#include <AMReX_FArrayBox.H>
#include <AMReX_Geometry.H>
#include <AMReX_TableData.H>
#include <AMReX_MultiFabUtil.H>
#include "ERF.H"
#include "ERF_Constants.H"
#include "ERF_MicrophysicsUtils.H"
#include "ERF_IndexDefines.H"
#include "ERF_DataStruct.H"
#include "ERF_NullMoist.H"
#include "ERF_Morrison.H"
Include dependency graph for ERF_AdvanceMorrison.cpp:

Namespaces

 MORRInd
 

Enumerations

enum  {
  MORRInd::lamc = 0 , MORRInd::lami , MORRInd::lams , MORRInd::lamr ,
  MORRInd::lamg , MORRInd::cdist1 , MORRInd::n0i , MORRInd::n0s ,
  MORRInd::n0r , MORRInd::n0g , MORRInd::pgam , MORRInd::qc3dten ,
  MORRInd::qi3dten , MORRInd::qni3dten , MORRInd::qr3dten , MORRInd::ni3dten ,
  MORRInd::ns3dten , MORRInd::nr3dten , MORRInd::qc3d , MORRInd::qi3d ,
  MORRInd::qni3d , MORRInd::qr3d , MORRInd::ni3d , MORRInd::ns3d ,
  MORRInd::nr3d , MORRInd::t3dten , MORRInd::qv3dten , MORRInd::t3d ,
  MORRInd::qv3d , MORRInd::pres , MORRInd::dzq , MORRInd::w3d ,
  MORRInd::nc3d , MORRInd::nc3dten , MORRInd::qg3dten , MORRInd::ng3dten ,
  MORRInd::qg3d , MORRInd::ng3d , MORRInd::qgsten , MORRInd::qrsten ,
  MORRInd::qisten , MORRInd::qnisten , MORRInd::qcsten , MORRInd::qrcu1d ,
  MORRInd::qscu1d , MORRInd::qicu1d , MORRInd::precrt , MORRInd::snowrt ,
  MORRInd::snowprt , MORRInd::grplprt , MORRInd::effc , MORRInd::effi ,
  MORRInd::effs , MORRInd::effr , MORRInd::effg , MORRInd::rho ,
  MORRInd::mu , MORRInd::ain , MORRInd::arn , MORRInd::asn ,
  MORRInd::acn , MORRInd::agn , MORRInd::dumi , MORRInd::dumr ,
  MORRInd::dumfni , MORRInd::dumg , MORRInd::dumfng , MORRInd::uni ,
  MORRInd::umi , MORRInd::umr , MORRInd::fr , MORRInd::fi ,
  MORRInd::fni , MORRInd::fg , MORRInd::fng , MORRInd::rgvm ,
  MORRInd::faloutr , MORRInd::falouti , MORRInd::faloutni , MORRInd::faltndr ,
  MORRInd::faltndi , MORRInd::faltndni , MORRInd::dumqs , MORRInd::dumfns ,
  MORRInd::ums , MORRInd::uns , MORRInd::fs , MORRInd::fns ,
  MORRInd::falouts , MORRInd::faloutns , MORRInd::faloutg , MORRInd::faloutng ,
  MORRInd::faltnds , MORRInd::faltndns , MORRInd::unr , MORRInd::faltndg ,
  MORRInd::faltndng , MORRInd::dumc , MORRInd::dumfnc , MORRInd::unc ,
  MORRInd::umc , MORRInd::ung , MORRInd::umg , MORRInd::fc ,
  MORRInd::faloutc , MORRInd::faloutnc , MORRInd::faltndc , MORRInd::faltndnc ,
  MORRInd::fnc , MORRInd::dumfnr , MORRInd::faloutnr , MORRInd::faltndnr ,
  MORRInd::fnr , MORRInd::dlams , MORRInd::dlamr , MORRInd::dlami ,
  MORRInd::dlamc , MORRInd::dlamg , MORRInd::xxls , MORRInd::xxlv ,
  MORRInd::cpm , MORRInd::xlf , MORRInd::NumInds
}
 

Functions

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real wrf_gamma (amrex::Real x)
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real gamma_function (Real x)
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real calc_saturation_vapor_pressure (const amrex::Real T, const int type)
 

Variables

constexpr Real xxx = Real(0.9189385332046727417803297)
 

Function Documentation

◆ calc_saturation_vapor_pressure()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real calc_saturation_vapor_pressure ( const amrex::Real  T,
const int  type 
)

Helper function to calculate saturation vapor pressure for water or ice. This corresponds to the POLYSVP function in the Fortran code (line ~5580).

Parameters
[in]TTemperature in Kelvin
[in]type0 for liquid water, 1 for ice
Returns
Saturation vapor pressure in Pascals
447  {
448  amrex::Real polysvp = Real(0);
449  amrex::Real del_T = T - Real(273.15); // Convert to Celsius
450 
451  if (type == 1) { // Ice (lines ~5631-5644)
452  if (T >= Real(195.8)) {
453  // Flatau et al. formula for ice
454  const amrex::Real a0i = Real(6.11147274);
455  const amrex::Real a1i = Real(0.503160820);
456  const amrex::Real a2i = Real(0.188439774e-1);
457  const amrex::Real a3i = Real(0.420895665e-3);
458  const amrex::Real a4i = Real(0.615021634e-5);
459  const amrex::Real a5i = Real(0.602588177e-7);
460  const amrex::Real a6i = Real(0.385852041e-9);
461  const amrex::Real a7i = Real(0.146898966e-11);
462  const amrex::Real a8i = Real(0.252751365e-14);
463 
464  polysvp = a0i + del_T*(a1i + del_T*(a2i + del_T*(a3i + del_T*(a4i + del_T*(a5i + del_T*(a6i + del_T*(a7i + a8i*del_T)))))));
465  polysvp *= Real(100.0); // Convert from hPa to Pa
466  } else {
467  // Goff-Gratch formula for ice at cold temperatures
468  polysvp = std::pow(Real(10.0), (-Real(9.09718)*(Real(273.16)/T-one) - Real(3.56654)*std::log10(Real(273.16)/T) +
469  Real(0.876793)*(one-T/Real(273.16)) + std::log10(Real(6.1071)))) * Real(100.0);
470  } // T
471  } else { // Water (lines ~5648-5665)
472  if (T >= Real(202.0)) {
473  // Flatau et al. formula for liquid water
474  const amrex::Real a0 = Real(6.11239921);
475  const amrex::Real a1 = Real(0.443987641);
476  const amrex::Real a2 = Real(0.142986287e-1);
477  const amrex::Real a3 = Real(0.264847430e-3);
478  const amrex::Real a4 = Real(0.302950461e-5);
479  const amrex::Real a5 = Real(0.206739458e-7);
480  const amrex::Real a6 = Real(0.640689451e-10);
481  const amrex::Real a7 = -Real(0.952447341e-13);
482  const amrex::Real a8 = -Real(0.976195544e-15);
483 
484  polysvp = a0 + del_T*(a1 + del_T*(a2 + del_T*(a3 + del_T*(a4 + del_T*(a5 + del_T*(a6 + del_T*(a7 + a8*del_T)))))));
485  polysvp *= Real(100.0); // Convert from hPa to Pa
486  } else {
487  // Goff-Gratch formula for water at cold temperatures
488  polysvp = std::pow(Real(10.0), (-Real(7.90298)*(Real(373.16)/T-one) + Real(5.02808)*std::log10(Real(373.16)/T) -
489  Real(1.3816e-7)*(std::pow(Real(10.0), (Real(11.344)*(one-T/Real(373.16))))-one) +
490  Real(8.1328e-3)*(std::pow(Real(10.0), (-Real(3.49149)*(Real(373.16)/T-one)))-one) +
491  std::log10(Real(1013.246)))) * Real(100.0);
492  }
493  }
494 
495  return polysvp;
496  }
constexpr amrex::Real one
Definition: ERF_Constants.H:7
Real T
Definition: ERF_InitCustomPert_Bubble.H:105
amrex::Real Real
Definition: ERF_ShocInterface.H:19
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 a4
Definition: ERF_module_model_constants.F90:97
real(c_double) function, public polysvp(T, TYPE)
Definition: ERF_module_mp_morr_two_moment.F90:4020

Referenced by Morrison::Advance().

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

◆ gamma_function()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real gamma_function ( Real  x)
433  {
434  return wrf_gamma(x);
435 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real wrf_gamma(amrex::Real x)
Definition: ERF_AdvanceMorrison.cpp:255

Referenced by Morrison::Advance().

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

◆ wrf_gamma()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real wrf_gamma ( amrex::Real  x)
256 {
257  // Debug: using printf since it's GPU compatible
258 // printf("wrf_gamma: Input value x = %g\n", x);
259 
260  // Local variables
261  int i, n;
262  bool parity = false;
263  amrex::Real fact, res, sum, twelve, xbig, xden, xinf, xminin;
264  amrex::Real xnum, y, y1, ysq, z;
265  amrex::Real c[7];
266  amrex::Real p[8];
267  amrex::Real q[8];
268 
269  // Mathematical constants
270  twelve = Real(12.0);
271 
272  // Machine dependent parameters
273  xbig = Real(35.040);
274  xminin = Real(1.18e-38);
275  amrex::Real eps = Real(1.19e-7);
276  xinf = Real(3.4e38);
277 
278  // Numerator and denominator coefficients for rational minimax approximation over (1,2)
279  p[0] = -Real(1.71618513886549492533811e+0);
280  p[1] = Real(2.47656508055759199108314e+1);
281  p[2] = -Real(3.79804256470945635097577e+2);
282  p[3] = Real(6.29331155312818442661052e+2);
283  p[4] = Real(8.66966202790413211295064e+2);
284  p[5] = -Real(3.14512729688483675254357e+4);
285  p[6] = -Real(3.61444134186911729807069e+4);
286  p[7] = Real(6.64561438202405440627855e+4);
287 
288  q[0] = -Real(3.08402300119738975254353e+1);
289  q[1] = Real(3.15350626979604161529144e+2);
290  q[2] = -Real(1.01515636749021914166146e+3);
291  q[3] = -Real(3.10777167157231109440444e+3);
292  q[4] = Real(2.25381184209801510330112e+4);
293  q[5] = Real(4.75584627752788110767815e+3);
294  q[6] = -Real(1.34659959864969306392456e+5);
295  q[7] = -Real(1.15132259675553483497211e+5);
296 
297  // Coefficients for minimax approximation over (12, inf)
298  c[0] = -Real(1.910444077728e-03);
299  c[1] = Real(8.4171387781295e-04);
300  c[2] = -Real(5.952379913043012e-04);
301  c[3] = Real(7.93650793500350248e-04);
302  c[4] = -Real(2.777777777777681622553e-03);
303  c[5] = Real(8.333333333333333331554247e-02);
304  c[6] = Real(5.7083835261e-03);
305 
306  // Initialize variables
307  parity = false;
308  fact = one;
309  n = 0;
310  y = x;
311 
312 // printf("wrf_gamma: Initial y = %g\n", y);
313 
314  if (y <= Real(0)) {
315  // Argument is negative
316 // printf("wrf_gamma: Handling negative argument\n");
317  y = -x;
318  y1 = std::floor(y);
319  res = y - y1;
320  if (res != Real(0)) {
321  if (y1 != std::floor(y1 * myhalf) * Real(2))
322  parity = true;
323  Real pi=amrex::Math::pi<Real>();
324  fact = -pi / std::sin(pi * res);
325  y = y + one;
326 // printf("wrf_gamma: After reflection formula: y = %g, fact = %g, parity = %d\n",
327 // y, fact, parity);
328  }
329  else {
330 // printf("wrf_gamma: Singularity detected, returning xinf = %g\n", xinf);
331  res = xinf;
332  return res;
333  }
334  }
335 
336  // Argument is positive
337  if (y < eps) {
338  // Argument < eps
339 // printf("wrf_gamma: Small argument branch (y < eps)\n");
340  if (y >= xminin) {
341  res = one / y;
342 // printf("wrf_gamma: Small argument result: res = %g\n", res);
343  }
344  else {
345 // printf("wrf_gamma: Argument too small, returning xinf = %g\n", xinf);
346  res = xinf;
347  return res;
348  }
349  }
350  else if (y < twelve) {
351  // Medium range argument
352 // printf("wrf_gamma: Medium range branch (eps <= y < 12)\n");
353  y1 = y;
354  if (y < one) {
355  // Real(0) < argument < one
356 // printf("wrf_gamma: Sub-branch: 0 < y < 1\n");
357  z = y;
358  y = y + one;
359  }
360  else {
361  // one < argument < Real(12.0), reduce argument if necessary
362  n = static_cast<int>(y) - 1;
363 // printf("wrf_gamma: Sub-branch: 1 <= y < 12, n = %d\n", n);
364  y = y - static_cast<amrex::Real>(n);
365  z = y - one;
366  }
367 
368  // Evaluate approximation
369 // printf("wrf_gamma: Before approximation: z = %g, y = %g\n", z, y);
370  xnum = Real(0);
371  xden = one;
372  for (i = 0; i < 8; i++) {
373  xnum = (xnum + p[i]) * z;
374  xden = xden * z + q[i];
375  }
376  res = xnum / xden + one;
377 // printf("wrf_gamma: After approximation: res = %g\n", res);
378 
379  if (y1 < y) {
380  // Adjust result for case Real(0) < argument < one
381  res = res / y1;
382 // printf("wrf_gamma: Adjusted for y < 1: res = %g\n", res);
383  }
384  else if (y1 > y) {
385  // Adjust for two < argument < Real(12.0)
386 // printf("wrf_gamma: Adjusting for y > 2 with %d multiplications\n", n);
387  for (i = 0; i < n; i++) {
388  res = res * y;
389  y = y + one;
390 // printf("wrf_gamma: Multiplication %d: res = %g, y = %g\n", i+1, res, y);
391  }
392  }
393  }
394  else {
395  // Large argument
396 // printf("wrf_gamma: Large argument branch (y >= 12)\n");
397  if (y <= xbig) {
398  ysq = y * y;
399  sum = c[6];
400  for (i = 0; i < 6; i++) {
401  sum = sum / ysq + c[i];
402 // printf("wrf_gamma: Sum step %d: sum = %g\n", i+1, sum);
403  }
404  sum = sum / y - y + xxx;
405  sum = sum + (y - myhalf) * std::log(y);
406 // printf("wrf_gamma: Before exp: sum = %g\n", sum);
407  res = std::exp(sum);
408 // printf("wrf_gamma: After exp: res = %g\n", res);
409  }
410  else {
411 // printf("wrf_gamma: Argument too large, returning xinf = %g\n", xinf);
412  res = xinf;
413  return res;
414  }
415  }
416 
417  // Final adjustments
418  if (parity) {
419  res = -res;
420 // printf("wrf_gamma: Applied parity adjustment: res = %g\n", res);
421  }
422  if (fact != one) {
423  res = fact / res;
424 // printf("wrf_gamma: Applied reflection adjustment: res = %g\n", res);
425  }
426 
427 // printf("wrf_gamma: Final result = %g\n", res);
428  return res;
429 }
constexpr Real xxx
Definition: ERF_AdvanceMorrison.cpp:159
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:11
Real * p
Definition: ERF_InitCustomPert_SquallLine.H:61
real(c_double), parameter, private pi
Definition: ERF_module_mp_morr_two_moment.F90:100

Referenced by gamma_function().

Here is the caller graph for this function:

Variable Documentation

◆ xxx

constexpr Real xxx = Real(0.9189385332046727417803297)
constexpr

Referenced by wrf_gamma().