ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_MoistUtils.H File Reference
#include "ERF_EOS.H"
#include "ERF_MicrophysicsUtils.H"
Include dependency graph for ERF_MoistUtils.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

AMREX_GPU_DEVICE AMREX_FORCE_INLINE void GetMoistureVars (int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, amrex::Real &qv, amrex::Real &qc_liquid, amrex::Real &qc_ice, const MoistureComponentIndices &moisture_indices)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeVirtualPotentialTemperature (amrex::Real theta, amrex::Real qv, amrex::Real qc_liquid, amrex::Real qc_ice)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetav (int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, const MoistureComponentIndices &moisture_indices)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeLiquidWaterPotentialTemperature (amrex::Real theta, amrex::Real T, amrex::Real qc_liquid)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetal (int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, const MoistureComponentIndices &moisture_indices)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeMoistStratification (int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, amrex::Real dzInv, amrex::Real abs_g, amrex::Real inv_theta0, const MoistureComponentIndices &moisture_indices)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeStratificationForSmagorinsky (int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, amrex::Real dzInv, amrex::Real abs_g, amrex::Real inv_theta0, bool use_moisture, int rho_qv_comp, const MoistureComponentIndices &moisture_indices)
 

Function Documentation

◆ ComputeLiquidWaterPotentialTemperature()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeLiquidWaterPotentialTemperature ( amrex::Real  theta,
amrex::Real  T,
amrex::Real  qc_liquid 
)

Compute linearized liquid-water potential temperature

92 {
93  return theta - (theta / T) * (L_v / Cp_d) * qc_liquid;
94 }
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:12
constexpr amrex::Real L_v
Definition: ERF_Constants.H:16
@ theta
Definition: ERF_MM5.H:20
@ T
Definition: ERF_IndexDefines.H:110

Referenced by GetThetal().

Here is the caller graph for this function:

◆ ComputeMoistStratification()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeMoistStratification ( int  i,
int  j,
int  k,
const amrex::Array4< amrex::Real const > &  cell_data,
amrex::Real  dzInv,
amrex::Real  abs_g,
amrex::Real  inv_theta0,
const MoistureComponentIndices moisture_indices 
)

Compute moist stratification accounting for conditional instability

129 {
130  // Get moisture variables partitioned into phases
131  amrex::Real qv, qc_liquid, qc_ice;
132  GetMoistureVars(i, j, k, cell_data, qv, qc_liquid, qc_ice, moisture_indices);
133 
134  // Compute virtual potential temperature gradient
135  amrex::Real theta_v_upper = GetThetav(i, j, k+1, cell_data, moisture_indices);
136  amrex::Real theta_v_lower = GetThetav(i, j, k-1, cell_data, moisture_indices);
137 
138  amrex::Real dthetav_dz = 0.5 * (theta_v_upper - theta_v_lower) * dzInv;
139  amrex::Real stratification = abs_g * dthetav_dz * inv_theta0;
140 
141  // Apply conditional instability correction
142  amrex::Real total_condensate = qc_liquid + qc_ice;
143  if (total_condensate > 1e-8) {
144  amrex::Real T_current = getTgivenRandRTh(cell_data(i,j,k,Rho_comp),
145  cell_data(i,j,k,RhoTheta_comp), qv);
146 
147  // Phase-weighted effective latent heat
148  amrex::Real liquid_fraction = qc_liquid / (total_condensate + 1e-12);
149  amrex::Real ice_fraction = 1.0 - liquid_fraction;
150  amrex::Real L_eff = liquid_fraction * L_v + ice_fraction * (L_v + lat_ice);
151 
152  // Phase-weighted saturation mixing ratio
153  amrex::Real qsat_liquid = 0.0, qsat_ice = 0.0;
154  amrex::Real pres_current = getPgivenRTh(cell_data(i,j,k,RhoTheta_comp), qv) * 0.01;
155 
156  erf_qsatw(T_current, pres_current, qsat_liquid);
157  erf_qsati(T_current, pres_current, qsat_ice);
158 
159  amrex::Real qsat_eff = liquid_fraction * qsat_liquid + ice_fraction * qsat_ice;
160 
161  // Moist adiabatic lapse rate correction
162  amrex::Real gamma_moist_factor = (1.0 + L_eff*qsat_eff/(R_d*T_current)) /
163  (1.0 + L_eff*L_eff*qsat_eff/(Cp_d*R_v*T_current*T_current));
164 
165  stratification *= gamma_moist_factor;
166  }
167 
168  return stratification;
169 }
constexpr amrex::Real R_v
Definition: ERF_Constants.H:11
constexpr amrex::Real lat_ice
Definition: ERF_Constants.H:86
constexpr amrex::Real R_d
Definition: ERF_Constants.H:10
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=0.)
Definition: ERF_EOS.H:81
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenRandRTh(const amrex::Real rho, const amrex::Real rhotheta, const amrex::Real qv=0.0)
Definition: ERF_EOS.H:46
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsatw(amrex::Real t, amrex::Real p, amrex::Real &qsatw)
Definition: ERF_MicrophysicsUtils.H:163
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsati(amrex::Real t, amrex::Real p, amrex::Real &qsati)
Definition: ERF_MicrophysicsUtils.H:152
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void GetMoistureVars(int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, amrex::Real &qv, amrex::Real &qc_liquid, amrex::Real &qc_ice, const MoistureComponentIndices &moisture_indices)
Definition: ERF_MoistUtils.H:16
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetav(int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, const MoistureComponentIndices &moisture_indices)
Definition: ERF_MoistUtils.H:72
amrex::Real Real
Definition: ERF_ShocInterface.H:16
@ qv
Definition: ERF_Kessler.H:28

Referenced by ComputeStratificationForSmagorinsky().

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

◆ ComputeStratificationForSmagorinsky()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeStratificationForSmagorinsky ( int  i,
int  j,
int  k,
const amrex::Array4< amrex::Real const > &  cell_data,
amrex::Real  dzInv,
amrex::Real  abs_g,
amrex::Real  inv_theta0,
bool  use_moisture,
int  rho_qv_comp,
const MoistureComponentIndices moisture_indices 
)

Compute stratification for Smagorinsky scheme (moist or dry)

184 {
185  if (use_moisture && (rho_qv_comp >= 0)) {
186  // Moist stratification with virtual temperature and conditional instability
187  return ComputeMoistStratification(i, j, k, cell_data, dzInv, abs_g, inv_theta0, moisture_indices);
188  } else {
189  // Dry stratification (original approach)
190  amrex::Real theta_hi = cell_data(i,j,k+1,RhoTheta_comp)/cell_data(i,j,k+1,Rho_comp);
191  amrex::Real theta_lo = cell_data(i,j,k-1,RhoTheta_comp)/cell_data(i,j,k-1,Rho_comp);
192  amrex::Real dtheta_dz = 0.5 * (theta_hi - theta_lo) * dzInv;
193  return abs_g * dtheta_dz * inv_theta0;
194  }
195 }
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeMoistStratification(int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, amrex::Real dzInv, amrex::Real abs_g, amrex::Real inv_theta0, const MoistureComponentIndices &moisture_indices)
Definition: ERF_MoistUtils.H:123

Referenced by ComputeTurbulentViscosityLES().

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

◆ ComputeVirtualPotentialTemperature()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeVirtualPotentialTemperature ( amrex::Real  theta,
amrex::Real  qv,
amrex::Real  qc_liquid,
amrex::Real  qc_ice 
)

Compute virtual potential temperature with moisture loading effects

62 {
63  amrex::Real qc_total = qc_liquid + qc_ice;
64  return theta * (1.0 + 0.61*qv - qc_total);
65 }

Referenced by GetThetav().

Here is the caller graph for this function:

◆ GetMoistureVars()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE void GetMoistureVars ( int  i,
int  j,
int  k,
const amrex::Array4< amrex::Real const > &  cell_data,
amrex::Real qv,
amrex::Real qc_liquid,
amrex::Real qc_ice,
const MoistureComponentIndices moisture_indices 
)

Extract moisture variables and partition into liquid/ice phases

22 {
23  qv = 0.0; qc_liquid = 0.0; qc_ice = 0.0;
24 
25  // Water vapor
26  if (moisture_indices.qv >= 0) {
27  qv = cell_data(i,j,k,moisture_indices.qv)/cell_data(i,j,k,Rho_comp);
28  }
29 
30  // Cloud liquid water
31  if (moisture_indices.qc >= 0) {
32  qc_liquid = cell_data(i,j,k,moisture_indices.qc)/cell_data(i,j,k,Rho_comp);
33  }
34 
35  // Cloud ice (only if separate ice species exists)
36  if (moisture_indices.qi >= 0) {
37  qc_ice = cell_data(i,j,k,moisture_indices.qi)/cell_data(i,j,k,Rho_comp);
38  }
39  // No temperature-based partitioning - respect the microphysics scheme's decisions
40 
41  // Add precipitating species
42  if (moisture_indices.qr >= 0) { // Rain (always liquid)
43  qc_liquid += cell_data(i,j,k,moisture_indices.qr)/cell_data(i,j,k,Rho_comp);
44  }
45  if (moisture_indices.qs >= 0) { // Snow (always ice)
46  qc_ice += cell_data(i,j,k,moisture_indices.qs)/cell_data(i,j,k,Rho_comp);
47  }
48  if (moisture_indices.qg >= 0) { // Graupel (always ice)
49  qc_ice += cell_data(i,j,k,moisture_indices.qg)/cell_data(i,j,k,Rho_comp);
50  }
51 }
int qs
Definition: ERF_DataStruct.H:104
int qr
Definition: ERF_DataStruct.H:103
int qi
Definition: ERF_DataStruct.H:102
int qv
Definition: ERF_DataStruct.H:100
int qc
Definition: ERF_DataStruct.H:101
int qg
Definition: ERF_DataStruct.H:105

Referenced by ComputeMoistStratification(), GetThetal(), and GetThetav().

Here is the caller graph for this function:

◆ GetThetal()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetal ( int  i,
int  j,
int  k,
const amrex::Array4< amrex::Real const > &  cell_data,
const MoistureComponentIndices moisture_indices 
)

Wrapper around ComputeLiquidWaterPotentialTemperature

104 {
105  amrex::Real qv, qcl, qci;
106  GetMoistureVars(i, j, k, cell_data, qv, qcl, qci, moisture_indices);
107 
108  amrex::Real theta = cell_data(i, j, k, RhoTheta_comp) / cell_data(i, j, k, Rho_comp);
109 
110  amrex::Real T = getTgivenRandRTh(cell_data(i, j, k, Rho_comp),
111  cell_data(i, j, k, RhoTheta_comp),
112  qv);
113 
115 }
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeLiquidWaterPotentialTemperature(amrex::Real theta, amrex::Real T, amrex::Real qc_liquid)
Definition: ERF_MoistUtils.H:89
@ qcl
Definition: ERF_Kessler.H:29
@ qci
Definition: ERF_Morrison.H:36

Referenced by ComputeTurbulentViscosityLES().

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

◆ GetThetav()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetav ( int  i,
int  j,
int  k,
const amrex::Array4< amrex::Real const > &  cell_data,
const MoistureComponentIndices moisture_indices 
)

Wrapper around ComputeVirtualPotentialTemperature

75 {
76  amrex::Real theta = cell_data(i, j, k, RhoTheta_comp) / cell_data(i, j, k, Rho_comp);
77 
79  GetMoistureVars(i, j, k, cell_data, qv, qcl, qci, moisture_indices);
80 
82 }
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeVirtualPotentialTemperature(amrex::Real theta, amrex::Real qv, amrex::Real qc_liquid, amrex::Real qc_ice)
Definition: ERF_MoistUtils.H:58

Referenced by MYNNPBLH::compute_pblh(), ComputeMoistStratification(), ComputeTurbulentViscosityLES(), and ComputeVerticalDerivativesPBL().

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