ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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::qrcuten_arr = 0 , MORRInd::qscuten_arr , MORRInd::qicuten_arr , MORRInd::lamc ,
  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 = 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
449  {
450  amrex::Real polysvp = 0.0;
451  amrex::Real del_T = T - 273.15; // Convert to Celsius
452 
453  if (type == 1) { // Ice (lines ~5631-5644)
454  if (T >= 195.8) {
455  // Flatau et al. formula for ice
456  const amrex::Real a0i = 6.11147274;
457  const amrex::Real a1i = 0.503160820;
458  const amrex::Real a2i = 0.188439774e-1;
459  const amrex::Real a3i = 0.420895665e-3;
460  const amrex::Real a4i = 0.615021634e-5;
461  const amrex::Real a5i = 0.602588177e-7;
462  const amrex::Real a6i = 0.385852041e-9;
463  const amrex::Real a7i = 0.146898966e-11;
464  const amrex::Real a8i = 0.252751365e-14;
465 
466  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)))))));
467  polysvp *= 100.0; // Convert from hPa to Pa
468  } else {
469  // Goff-Gratch formula for ice at cold temperatures
470  polysvp = std::pow(10.0, (-9.09718*(273.16/T-1.0) - 3.56654*std::log10(273.16/T) +
471  0.876793*(1.0-T/273.16) + std::log10(6.1071))) * 100.0;
472  polysvp = 0.0;
473  } // T
474  } else { // Water (lines ~5648-5665)
475  if (T >= 202.0) {
476  // Flatau et al. formula for liquid water
477  const amrex::Real a0 = 6.11239921;
478  const amrex::Real a1 = 0.443987641;
479  const amrex::Real a2 = 0.142986287e-1;
480  const amrex::Real a3 = 0.264847430e-3;
481  const amrex::Real a4 = 0.302950461e-5;
482  const amrex::Real a5 = 0.206739458e-7;
483  const amrex::Real a6 = 0.640689451e-10;
484  const amrex::Real a7 = -0.952447341e-13;
485  const amrex::Real a8 = -0.976195544e-15;
486 
487  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)))))));
488  polysvp *= 100.0; // Convert from hPa to Pa
489  } else {
490  // Goff-Gratch formula for water at cold temperatures
491  polysvp = std::pow(10.0, (-7.90298*(373.16/T-1.0) + 5.02808*std::log10(373.16/T) -
492  1.3816e-7*(std::pow(10.0, (11.344*(1.0-T/373.16)))-1.0) +
493  8.1328e-3*(std::pow(10.0, (-3.49149*(373.16/T-1.0)))-1.0) +
494  std::log10(1013.246))) * 100.0;
495  }
496  }
497 
498  return polysvp;
499  }
@ T
Definition: ERF_IndexDefines.H:110
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:4006

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)
435  {
436  return wrf_gamma(x);
437 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real wrf_gamma(amrex::Real x)
Definition: ERF_AdvanceMorrison.cpp:253

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

Referenced by wrf_gamma().