ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_PrognosticCloudFraction.H File Reference

Prognostic cloud fraction diagnosis from relative humidity and cloud water. More...

#include <AMReX_GpuControl.H>
#include <AMReX_Math.H>
#include <AMReX_FArrayBox.H>
#include <cmath>
Include dependency graph for ERF_PrognosticCloudFraction.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real compute_relative_humidity (amrex::Real qv, amrex::Real T, amrex::Real P)
 Compute relative humidity from water vapor mixing ratio. More...
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real diagnose_cloud_fraction_from_rh_qc (amrex::Real rh, amrex::Real qc, amrex::Real rh_min, amrex::Real rh_max, amrex::Real qc_scale)
 Diagnose cloud fraction from relative humidity and cloud water. More...
 

Detailed Description

Prognostic cloud fraction diagnosis from relative humidity and cloud water.

Implements RH/qc-based cloud fraction diagnosis for use in TwoStream radiation.

Cloud fraction diagnosis formula: cf_rh(k) = max(0, min(1, (rh(k) - rh_min) / (rh_max - rh_min))) [linear ramp] cf_qc(k) = min(1, qc / qc_scale(k)) [qc contribution] cf_diag(k) = min(1, cf_rh(k) + cf_qc(k)) [combined with saturation]

References:

Function Documentation

◆ compute_relative_humidity()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real compute_relative_humidity ( amrex::Real  qv,
amrex::Real  T,
amrex::Real  P 
)

Compute relative humidity from water vapor mixing ratio.

Approximate RH from qv and temperature using saturation mixing ratio. The saturation vapour pressure over liquid water is the Magnus formula with the WMO (2008) coefficients, applied to the temperature in Celsius.

Parameters
[in]qvWater vapor mixing ratio [kg/kg]
[in]TTemperature [K]
[in]PPressure [Pa]
Returns
Relative humidity [0, 1]
38 {
39  // Guard against invalid inputs
40  if (T <= 0.0 || P <= 0.0 || qv < 0.0 || !amrex::Math::isfinite(qv) ||
41  !amrex::Math::isfinite(T) || !amrex::Math::isfinite(P)) {
42  return 0.0;
43  }
44 
45  // Saturation vapour pressure over liquid water from the Magnus formula,
46  // with the WMO (2008) coefficients for the temperature in Celsius:
47  // e_sat = e0 * exp(a * tc / (tc + b)), tc = T - T0
48  // and the saturation mixing ratio qsat = epsilon * e_sat / max(e_sat, P - e_sat).
49  const amrex::Real e0 = 611.2; // Pa (saturation vapor pressure at 0°C)
50  const amrex::Real T0 = 273.15; // K
51  const amrex::Real a = 17.62;
52  const amrex::Real b = 243.12; // °C
53 
54  // tc + b <= 0 only below about 30 K, where e_sat tends to 0. Otherwise
55  // arg < a, so e_sat stays below e0 * exp(a) and cannot overflow.
56  const amrex::Real tc = T - T0;
57  const amrex::Real arg = (tc + b > amrex::Real(0.0)) ? a * tc / (tc + b) : amrex::Real(-100.0);
58  const amrex::Real e_sat = e0 * std::exp(arg);
59 
60  // Saturation mixing ratio. The denominator is floored at e_sat, as in
61  // erf_qsatw, so qsat stays positive and bounded by epsilon when e_sat
62  // approaches or exceeds P (hot or very low-pressure air).
63  const amrex::Real epsilon = 0.622; // ratio of molecular weights
64  amrex::Real qsat = epsilon * e_sat / amrex::max(e_sat, P - e_sat);
65  if (qsat <= 0.0) {
66  qsat = 1.0e-6; // fallback when e_sat underflows (unphysically cold air)
67  }
68 
69  // RH = qv / qsat, clamped to [0, 1]
70  amrex::Real rh = qv / qsat;
71  if (rh < 0.0) rh = 0.0;
72  if (rh > 1.0) rh = 1.0;
73 
74  return rh;
75 }
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ P
Definition: ERF_IndexDefines.H:244
@ qv
Definition: ERF_Kessler.H:31
@ T
Definition: ERF_IndexDefines.H:168
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12

Referenced by diagnose_cloud_fraction_prognostic(), and ParallelFor().

Here is the caller graph for this function:

◆ diagnose_cloud_fraction_from_rh_qc()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real diagnose_cloud_fraction_from_rh_qc ( amrex::Real  rh,
amrex::Real  qc,
amrex::Real  rh_min,
amrex::Real  rh_max,
amrex::Real  qc_scale 
)

Diagnose cloud fraction from relative humidity and cloud water.

Computes diagnosed cloud fraction from RH and qc:

  • RH contribution: linear ramp from 0 at rh_min to 1 at rh_max
  • qc contribution: scaled by qc_scale coefficient
  • Combined: saturated blend (cf ≤ 1)

This is a GPU-safe inline function for device-side kernels.

Parameters
[in]rhRelative humidity [0, 1]
[in]qcCloud liquid water mixing ratio [kg/kg]
[in]rh_minMinimum RH threshold [0, 1]
[in]rh_maxMaximum RH threshold [0, 1]
[in]qc_scaleScaling coefficient for qc contribution
Returns
Diagnosed cloud fraction [0, 1]
Note
All inputs are assumed to be validated and finite.
Output is always in [0, 1], finite, and safe for further use.
103 {
104  // Guard against invalid inputs
105  if (!amrex::Math::isfinite(rh) || !amrex::Math::isfinite(qc) ||
106  !amrex::Math::isfinite(rh_min) || !amrex::Math::isfinite(rh_max) ||
107  !amrex::Math::isfinite(qc_scale)) {
108  return 0.0; // Safe fallback on invalid input
109  }
110 
111  // Clamp RH and qc to valid ranges
112  if (rh < 0.0) rh = 0.0;
113  if (rh > 1.0) rh = 1.0;
114  if (qc < 0.0) qc = 0.0;
115 
116  amrex::Real cf = 0.0;
117 
118  // RH contribution: linear ramp from 0 at rh_min to 1 at rh_max
119  if (rh_max > rh_min) {
120  // Linear interpolation
121  amrex::Real cf_rh = (rh - rh_min) / (rh_max - rh_min);
122  if (cf_rh < 0.0) cf_rh = 0.0;
123  if (cf_rh > 1.0) cf_rh = 1.0;
124  cf += cf_rh;
125  } else if (rh >= rh_min) {
126  // rh_max == rh_min: step function
127  cf += 1.0;
128  }
129 
130  // qc contribution: qc_scale is the cloud water [kg/kg] at which the
131  // liquid-water term alone saturates, so cf_qc = qc / qc_scale, capped at 1.
132  if (qc_scale > 0.0) {
133  amrex::Real cf_qc = qc / qc_scale;
134  if (cf_qc > 1.0) cf_qc = 1.0;
135  cf += cf_qc;
136  }
137 
138  // Saturate combined cloud fraction to [0, 1]
139  if (cf < 0.0) cf = 0.0;
140  if (cf > 1.0) cf = 1.0;
141 
142  // Final sanity check
143  if (!amrex::Math::isfinite(cf)) {
144  cf = 0.0;
145  }
146 
147  return cf;
148 }
@ qc
Definition: ERF_Morrison.H:110

Referenced by diagnose_cloud_fraction_prognostic().

Here is the caller graph for this function: