|
ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
|
Per-column two-stream radiation kernels. More...
#include <algorithm>#include <cmath>#include <type_traits>#include <AMReX_Array4.H>#include <AMReX_Box.H>#include <AMReX_Geometry.H>#include <AMReX_GpuControl.H>#include <AMReX_Math.H>#include <AMReX_REAL.H>#include <ERF_Constants.H>#include <ERF_EOS.H>#include <ERF_IndexDefines.H>#include <ERF_RadStruct.H>#include <ERF_TwoStreamSW.H>#include <ERF_TwoStreamLW.H>#include <ERF_PrognosticCloudFraction.H>#include <ERF_AerosolOpticalDepth.H>#include <ERF_OrbCosZenith.H>#include <ERF_SurfaceTemperature.H>#include <ERF_TerrainMetrics.H>

Go to the source code of this file.
Classes | |
| struct | TwoStreamParams |
| Trivially copyable subset of RadChoice used by the column kernels. More... | |
Namespaces | |
| TwoStreamScratch | |
| Per-column scratch the sweep keeps in a caller-provided Array4. | |
Functions | |
| TwoStreamParams | make_two_stream_params (const RadChoice &rc, const amrex::Real rdOcp) |
| Copy the column-kernel parameters out of a RadChoice. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | get_temperature_from_rhotheta (amrex::Real rho_theta, amrex::Real rho, amrex::Real qv=0.0) |
| GPU-safe helper to compute absolute temperature from (rho, rho*theta). More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool | valid_surface_temperature (amrex::Real value) |
| Check whether a heterogeneous absolute surface temperature is valid. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | resolve_surface_albedo_sw (int i, int j, const amrex::Array4< const amrex::Real > *hetero_alb_sw, const TwoStreamParams &rad_choice, bool has_hetero_alb) |
| Resolve per-column shortwave surface albedo from hetero field or fallback. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | resolve_surface_emissivity_lw (int i, int j, const amrex::Array4< const amrex::Real > *hetero_emiss_lw, const TwoStreamParams &rad_choice, bool has_hetero_emiss) |
| Resolve per-column longwave surface emissivity from hetero field or fallback. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | resolve_surface_temp_k (int i, int j, const amrex::Array4< const amrex::Real > *lsm_t_sfc, bool has_lsm_t_sfc, const amrex::Array4< const amrex::Real > *seb_t_sfc, bool has_seb_t_sfc, const amrex::Array4< const amrex::Real > *surface_layer_theta, bool has_surface_layer, const TwoStreamParams &rad_choice, bool &from_surface_layer) |
| Resolve the per-column surface-temperature boundary condition. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool | is_cloud_level (amrex::Real z_center, const TwoStreamParams &rad_choice) |
| GPU-safe helper to determine whether a layer falls within the cloud band [cloud_base_height_m, cloud_top_height_m]. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | get_qv_from_state (int i, int j, int k, const amrex::Array4< const amrex::Real > &state_arr) |
| Water-vapor mixing ratio qv = RhoQv / Rho at (i,j,k). More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | get_inverse_exner (int i, int j, int k, const amrex::Array4< const amrex::Real > &state_arr) |
| Inverse Exner function 1/pi at (i,j,k) from the state, with pi = (p / p_0)^(R_d/c_p) evaluated by getExnergivenRTh(). Used to convert a temperature tendency dT/dt into the potential-temperature tendency dtheta/dt = (dT/dt) / pi that the RhoTheta source term expects. Returns 1 for unphysical input. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | get_qc_from_state (int i, int j, int k, const amrex::Array4< const amrex::Real > &state_arr) |
| Cloud-water mixing ratio qc = RhoQc / Rho at (i,j,k). More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | diagnose_tau_dynamic (amrex::Real tau_base, amrex::Real qv, amrex::Real qc, amrex::Real coeff_qv, amrex::Real coeff_qc) |
| Moisture-dependent (dynamic) per-layer optical depth. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | tau_layer_value (amrex::Real z_center, amrex::Real tau_base, const TwoStreamParams &rad_choice, bool apply_cloud) |
| GPU-safe helper to compute the per-layer optical depth at level k, given the base (clear-sky) optical depth and cloud-layer parameters. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void | select_scattering_props (amrex::Real z_center, const TwoStreamParams &rad_choice, bool apply_cloud, amrex::Real &omega, amrex::Real &g) |
| GPU-safe helper to select the single-scattering albedo and asymmetry factor to use for level k's diffuse SW calculation. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | diagnose_cloud_fraction_prognostic (int i, int j, int k, const amrex::Array4< const amrex::Real > &state_arr, const TwoStreamParams &rad_choice) |
| GPU-safe helper to diagnose prognostic cloud fraction from per-level relative humidity and cloud liquid water. More... | |
| amrex::Box | two_stream_scratch_box (const amrex::Box &bx) |
| Box of the scratch FArrayBox a sweep over box bx needs. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real | diagnose_layer_tau (int i, int j, int k, amrex::Real dz_layer, amrex::Real z_center, const amrex::Array4< const amrex::Real > &state_arr, amrex::Real tau_base, bool is_sw, bool cloudy, const TwoStreamParams &rad_choice) |
| GPU-safe helper to assemble the total per-layer optical depth at level k for either the SW or the LW band. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void | diagnose_layer_optics (int i, int j, int k, amrex::Real dz_layer, amrex::Real z_center, const amrex::Array4< const amrex::Real > &state_arr, amrex::Real tau_base, bool is_sw, bool cloudy, const TwoStreamParams &rad_choice, amrex::Real &tau, amrex::Real &omega, amrex::Real &g) |
| Optical depth, single-scattering albedo and asymmetry factor of layer k for one band, for either optical-depth model. More... | |
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void | vertical_two_stream_sweep (int i, int j, const amrex::Box &bx, amrex::Real dz_uniform, const amrex::Array4< const amrex::Real > &state_arr, const TwoStreamParams &rad_choice, bool cloudy, const amrex::Array4< amrex::Real > &qheating_arr, amrex::Real &max_heating_rate, amrex::Real &sw_surface_flux, amrex::Real &sw_up_toa, amrex::Real &lw_net_surface, amrex::Real &lw_up_toa, amrex::Real &sw_down_toa, const amrex::Array4< const amrex::Real > &z_phys_nd, const amrex::Array4< amrex::Real > &scratch, bool has_hetero_alb_sw=false, const amrex::Array4< const amrex::Real > *hetero_alb_sw=nullptr, bool has_hetero_emiss_lw=false, const amrex::Array4< const amrex::Real > *hetero_emiss_lw=nullptr, bool has_lsm_t_sfc=false, const amrex::Array4< const amrex::Real > *lsm_t_sfc=nullptr, bool has_seb_t_sfc=false, const amrex::Array4< const amrex::Real > *seb_t_sfc=nullptr, bool has_surface_layer=false, const amrex::Array4< const amrex::Real > *surface_layer_theta=nullptr, bool has_latlon=false, const amrex::Array4< const amrex::Real > *lat_arr=nullptr, const amrex::Array4< const amrex::Real > *lon_arr=nullptr, const amrex::Array4< amrex::Real > *rad_flux_out=nullptr) |
GPU-safe per-column vertical integration kernel for two-stream radiation, computing either the clear-sky or cloudy-column fluxes and per-level heating rates, depending on the cloudy flag. More... | |
Variables | |
| constexpr int | TwoStreamScratch::DZ = 0 |
| constexpr int | TwoStreamScratch::Z = 1 |
| constexpr int | TwoStreamScratch::TAU_SW = 2 |
| constexpr int | TwoStreamScratch::F_DIR = 3 |
| constexpr int | TwoStreamScratch::A = 4 |
| constexpr int | TwoStreamScratch::S = 5 |
| constexpr int | TwoStreamScratch::LW_UP = 6 |
| constexpr int | TwoStreamScratch::LW_DN = 7 |
| constexpr int | TwoStreamScratch::TAU_LW = 8 |
| constexpr int | TwoStreamScratch::NCOMP = 9 |
Per-column two-stream radiation kernels.
Everything needed to evaluate one (i,j) column of the two-stream model: temperature from the equation of state, per-column surface properties, per-layer optical depth assembly, and vertical_two_stream_sweep(), which performs the SW and LW sweeps and writes per-level heating rates.
Vertical orientation follows ERF: k = kmin is the surface layer and k = kmax the top layer. SW sweeps downward from kmax to kmin; LW sweeps downward (TOA -> surface) and then upward (surface -> TOA) on layer interfaces. Layer temperature is obtained from rho*theta through the Exner function.
The functions are header-only and GPU-safe so that the column physics can be exercised directly by unit tests (Tests/Unit/Radiation) as well as by the level driver in ERF_TwoStreamRadiation.cpp (TwoStreamRadiation::advance).
| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real diagnose_cloud_fraction_prognostic | ( | int | i, |
| int | j, | ||
| int | k, | ||
| const amrex::Array4< const amrex::Real > & | state_arr, | ||
| const TwoStreamParams & | rad_choice | ||
| ) |
GPU-safe helper to diagnose prognostic cloud fraction from per-level relative humidity and cloud liquid water.
Computes cloud fraction from RH and qc using: cf_rh(k) = linear ramp from 0 at rh_min to 1 at rh_max cf_qc(k) = qc_scale * qc(k) cf(k) = min(1, cf_rh + cf_qc) [saturated blend]
Temperature comes from the equation of state (Exner function) and pressure from getPgivenRTh(), both evaluated with the local qv. Returns 0 when cloud_fraction_prog_enable is false.
| [in] | i,j,k | Grid indices |
| [in] | state_arr | State array proxy (contains Rho, RhoTheta, qv, qc) |
| [in] | rad_choice | Radiation parameters (prognostic cloud fraction settings) |
Referenced by diagnose_layer_optics(), and diagnose_layer_tau().


| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void diagnose_layer_optics | ( | int | i, |
| int | j, | ||
| int | k, | ||
| amrex::Real | dz_layer, | ||
| amrex::Real | z_center, | ||
| const amrex::Array4< const amrex::Real > & | state_arr, | ||
| amrex::Real | tau_base, | ||
| bool | is_sw, | ||
| bool | cloudy, | ||
| const TwoStreamParams & | rad_choice, | ||
| amrex::Real & | tau, | ||
| amrex::Real & | omega, | ||
| amrex::Real & | g | ||
| ) |
Optical depth, single-scattering albedo and asymmetry factor of layer k for one band, for either optical-depth model.
Per-layer model (default): the optical depth comes from diagnose_layer_tau() and the scattering properties from the clear-sky or cloud-band inputs through select_scattering_props(), exactly as before.
Mass model (tau_model = mass), shortwave: each constituent contributes an extinction optical depth from the layer mass path, dry absorption rho dz sw_kabs_dry (omega = 0) Rayleigh rho dz sw_kscat_dry (omega = 1, g = 0) water vapor rho dz sw_kabs_vapor qv (omega = 0) cloud water rho dz sw_kext_cloud qc (sw_cloud_omega, sw_cloud_g) plus the prescribed cloud-band enhancement (with the cloud-band scattering inputs) and the absorbing moisture-coefficient and aerosol additions. The layer properties are the extinction-weighted mixtures tau = sum tau_i, omega = sum omega_i tau_i / tau, g = sum g_i omega_i tau_i / sum omega_i tau_i. Longwave uses diagnose_layer_tau(), whose clear-sky base is the mass path rho dz (lw_kabs_dry + lw_kabs_vapor qv + lw_kabs_cloud qc) in this model.
| [in] | i,j,k | Grid indices (kmin is the surface layer). |
| [in] | dz_layer | Thickness of this layer [m]. |
| [in] | z_center | Height of the layer center above the surface [m]. |
| [in] | state_arr | State array (read-only). |
| [in] | tau_base | Per-layer-model clear-sky optical depth for this band. |
| [in] | is_sw | true for the shortwave band, false for longwave. |
| [in] | cloudy | true for the cloudy-column evaluation. |
| [in] | rad_choice | Column-kernel parameters. |
| [out] | tau | Optical depth of the layer [unitless]. |
| [out] | omega | Single-scattering albedo of the layer (0 for LW). |
| [out] | g | Asymmetry factor of the layer (0 for LW). |
Referenced by vertical_two_stream_sweep().


| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real diagnose_layer_tau | ( | int | i, |
| int | j, | ||
| int | k, | ||
| amrex::Real | dz_layer, | ||
| amrex::Real | z_center, | ||
| const amrex::Array4< const amrex::Real > & | state_arr, | ||
| amrex::Real | tau_base, | ||
| bool | is_sw, | ||
| bool | cloudy, | ||
| const TwoStreamParams & | rad_choice | ||
| ) |
GPU-safe helper to assemble the total per-layer optical depth at level k for either the SW or the LW band.
The contributions are applied in the same order for both bands:
| [in] | i,j,k | Grid indices (k increases upward; kmin is the surface layer). |
| [in] | dz_layer | Thickness of this layer [m]. |
| [in] | z_center | Height of the layer center above the surface [m] (cloud-band detection and the aerosol profile). |
| [in] | state_arr | State array (read-only). |
| [in] | tau_base | Clear-sky optical depth per layer for this band (for LW, replaced by the mass-path value when lw_mass_absorption_enable or tau_model = mass is set). |
| [in] | is_sw | true for the shortwave band, false for longwave. |
| [in] | cloudy | true for the cloudy-column evaluation. |
| [in] | rad_choice | Radiation parameters. |
Referenced by diagnose_layer_optics(), and vertical_two_stream_sweep().


| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real diagnose_tau_dynamic | ( | amrex::Real | tau_base, |
| amrex::Real | qv, | ||
| amrex::Real | qc, | ||
| amrex::Real | coeff_qv, | ||
| amrex::Real | coeff_qc | ||
| ) |
Moisture-dependent (dynamic) per-layer optical depth.
tau = tau_base + coeff_qv * qv + coeff_qc * qc
clamped to [0, 100]. With both coefficients zero this returns tau_base unchanged, so the static configuration is reproduced exactly. Used for both the SW and the LW band with the respective coefficient pair.
| [in] | tau_base | Optical depth before the moisture contribution [unitless]. |
| [in] | qv | Water-vapor mixing ratio [kg/kg]. |
| [in] | qc | Cloud-water mixing ratio [kg/kg]. |
| [in] | coeff_qv | Optical depth per unit qv [unitless per kg/kg]. |
| [in] | coeff_qc | Optical depth per unit qc [unitless per kg/kg]. |
Referenced by diagnose_layer_tau().

| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real get_inverse_exner | ( | int | i, |
| int | j, | ||
| int | k, | ||
| const amrex::Array4< const amrex::Real > & | state_arr | ||
| ) |
Inverse Exner function 1/pi at (i,j,k) from the state, with pi = (p / p_0)^(R_d/c_p) evaluated by getExnergivenRTh(). Used to convert a temperature tendency dT/dt into the potential-temperature tendency dtheta/dt = (dT/dt) / pi that the RhoTheta source term expects. Returns 1 for unphysical input.
Referenced by vertical_two_stream_sweep().


| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real get_qc_from_state | ( | int | i, |
| int | j, | ||
| int | k, | ||
| const amrex::Array4< const amrex::Real > & | state_arr | ||
| ) |
Cloud-water mixing ratio qc = RhoQc / Rho at (i,j,k).
Returns 0 when the state carries no cloud-water component, or when the stored values are non-finite or negative.
Referenced by diagnose_cloud_fraction_prognostic(), diagnose_layer_optics(), and diagnose_layer_tau().

| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real get_qv_from_state | ( | int | i, |
| int | j, | ||
| int | k, | ||
| const amrex::Array4< const amrex::Real > & | state_arr | ||
| ) |
Water-vapor mixing ratio qv = RhoQv / Rho at (i,j,k).
Returns 0 when the state carries no moisture components, or when the stored values are non-finite or negative.
Referenced by diagnose_cloud_fraction_prognostic(), diagnose_layer_optics(), diagnose_layer_tau(), get_inverse_exner(), and vertical_two_stream_sweep().

| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real get_temperature_from_rhotheta | ( | amrex::Real | rho_theta, |
| amrex::Real | rho, | ||
| amrex::Real | qv = 0.0 |
||
| ) |
GPU-safe helper to compute absolute temperature from (rho, rho*theta).
ERF stores dry density and dry potential temperature. The pressure follows from the equation of state, p = p_0 * (R_d * rho * theta_m / p_0)^gamma, theta_m = theta * (1 + R_v/R_d * qv), and the absolute temperature is recovered through the Exner function, T = theta * (p / p_0)^(R_d / c_p), which getTgivenRandRTh() evaluates as p / (R_d * rho * (1 + R_v/R_d * qv)).
| [in] | rho_theta | RhoTheta component [K·kg/m^3] |
| [in] | rho | Density [kg/m^3] |
| [in] | qv | Water-vapor mixing ratio [kg/kg] (0 for dry air) |
Referenced by diagnose_cloud_fraction_prognostic(), and vertical_two_stream_sweep().


| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool is_cloud_level | ( | amrex::Real | z_center, |
| const TwoStreamParams & | rad_choice | ||
| ) |
GPU-safe helper to determine whether a layer falls within the cloud band [cloud_base_height_m, cloud_top_height_m].
| [in] | z_center | Height of the layer center above the surface [m]. |
| [in] | rad_choice | Radiation parameters. |
Referenced by diagnose_layer_optics(), diagnose_layer_tau(), select_scattering_props(), and tau_layer_value().

|
inline |
Copy the column-kernel parameters out of a RadChoice.
Referenced by TwoStreamRadiation::advance().

| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real resolve_surface_albedo_sw | ( | int | i, |
| int | j, | ||
| const amrex::Array4< const amrex::Real > * | hetero_alb_sw, | ||
| const TwoStreamParams & | rad_choice, | ||
| bool | has_hetero_alb | ||
| ) |
Resolve per-column shortwave surface albedo from hetero field or fallback.
Precedence:
| [in] | i,j | Column index |
| [in] | hetero_alb_sw | Heterogeneous SW albedo field (may be nullptr) |
| [in] | rad_choice | Radiation parameters with fallback surface_albedo_sw |
| [in] | has_hetero_alb | true if hetero_alb_sw is available |
Referenced by vertical_two_stream_sweep().

| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real resolve_surface_emissivity_lw | ( | int | i, |
| int | j, | ||
| const amrex::Array4< const amrex::Real > * | hetero_emiss_lw, | ||
| const TwoStreamParams & | rad_choice, | ||
| bool | has_hetero_emiss | ||
| ) |
Resolve per-column longwave surface emissivity from hetero field or fallback.
Precedence:
| [in] | i,j | Column index |
| [in] | hetero_emiss_lw | Heterogeneous LW emissivity field (may be nullptr) |
| [in] | rad_choice | Radiation parameters with fallback surface_emissivity_lw |
| [in] | has_hetero_emiss | true if hetero_emiss_lw is available |
Referenced by vertical_two_stream_sweep().

| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real resolve_surface_temp_k | ( | int | i, |
| int | j, | ||
| const amrex::Array4< const amrex::Real > * | lsm_t_sfc, | ||
| bool | has_lsm_t_sfc, | ||
| const amrex::Array4< const amrex::Real > * | seb_t_sfc, | ||
| bool | has_seb_t_sfc, | ||
| const amrex::Array4< const amrex::Real > * | surface_layer_theta, | ||
| bool | has_surface_layer, | ||
| const TwoStreamParams & | rad_choice, | ||
| bool & | from_surface_layer | ||
| ) |
Resolve the per-column surface-temperature boundary condition.
The candidates remain separate until this per-cell resolver runs. This is important for an LSM field that exists globally but contains an undefined value in an individual column.
Precedence for each column:
Only the SurfaceLayer candidate is converted by the caller. The LSM and prognostic SEB candidates already satisfy the absolute-temperature contract.
| [in] | i,j | Column index |
| [in] | lsm_t_sfc | LSM absolute-temperature field (may be nullptr) |
| [in] | has_lsm_t_sfc | true if the LSM field is available |
| [in] | seb_t_sfc | prognostic SEB absolute-temperature field (may be nullptr) |
| [in] | has_seb_t_sfc | true if the prognostic SEB field is available |
| [in] | surface_layer_theta | SurfaceLayer potential-temperature field (may be nullptr) |
| [in] | has_surface_layer | true if the SurfaceLayer field is available |
| [in] | rad_choice | Radiation parameters with the fallback t_sfc_default |
| [out] | from_surface_layer | true when the returned value is SurfaceLayer theta |
Referenced by vertical_two_stream_sweep().


| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void select_scattering_props | ( | amrex::Real | z_center, |
| const TwoStreamParams & | rad_choice, | ||
| bool | apply_cloud, | ||
| amrex::Real & | omega, | ||
| amrex::Real & | g | ||
| ) |
GPU-safe helper to select the single-scattering albedo and asymmetry factor to use for level k's diffuse SW calculation.
When this column evaluation applies the cloud-layer enhancement (apply_cloud == true, tau_profile_type == CloudLayer, and level k falls within the cloud band), the cloud scattering properties (cloud_single_scattering_albedo, cloud_asymmetry_factor) are used. Otherwise, the clear-sky scattering properties (single_scattering_albedo, asymmetry_factor) are used. Both default to 0.0, so by default this function always yields omega == 0.0 and the layers neither scatter the direct beam nor reflect diffuse light; the diffuse field then consists of the surface-reflected beam only.
| [in] | z_center | Height of the layer center above the surface [m]. |
| [in] | rad_choice | Radiation parameters. |
| [in] | apply_cloud | Same flag passed to tau_layer_value(); true for the cloudy-column evaluation, false for the clear-sky column evaluation. |
| [out] | omega | Selected single-scattering albedo for this level. |
| [out] | g | Selected asymmetry factor for this level. |
Referenced by diagnose_layer_optics().


| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real tau_layer_value | ( | amrex::Real | z_center, |
| amrex::Real | tau_base, | ||
| const TwoStreamParams & | rad_choice, | ||
| bool | apply_cloud | ||
| ) |
GPU-safe helper to compute the per-layer optical depth at level k, given the base (clear-sky) optical depth and cloud-layer parameters.
When rad_choice.tau_profile_type == Constant, returns tau_base unchanged (byte-identical). When == CloudLayer, adds rad_choice.cloud_tau_per_layer whenever the level height falls within [cloud_base_height_m, cloud_top_height_m].
| [in] | z_center | Height of the layer center above the surface [m]. |
| [in] | tau_base | Clear-sky optical depth per layer. |
| [in] | rad_choice | Radiation parameters. |
| [in] | apply_cloud | If false, always returns tau_base (used for the clear-sky column computation even when cloud_fraction > 0). |
Referenced by diagnose_layer_optics(), and diagnose_layer_tau().


|
inline |
Box of the scratch FArrayBox a sweep over box bx needs.
Referenced by TwoStreamRadiation::advance().

| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool valid_surface_temperature | ( | amrex::Real | value | ) |
Check whether a heterogeneous absolute surface temperature is valid.
Referenced by resolve_surface_temp_k().

| AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void vertical_two_stream_sweep | ( | int | i, |
| int | j, | ||
| const amrex::Box & | bx, | ||
| amrex::Real | dz_uniform, | ||
| const amrex::Array4< const amrex::Real > & | state_arr, | ||
| const TwoStreamParams & | rad_choice, | ||
| bool | cloudy, | ||
| const amrex::Array4< amrex::Real > & | qheating_arr, | ||
| amrex::Real & | max_heating_rate, | ||
| amrex::Real & | sw_surface_flux, | ||
| amrex::Real & | sw_up_toa, | ||
| amrex::Real & | lw_net_surface, | ||
| amrex::Real & | lw_up_toa, | ||
| amrex::Real & | sw_down_toa, | ||
| const amrex::Array4< const amrex::Real > & | z_phys_nd, | ||
| const amrex::Array4< amrex::Real > & | scratch, | ||
| bool | has_hetero_alb_sw = false, |
||
| const amrex::Array4< const amrex::Real > * | hetero_alb_sw = nullptr, |
||
| bool | has_hetero_emiss_lw = false, |
||
| const amrex::Array4< const amrex::Real > * | hetero_emiss_lw = nullptr, |
||
| bool | has_lsm_t_sfc = false, |
||
| const amrex::Array4< const amrex::Real > * | lsm_t_sfc = nullptr, |
||
| bool | has_seb_t_sfc = false, |
||
| const amrex::Array4< const amrex::Real > * | seb_t_sfc = nullptr, |
||
| bool | has_surface_layer = false, |
||
| const amrex::Array4< const amrex::Real > * | surface_layer_theta = nullptr, |
||
| bool | has_latlon = false, |
||
| const amrex::Array4< const amrex::Real > * | lat_arr = nullptr, |
||
| const amrex::Array4< const amrex::Real > * | lon_arr = nullptr, |
||
| const amrex::Array4< amrex::Real > * | rad_flux_out = nullptr |
||
| ) |
GPU-safe per-column vertical integration kernel for two-stream radiation, computing either the clear-sky or cloudy-column fluxes and per-level heating rates, depending on the cloudy flag.
Vertical orientation. ERF's vertical index increases upward: k = kmin is the layer adjacent to the surface and k = kmax is the layer adjacent to the top of the domain (TOA for this model). Layer k spans the interfaces m = k - kmin (bottom) and m = k - kmin + 1 (top), so interface m = 0 is the surface and m = nlev is the TOA.
Per (i,j) column:
Layer temperature is obtained from (rho, rho*theta, qv) through the equation of state, i.e. including the Exner function, so LW emission uses absolute temperature rather than potential temperature.
Integrates per-column heterogeneous surface properties (albedo, emissivity, surface temperature) from optional fields with robust fallback to RadChoice scalar parameters.
| [in] | i,j | Column indices |
| [in] | bx | Computational box (cell-centered, full vertical extent) |
| [in] | dz_uniform | Uniform vertical cell size [m], used when z_phys_cc is unavailable. Passed in rather than taken from a Geometry because Geometry::CellSize() is host-only and this runs on device. |
| [in] | state_arr | Array proxy to state data (read-only) |
| [in] | rad_choice | Column-kernel parameters (TwoStreamParams, built from RadChoice) |
| [in] | cloudy | If true and tau_profile_type == CloudLayer, apply the cloud-layer optical depth enhancement (and cloud scattering properties). |
| [out] | qheating_arr | Component 0 receives the SW and component 1 the LW radiative tendency of potential temperature, dtheta/dt = (dT/dt) / pi [K/s], at every level k in [kmin, kmax]. This is the convention the RhoTheta source term (ERF_MakeSources.cpp) and the RRTMGP path use. |
| [out] | max_heating_rate | Maximum |Q_sw|+|Q_lw| of the stored theta tendencies in this column |
| [out] | sw_surface_flux | SW absorbed by the surface, (1 - alb_dir) F_dir + (1 - alb_dif) F_dif [W/m^2] |
| [out] | sw_up_toa | Upwelling (reflected) SW at the top of the atmosphere [W/m^2] |
| [out] | lw_net_surface | Net LW (up - down) at the surface [W/m^2] |
| [out] | lw_up_toa | Upwelling LW at the top of the atmosphere (outgoing longwave) [W/m^2] |
| [out] | sw_down_toa | Incident SW at the top of the atmosphere, S0 cos(zenith) or zero at night [W/m^2] |
| [in] | z_phys_nd | Optional nodal physical heights (layer interfaces on a nonuniform grid) |
| [in] | has_hetero_alb_sw | true if hetero_alb_sw is available |
| [in] | hetero_alb_sw | Optional per-column SW surface albedo field |
| [in] | has_hetero_emiss_lw | true if hetero_emiss_lw is available |
| [in] | hetero_emiss_lw | Optional per-column LW surface emissivity field |
| [in] | has_lsm_t_sfc | true if the LSM absolute-temperature field is available |
| [in] | lsm_t_sfc | Optional LSM absolute surface-temperature field [K] |
| [in] | has_seb_t_sfc | true if the prognostic SEB absolute-temperature field is available |
| [in] | seb_t_sfc | Optional prognostic SEB absolute surface-temperature field [K] |
| [in] | has_surface_layer | true if the SurfaceLayer potential-temperature field is available |
| [in] | surface_layer_theta | Optional SurfaceLayer potential-temperature field [K] |
| [in] | has_latlon | true if per-column latitude and longitude fields are available |
| [in] | lat_arr | Optional per-column latitude [degrees] (dynamic sun) |
| [in] | lon_arr | Optional per-column longitude [degrees, east positive] (dynamic sun) |
| [out] | rad_flux_out | Optional 4-component flux output in RRTMGP's level layout: at index k the lower interface of layer k, and at kmax + 1 the top-of-atmosphere interface (the array must extend one cell above the column); component 0 is the upward SW, 1 the downward SW (direct plus diffuse), 2 the upward LW and 3 the downward LW [W/m^2] |
Referenced by TwoStreamRadiation::advance().

