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

Functions

void fill_sea_level_pressure (MultiFab &destination, int destination_component, const MultiFab &conserved_state, const MultiFab &physical_nodal_height, int vapor_component, int klo)
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real specific_humidity_from_dry_mixing_ratio (amrex::Real vapor_mixing_ratio) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real virtual_temperature (amrex::Real temperature, amrex::Real specific_humidity) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real apply_shuell_correction (amrex::Real virtual_temperature_surface, amrex::Real virtual_temperature_sea_level) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real reconstruct_surface_pressure (amrex::Real pressure_lowest_level, amrex::Real virtual_temperature_lowest_level, amrex::Real virtual_temperature_surface, amrex::Real height_lowest_level, amrex::Real height_surface) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real reduce_surface_pressure_to_sea_level (amrex::Real surface_pressure, amrex::Real temperature_lowest_level, amrex::Real specific_humidity, amrex::Real height_lowest_level, amrex::Real height_surface) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real compute_from_erf_lowest_level_state (amrex::Real dry_density, amrex::Real dry_density_times_potential_temperature, amrex::Real vapor_mixing_ratio, amrex::Real height_lowest_level, amrex::Real height_surface) noexcept
 
void fill_sea_level_pressure (amrex::MultiFab &destination, int destination_component, const amrex::MultiFab &conserved_state, const amrex::MultiFab &physical_nodal_height, int vapor_component, int klo)
 

Variables

constexpr amrex::Real lapse_rate = amrex::Real(0.0065)
 
constexpr amrex::Real shuell_critical_temperature = amrex::Real(290.66)
 
constexpr amrex::Real shuell_quadratic_coefficient = amrex::Real(0.005)
 
constexpr amrex::Real sea_level_height = amrex::Real(0.0)
 
constexpr amrex::Real surface_height_deadband = amrex::Real(1.0)
 

Detailed Description

NMC/NGM sea-level-pressure reduction with the Shuell correction.

The algorithm and empirical parameters are adapted from NOAA-EMC UPP, sorc/ncep_post.fd/NGMSLP.f, commit 1ee7b175c340a566287a987870d925e4708fe19b.

This ERF implementation uses ERF's native thermodynamic constants and reconstructs ground-interface pressure from the lowest cell-centered atmospheric state. It is therefore an adaptation of the UPP algorithm, not a bit-for-bit reproduction of UPP output.

Function Documentation

◆ apply_shuell_correction()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sea_level_pressure_diagnostics::apply_shuell_correction ( amrex::Real  virtual_temperature_surface,
amrex::Real  virtual_temperature_sea_level 
)
noexcept

Apply the NMC/NGM Shuell correction to the sea-level virtual temperature.

The strict/non-strict comparisons reproduce NGMSLP.f exactly. The quadratic temperature form is algebraically equivalent to UPP's tau-space form.

Parameters
[in]virtual_temperature_surfaceGround-interface virtual temperature [K].
[in]virtual_temperature_sea_levelUncorrected sea-level virtual temperature [K].
Returns
Corrected sea-level virtual temperature [K].
74 {
75  if (virtual_temperature_sea_level > shuell_critical_temperature &&
76  virtual_temperature_surface <= shuell_critical_temperature) {
78  } else if (virtual_temperature_sea_level > shuell_critical_temperature &&
79  virtual_temperature_surface > shuell_critical_temperature) {
82  (virtual_temperature_surface - shuell_critical_temperature) *
83  (virtual_temperature_surface - shuell_critical_temperature);
84  }
85  return virtual_temperature_sea_level;
86 }
constexpr amrex::Real shuell_quadratic_coefficient
Definition: ERF_SeaLevelPressure.H:30
constexpr amrex::Real shuell_critical_temperature
Definition: ERF_SeaLevelPressure.H:29

Referenced by reduce_surface_pressure_to_sea_level().

Here is the caller graph for this function:

◆ compute_from_erf_lowest_level_state()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sea_level_pressure_diagnostics::compute_from_erf_lowest_level_state ( amrex::Real  dry_density,
amrex::Real  dry_density_times_potential_temperature,
amrex::Real  vapor_mixing_ratio,
amrex::Real  height_lowest_level,
amrex::Real  height_surface 
)
noexcept

Compute the complete NMC/NGM reduction from an ERF conserved state.

ERF stores dry density, dry density times potential temperature, and (when active) dry-density times vapor mixing ratio. The pressure and temperature are diagnosed through ERF's EOS, then pressure is reconstructed at the ground interface before the method-specific sea-level reduction.

Parameters
[in]dry_densityLowest-level dry-air density [kg/m^3].
[in]dry_density_times_potential_temperatureLowest-level rho_d theta [kg K/m^3].
[in]vapor_mixing_ratioLowest-level vapor mixing ratio [kg/kg dry air].
[in]height_lowest_levelLowest cell-center physical height [m].
[in]height_surfaceGround-interface physical height [m].
Returns
Pressure reduced to physical z=0 [Pa].
Precondition
State and heights are finite and physically valid; use zero mixing ratio for dry runs.
175 {
176  const amrex::Real specific_humidity =
178  const amrex::Real pressure_lowest =
179  getPgivenRTh(dry_density_times_potential_temperature,
181  const amrex::Real temperature_lowest =
182  getTgivenRandRTh(dry_density,
183  dry_density_times_potential_temperature,
185  const amrex::Real virtual_temperature_lowest =
186  virtual_temperature(temperature_lowest, specific_humidity);
187  const amrex::Real virtual_temperature_surface =
188  virtual_temperature_lowest + lapse_rate *
189  (height_lowest_level - height_surface);
190  const amrex::Real pressure_surface = reconstruct_surface_pressure(
191  pressure_lowest, virtual_temperature_lowest, virtual_temperature_surface,
192  height_lowest_level, height_surface);
193 
195  pressure_surface, temperature_lowest, specific_humidity,
196  height_lowest_level, height_surface);
197 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenRandRTh(const amrex::Real rho, const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:46
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:81
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Real vapor_mixing_ratio(const Real p_b, const Real T_b, const Real RH, const bool use_empirical, int which_zone)
Definition: ERF_HSEUtils.H:462
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real virtual_temperature(amrex::Real temperature, amrex::Real specific_humidity) noexcept
Definition: ERF_SeaLevelPressure.H:54
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real reduce_surface_pressure_to_sea_level(amrex::Real surface_pressure, amrex::Real temperature_lowest_level, amrex::Real specific_humidity, amrex::Real height_lowest_level, amrex::Real height_surface) noexcept
Definition: ERF_SeaLevelPressure.H:122
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real specific_humidity_from_dry_mixing_ratio(amrex::Real vapor_mixing_ratio) noexcept
Definition: ERF_SeaLevelPressure.H:41
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real reconstruct_surface_pressure(amrex::Real pressure_lowest_level, amrex::Real virtual_temperature_lowest_level, amrex::Real virtual_temperature_surface, amrex::Real height_lowest_level, amrex::Real height_surface) noexcept
Definition: ERF_SeaLevelPressure.H:98
constexpr amrex::Real lapse_rate
Definition: ERF_SeaLevelPressure.H:28

Referenced by fill_sea_level_pressure().

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

◆ fill_sea_level_pressure() [1/2]

void sea_level_pressure_diagnostics::fill_sea_level_pressure ( amrex::MultiFab &  destination,
int  destination_component,
const amrex::MultiFab &  conserved_state,
const amrex::MultiFab &  physical_nodal_height,
int  vapor_component,
int  klo 
)

Fill one selected 2D field from each column's lowest ERF state.

Parameters
[out]destination2D destination MultiFab; only destination_component is written.
[in]destination_componentComponent to fill in destination.
[in]conserved_stateCell-centered ERF conserved state MultiFab.
[in]physical_nodal_heightAbsolute physical nodal heights [m].
[in]vapor_componentConserved vapor component, or -1 for a dry run.
[in]kloLowest valid source-state vertical index for this AMR level.

◆ fill_sea_level_pressure() [2/2]

void sea_level_pressure_diagnostics::fill_sea_level_pressure ( MultiFab &  destination,
int  destination_component,
const MultiFab &  conserved_state,
const MultiFab &  physical_nodal_height,
int  vapor_component,
int  klo 
)
20 {
21  AMREX_ALWAYS_ASSERT(destination_component >= 0);
22  AMREX_ALWAYS_ASSERT(destination_component < destination.nComp());
23  AMREX_ALWAYS_ASSERT(conserved_state.nComp() > Rho_comp);
24  AMREX_ALWAYS_ASSERT(conserved_state.nComp() > RhoTheta_comp);
25  AMREX_ALWAYS_ASSERT(vapor_component < 0 || vapor_component < conserved_state.nComp());
26 
27 #ifdef _OPENMP
28 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
29 #endif
30  for (MFIter mfi(destination, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
31  const Box& bx = mfi.tilebox();
32  const auto destination_arr = destination.array(mfi);
33  const auto conserved_arr = conserved_state.const_array(mfi);
34  const auto height_arr = physical_nodal_height.const_array(mfi);
35 
36  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
37  const Real dry_density = conserved_arr(i, j, klo, Rho_comp);
38  const Real dry_density_times_potential_temperature =
39  conserved_arr(i, j, klo, RhoTheta_comp);
40  const Real vapor_mixing_ratio = vapor_component < 0
41  ? zero
42  : conserved_arr(i, j, klo, vapor_component) / dry_density;
43  const Real height_lowest_level =
44  Compute_Z_AtCellCenter(i, j, klo, height_arr);
45  const Real height_surface = Compute_Z_AtWFace(i, j, klo, height_arr);
46 
47  destination_arr(i, j, k, destination_component) =
49  dry_density, dry_density_times_potential_temperature,
50  vapor_mixing_ratio, height_lowest_level, height_surface);
51  });
52  }
53 }
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Z_AtCellCenter(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:361
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Z_AtWFace(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:376
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real compute_from_erf_lowest_level_state(amrex::Real dry_density, amrex::Real dry_density_times_potential_temperature, amrex::Real vapor_mixing_ratio, amrex::Real height_lowest_level, amrex::Real height_surface) noexcept
Definition: ERF_SeaLevelPressure.H:169

Referenced by ERF::Write2DPlotFile().

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

◆ reconstruct_surface_pressure()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sea_level_pressure_diagnostics::reconstruct_surface_pressure ( amrex::Real  pressure_lowest_level,
amrex::Real  virtual_temperature_lowest_level,
amrex::Real  virtual_temperature_surface,
amrex::Real  height_lowest_level,
amrex::Real  height_surface 
)
noexcept

Reconstruct pressure at the lower terrain interface from the lowest cell.

Parameters
[in]pressure_lowest_levelLowest cell-center pressure [Pa].
[in]virtual_temperature_lowest_levelLowest cell-center virtual temperature [K].
[in]virtual_temperature_surfaceGround-interface virtual temperature [K].
[in]height_lowest_levelLowest cell-center physical height [m].
[in]height_surfaceGround-interface physical height [m].
Returns
Ground-interface pressure [Pa].
104 {
105  const amrex::Real mean_tau = (R_d / CONST_GRAV) *
106  (virtual_temperature_lowest_level + virtual_temperature_surface) /
107  amrex::Real(2.0);
108  return pressure_lowest_level * std::exp(
109  (height_lowest_level - height_surface) / mean_tau);
110 }
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:64
constexpr amrex::Real R_d
Definition: ERF_Constants.H:47

Referenced by compute_from_erf_lowest_level_state().

Here is the caller graph for this function:

◆ reduce_surface_pressure_to_sea_level()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sea_level_pressure_diagnostics::reduce_surface_pressure_to_sea_level ( amrex::Real  surface_pressure,
amrex::Real  temperature_lowest_level,
amrex::Real  specific_humidity,
amrex::Real  height_lowest_level,
amrex::Real  height_surface 
)
noexcept

Reconstruct ground-interface pressure and reduce it to physical z=0.

Parameters
[in]surface_pressureGround-interface pressure [Pa].
[in]temperature_lowest_levelLowest cell-center temperature [K].
[in]specific_humidityLowest-level specific humidity [kg/kg].
[in]height_lowest_levelLowest cell-center physical height [m].
[in]height_surfaceGround-interface physical height [m].
Returns
Pressure reduced to the physical z=0 datum [Pa].
128 {
129  const amrex::Real virtual_temperature_lowest =
130  virtual_temperature(temperature_lowest_level, specific_humidity);
131  const amrex::Real virtual_temperature_surface =
132  virtual_temperature_lowest + lapse_rate *
133  (height_lowest_level - height_surface);
134  const amrex::Real virtual_temperature_sea_level =
135  virtual_temperature_lowest + lapse_rate *
136  (height_lowest_level - sea_level_height);
137  const amrex::Real corrected_virtual_temperature_sea_level =
138  apply_shuell_correction(virtual_temperature_surface,
139  virtual_temperature_sea_level);
140  const amrex::Real mean_tau_surface_sea_level =
141  (R_d / CONST_GRAV) *
142  (virtual_temperature_surface + corrected_virtual_temperature_sea_level) /
143  amrex::Real(2.0);
144 
145  if (amrex::Math::abs(height_surface - sea_level_height) <=
147  return surface_pressure;
148  }
149  return surface_pressure * std::exp(
150  (height_surface - sea_level_height) / mean_tau_surface_sea_level);
151 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real apply_shuell_correction(amrex::Real virtual_temperature_surface, amrex::Real virtual_temperature_sea_level) noexcept
Definition: ERF_SeaLevelPressure.H:72
constexpr amrex::Real sea_level_height
Definition: ERF_SeaLevelPressure.H:31
constexpr amrex::Real surface_height_deadband
Definition: ERF_SeaLevelPressure.H:32

Referenced by compute_from_erf_lowest_level_state().

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

◆ specific_humidity_from_dry_mixing_ratio()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sea_level_pressure_diagnostics::specific_humidity_from_dry_mixing_ratio ( amrex::Real  vapor_mixing_ratio)
noexcept

Convert ERF dry-air water-vapor mixing ratio to specific humidity.

Parameters
[in]vapor_mixing_ratioWater vapor mass per unit dry-air mass [kg/kg].
Returns
Specific humidity used by the NMC/NGM reduction [kg/kg].
Precondition
The mixing ratio is finite and nonnegative.
43 {
45 }

Referenced by compute_from_erf_lowest_level_state().

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

◆ virtual_temperature()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sea_level_pressure_diagnostics::virtual_temperature ( amrex::Real  temperature,
amrex::Real  specific_humidity 
)
noexcept

Compute virtual temperature using ERF's native gas constants.

Parameters
[in]temperaturePhysical temperature [K].
[in]specific_humiditySpecific humidity [kg/kg].
Returns
Virtual temperature [K].
56 {
57  // UPP uses rounded 0.608; ERF uses the equivalent coefficient from its
58  // shared R_d and R_v so the diagnostic remains EOS-consistent.
59  return temperature * (amrex::Real(1.0) + epsv * specific_humidity);
60 }
constexpr amrex::Real epsv
Definition: ERF_Constants.H:53

Referenced by compute_from_erf_lowest_level_state(), and reduce_surface_pressure_to_sea_level().

Here is the caller graph for this function:

Variable Documentation

◆ lapse_rate

constexpr amrex::Real sea_level_pressure_diagnostics::lapse_rate = amrex::Real(0.0065)
constexpr

◆ sea_level_height

constexpr amrex::Real sea_level_pressure_diagnostics::sea_level_height = amrex::Real(0.0)
constexpr

◆ shuell_critical_temperature

constexpr amrex::Real sea_level_pressure_diagnostics::shuell_critical_temperature = amrex::Real(290.66)
constexpr

Referenced by apply_shuell_correction().

◆ shuell_quadratic_coefficient

constexpr amrex::Real sea_level_pressure_diagnostics::shuell_quadratic_coefficient = amrex::Real(0.005)
constexpr

Referenced by apply_shuell_correction().

◆ surface_height_deadband

constexpr amrex::Real sea_level_pressure_diagnostics::surface_height_deadband = amrex::Real(1.0)
constexpr