ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ib_stability Namespace Reference

Functions

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real zeta_max () noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real floored_wind (amrex::Real speed, amrex::Real wind_floor) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real bounded_obukhov_length (amrex::Real Olen, amrex::Real z_ref) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real bounded_zeta (amrex::Real z, amrex::Real Olen) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real psi_cap (amrex::Real z, amrex::Real z0, amrex::Real factor) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real capped_psi (amrex::Real psi, amrex::Real z, amrex::Real z0, amrex::Real factor) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real psi_m_for_ustar (amrex::Real psi_m, amrex::Real z, amrex::Real z0, amrex::Real factor) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real clamped_ustar (amrex::Real ustar) noexcept
 

Detailed Description

Bounds on the stability estimate of the immersed-forcing wall law. Without them a zero tangential wind one cell from the wall gives u* = 0, an Obukhov length of zero and zeta = z/0 (erf-model/ERF#4016).

Always on:

  • An Obukhov length derived from u* and the heat flux is held at |L| >= z_ref / 100, and every zeta = z / L at |zeta| <= 100, as on flat ground (ERF_MOSTStress.H). A prescribed erf.if_Olen is used as given: only its zeta is held, so one input means one L on every face and at every height.

Opt-in (WRF's revised surface layer, sf_sfclayrev):

  • erf.if_stability_wind_floor (default 0, WRF and the flat-ground WSMIN use 0.1 m/s) floors the wind behind the friction velocity of the stability estimate.
  • erf.if_psi_cap_factor (default 1, WRF uses 0.9) caps psi_m at factor ln(z / z0) in the velocity target and before it forms the friction velocity of the momentum law. The temperature forcing keeps caps of ln(z / z0): its surface-flux branch forms theta* from an Obukhov length that is not consistent with u*, which those caps keep from reaching the target in strongly unstable air.

Function Documentation

◆ bounded_obukhov_length()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ib_stability::bounded_obukhov_length ( amrex::Real  Olen,
amrex::Real  z_ref 
)
noexcept

An Obukhov length derived from u* and the heat flux, with |L| no smaller than z_ref / zeta_max(), so that z / L lies within +-zeta_max() for every z <= z_ref and the zero L of a zero u* is never divided by. The sign is kept: L = -0 is the unstable bound and L = +0 the stable one. Unchanged, bit for bit, when |L| >= z_ref / zeta_max(). Not for a prescribed L, whose bound would then depend on the local cell size; see bounded_zeta.

52  {
53  return std::copysign(amrex::max(std::abs(Olen), z_ref / zeta_max()), Olen);
54  }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real zeta_max() noexcept
Definition: ERF_ImmersedWallStability.H:34

Referenced by compute_if_most_target_vel(), ImmersedForcingBuildings_Scalar(), ImmersedForcingTerrain_Scalar(), ImmersedForcingTerrain_Xmom(), and ImmersedForcingTerrain_Ymom().

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

◆ bounded_zeta()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ib_stability::bounded_zeta ( amrex::Real  z,
amrex::Real  Olen 
)
noexcept

zeta = z / L held within +-zeta_max(), for an L that is not zero (a prescribed erf.if_Olen, which start-up refuses at 0, or one from bounded_obukhov_length). Unchanged, bit for bit, when |z / L| <= zeta_max(); a NaN stays NaN.

63  {
64  // z / L first in both, so a NaN propagates instead of becoming a bound
65  return amrex::min(amrex::max(z / Olen, -zeta_max()), zeta_max());
66  }

Referenced by compute_if_most_target_vel(), ImmersedForcingBuildings_Scalar(), ImmersedForcingTerrain_Scalar(), ImmersedForcingTerrain_Xmom(), and ImmersedForcingTerrain_Ymom().

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

◆ capped_psi()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ib_stability::capped_psi ( amrex::Real  psi,
amrex::Real  z,
amrex::Real  z0,
amrex::Real  factor 
)
noexcept

psi held at or below psi_cap(z, z0, factor).

86  {
87  return amrex::min(psi, psi_cap(z, z0, factor));
88  }
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:8
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real psi_cap(amrex::Real z, amrex::Real z0, amrex::Real factor) noexcept
Definition: ERF_ImmersedWallStability.H:77

Referenced by compute_if_most_target_vel(), ImmersedForcingBuildings_Scalar(), ImmersedForcingTerrain_Scalar(), ImmersedForcingTerrain_Xmom(), and ImmersedForcingTerrain_Ymom().

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

◆ clamped_ustar()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ib_stability::clamped_ustar ( amrex::Real  ustar)
noexcept

The friction velocity held within [0, 2] m/s, a NaN going to 0: the wall law's guard against a log-law denominator that cancels or changes sign.

110  {
111  if (!(ustar > amrex::Real(0.0) && !std::isnan(ustar))) { ustar = amrex::Real(0.0); }
112  if (!(ustar < amrex::Real(2.0) && !std::isnan(ustar))) { ustar = amrex::Real(2.0); }
113  return ustar;
114  }
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ ustar
Definition: ERF_SLM.H:28

Referenced by compute_if_most_target_vel(), ImmersedForcingBuildings_Scalar(), ImmersedForcingTerrain_Scalar(), ImmersedForcingTerrain_Xmom(), and ImmersedForcingTerrain_Ymom().

Here is the caller graph for this function:

◆ floored_wind()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ib_stability::floored_wind ( amrex::Real  speed,
amrex::Real  wind_floor 
)
noexcept

The wind speed the stability estimate uses: the speed, floored at wind_floor (>= 0).

39  {
40  return amrex::max(speed, wind_floor);
41  }

Referenced by compute_if_most_target_vel(), ImmersedForcingBuildings_Scalar(), ImmersedForcingTerrain_Scalar(), ImmersedForcingTerrain_Xmom(), and ImmersedForcingTerrain_Ymom().

Here is the caller graph for this function:

◆ psi_cap()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ib_stability::psi_cap ( amrex::Real  z,
amrex::Real  z0,
amrex::Real  factor 
)
noexcept

The largest psi (momentum or heat) the wall law uses at height z: factor ln(z / z0) for 0 < factor <= 1, and never more than ln(z / z0). For z > z0 a factor below 1 keeps ln(z / z0) - psi at no less than (1 - factor) ln(z / z0) > 0, so strongly unstable air still carries momentum and heat between the wall and the cell above; a cap of ln(z / z0) itself makes the target zero (momentum) or the value above (heat). For z <= z0, where the log law does not hold, the cap stays ln(z / z0).

78  {
79  const amrex::Real ln = std::log(z / z0);
80  return amrex::min(factor * ln, ln);
81  }

Referenced by capped_psi().

Here is the caller graph for this function:

◆ psi_m_for_ustar()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ib_stability::psi_m_for_ustar ( amrex::Real  psi_m,
amrex::Real  z,
amrex::Real  z0,
amrex::Real  factor 
)
noexcept

psi_m in the friction velocity u* = U kappa / (ln(z / z0) - psi_m) at height z: held at or below factor ln(z / z0), as WRF caps PSIM before it forms UST, so the denominator stays at least (1 - factor) ln(z / z0) > 0 and strongly unstable air keeps a positive u*. Uncapped for factor = 1 (a cap of ln(z / z0) would zero the denominator) and for z <= z0, where the log law does not hold; there the wall law's u* clamp handles a denominator of either sign.

99  {
100  const amrex::Real ln = std::log(z / z0);
101  return (factor < amrex::Real(1.0) && ln > amrex::Real(0.0)) ? amrex::min(psi_m, factor * ln) : psi_m;
102  }

Referenced by compute_if_most_target_vel(), ImmersedForcingTerrain_Xmom(), and ImmersedForcingTerrain_Ymom().

Here is the caller graph for this function:

◆ zeta_max()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ib_stability::zeta_max ( )
noexcept

Largest |zeta| = |z / L| the wall law uses.

34 { return amrex::Real(100.0); }

Referenced by bounded_obukhov_length(), and bounded_zeta().

Here is the caller graph for this function: