ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
RadChoice Struct Reference

Container holding radiation-related choices and parameters. More...

#include <ERF_RadStruct.H>

Collaboration diagram for RadChoice:

Public Member Functions

void init_params (bool two_stream_selected, std::string pp_prefix)
 
bool uses_two_stream_radiation () const noexcept
 Check if two-stream radiation is active. More...
 

Static Public Member Functions

static void clamp_low (const char *key, amrex::Real &value, amrex::Real lo)
 Read radiation options from the input parameter database. More...
 
static void clamp_high (const char *key, amrex::Real &value, amrex::Real hi)
 
static void reset_nonpositive (const char *key, amrex::Real &value, amrex::Real fallback)
 

Public Attributes

bool enabled = false
 True when erf.radiation_model = TwoStream. Set by init_params from the model SolverChoice read; the erf.radiation.* sub-options are read only then. More...
 
bool sw_enabled = true
 Enable shortwave (solar) radiation computation. Only used by the two-stream model. More...
 
bool lw_enabled = true
 Enable longwave (thermal) radiation computation. Only used by the two-stream model. More...
 
amrex::Real tau_per_layer = 0.05
 Shortwave optical depth per layer (constant for all layers). Used in Beer-Lambert direct-beam formula. Only used by the two-stream model. More...
 
amrex::Real tau_lw_per_layer = 1.0
 Longwave optical depth per layer (constant for all layers). Used in gray-gas LW two-stream solver. Only used by the two-stream model. More...
 
TauModel tau_model = TauModel::PerLayer
 Optical depth model: "per_layer" (default, fixed tau per layer) or "mass" (from the layer mass path in both bands; see TauModel). More...
 
amrex::Real sw_kabs_dry = 4.0e-6
 Mass model, SW: dry-air gray absorption coefficient [m^2/kg]. More...
 
amrex::Real sw_kscat_dry = 3.0e-6
 Mass model, SW: dry-air (Rayleigh) scattering coefficient [m^2/kg], omega = 1, g = 0. More...
 
amrex::Real sw_kabs_vapor = 4.0e-3
 Mass model, SW: water-vapor gray absorption coefficient [m^2/kg]. More...
 
amrex::Real sw_kext_cloud = 150.0
 Mass model, SW: cloud-water extinction coefficient m^2/kg. More...
 
amrex::Real sw_cloud_omega = 0.9999
 Mass model, SW: cloud-water single-scattering albedo. More...
 
amrex::Real sw_cloud_g = 0.85
 Mass model, SW: cloud-water asymmetry factor. More...
 
bool lw_mass_absorption_enable = false
 Gray longwave optical depth from the layer mass path instead of the fixed tau_lw_per_layer (also selected by tau_model = mass): tau_lw(k) = rho dz (lw_kabs_dry + lw_kabs_vapor qv + lw_kabs_cloud qc) The cloud term is the Stephens (1978) emissivity, eps = 1 - exp(-a LWP) with a = 0.158 m^2/g, written as an optical depth. The column optical depth is then independent of the vertical resolution. The cloud-band, moisture-coefficient and aerosol additions still apply on top. Default false keeps tau_lw_per_layer. More...
 
amrex::Real lw_kabs_dry = 1.0e-4
 Dry-air gray LW mass absorption coefficient [m^2/kg]. More...
 
amrex::Real lw_kabs_vapor = 0.1
 Water-vapor gray LW mass absorption coefficient [m^2/kg]. More...
 
amrex::Real lw_kabs_cloud = 158.0
 Cloud-water LW mass absorption coefficient m^2/kg. More...
 
int verbosity = 0
 Debug verbosity level (0=off, 1+=debug output). Gated debug prints only emit when this is >= 1. More...
 
std::string diag_file = "radiation_diag.dat"
 Output file path for radiation diagnostics CSV. Paths are relative to the simulation working directory. More...
 
bool diag_enable = false
 Master switch for radiation diagnostics emission. When false, no diagnostics output (stdout/tagged/regtest/csv). Default false: a run that did not ask for the diagnostics should not write a CSV row and a stdout block on every step. The per-stream switches below stay on by default, so setting this one input to true turns the whole set on. More...
 
bool diag_stdout_enable = true
 Enable human-readable stdout diagnostics block. Controls tagged [RAD][...] debug line emission (when verbosity >= 1). Default true. More...
 
bool diag_tagged_enable = true
 Enable tagged [RAD][...] debug lines. Controls emission of bracketed-tag debug output. Default true. More...
 
bool diag_regtest_line_enable = true
 Enable RADIATION_DIAG: line emission. Controls regtest-parsing diagnostics line. Default true. More...
 
bool diag_csv_enable = true
 Enable CSV file append behavior. When false, no file writes; other enabled streams may still print. Default true. More...
 
std::string diag_callsite_mode = "both"
 Call-site filtering mode: "both" (pre+post rows), "pre_only", or "post_only". More...
 
amrex::Real diag_dedup_tol = 1.0e-12
 Tolerance for time equality in duplicate guard [s]. Times within this tolerance are considered equal. Default 1e-12. More...
 
TauProfileType tau_profile_type = TauProfileType::Constant
 Optical depth profile type: "constant" (default, the thickness-independent tau) or "cloud_layer" (adds height-varying cloud optical depth between cloud_base_height_m and cloud_top_height_m). More...
 
amrex::Real cloud_base_height_m = 500.0
 Cloud layer base height [m]. Only used when tau_profile_type == CloudLayer. More...
 
amrex::Real cloud_top_height_m = 1000.0
 Cloud layer top height [m]. Only used when tau_profile_type == CloudLayer. Must be >= cloud_base_height_m. More...
 
amrex::Real cloud_tau_per_layer = 0.5
 Additional optical depth per layer contributed by the cloud, added on top of the clear-sky tau_per_layer/tau_lw_per_layer background within [cloud_base_height_m, cloud_top_height_m]. Only used when tau_profile_type == CloudLayer. More...
 
amrex::Real cloud_fraction = 0.0
 Cloud fraction in [0, 1] used to blend clear-sky and cloudy-column fluxes: F = (1 - cloud_fraction) * F_clear + cloud_fraction * F_cloudy. Default 0.0 (fully clear sky), which reduces exactly to the clear-sky column regardless of tau_profile_type. More...
 
amrex::Real single_scattering_albedo = 0.0
 Clear-sky (background gas) single-scattering albedo in [0, 1] for the SW diffuse (scattering) two-stream calculation. Default 0.0 means the clear-sky column is purely absorbing, and the diffuse SW contribution from the clear-sky column is exactly zero — reducing exactly to the direct-beam-only result. Only used by the two-stream model and sw_enabled == true. More...
 
amrex::Real asymmetry_factor = 0.0
 Clear-sky (background gas) scattering asymmetry factor in [-1, 1] (0 = isotropic scattering, close to 1 = strongly forward-scattering). Only meaningful when single_scattering_albedo

0. Default 0.0.

More...
 
amrex::Real cloud_single_scattering_albedo = 0.0
 Cloud single-scattering albedo in [0, 1], used instead of single_scattering_albedo for levels where the cloud-layer optical depth enhancement applies (i.e., within [cloud_base_height_m, cloud_top_height_m] on the "cloudy" column evaluation). Default 0.0 leaves the cloud band non-scattering for SW_Cloud_Layer unless explicitly configured otherwise. Typical liquid water cloud values are close to 1 (e.g., 0.9999). Only used when tau_profile_type == CloudLayer. More...
 
amrex::Real cloud_asymmetry_factor = 0.0
 Cloud scattering asymmetry factor in [-1, 1], used instead of asymmetry_factor for levels where the cloud-layer optical depth enhancement applies. Default 0.0. Typical liquid water cloud droplet values are around 0.85 (strongly forward-scattering). Only meaningful when cloud_single_scattering_albedo > 0. More...
 
amrex::Real surface_albedo_sw = 0.3
 Shortwave surface albedo fallback [0, 1] for per-column heterogeneous-surface-property resolution. Used when per-column LSM/radiation interface albedo field is unavailable or invalid. Default 0.3 represents typical land/water reflectivity. Only used when hetero surface fields not present or disabled. More...
 
amrex::Real surface_albedo_sw_diffuse = -1.0
 Shortwave surface albedo for diffuse light [0,1]. A negative value (default) uses surface_albedo_sw for both direct and diffuse light. More...
 
amrex::Real surface_emissivity_lw = 0.99
 Longwave surface emissivity fallback [0, 1] for per-column heterogeneous-surface-property resolution. Used when per-column LSM/radiation interface emissivity field is unavailable or invalid. Default 0.99 represents typical land/water/ice emissivity (nearly blackbody). Only used when hetero surface fields not present or disabled. More...
 
bool seb_enable = false
 Master switch for simplified SEB infrastructure. When false (default), no SEB MultiFabs are allocated and behavior is unchanged. More...
 
bool seb_use_radiation_fluxes = false
 Take the SEB's net surface shortwave and longwave fluxes from the two-stream sweep itself (per column, absorbed fluxes positive) wherever the LSM does not expose them. When false (default) those fluxes are the LSM fields or, without an LSM, the seb_sw_flux_default and seb_lw_flux_default constants. Sensible, latent and ground heat fluxes are unaffected. More...
 
amrex::Real seb_sw_flux_default = 0.0
 Fallback SEB surface net shortwave flux [W/m^2]. More...
 
amrex::Real seb_lw_flux_default = 0.0
 Fallback SEB surface net longwave flux [W/m^2]. More...
 
SEBTurbulentFluxSource seb_turbulent_flux_source = SEBTurbulentFluxSource::SurfaceLayer
 Source of the SEB's sensible and latent heat fluxes when no land-surface model supplies them: "surface_layer" (default) or "defaults". See SEBTurbulentFluxSource. More...
 
bool seb_surface_layer_uses_skin = false
 Two-way coupling with the zlo surface layer: the surface layer takes its land surface temperature from the SEB's prognostic skin temperature T_s (converted to potential temperature), so its sensible heat flux responds to T_s. Requires seb_prognostic_enable and seb_turbulent_flux_source = surface_layer. Default false: the surface layer keeps its own temperature. More...
 
bool seb_surface_layer_uses_moisture = false
 Two-way coupling of moisture as well: the surface layer takes its land surface mixing ratio from the balance's surface water, so its moisture flux follows the soil and dries as the balance's q_s does. Without seb_soil_type it is beta * q_sat(T_s, p_s) + (1 - beta) * q_air with beta the soil-water factor clamp((q_s - seb_soil_moisture_wilt) / (seb_soil_moisture_fc - seb_soil_moisture_wilt), 0, 1). With seb_soil_type, the bare soil evaporates from its pore air (Noah-MP's relative humidity exp(psi g / (R_v T_s)) times q_sat) through Noah-MP's bare-soil resistance, and with seb_vegetation_type the canopy transpires through its own, each in series with the aerodynamic one (erf_surface_moisture::two_source_surface_mixing_ratio). q_s is then the volumetric water content [m^3/m^3] of the top seb_moisture_layer_depth_m of soil. Requires seb_surface_layer_uses_skin. Default false: the surface layer keeps its own surface moisture (erf.most.surf_moist). More...
 
amrex::Real seb_soil_moisture_wilt = 0.066
 Wilting point [m^3/m^3]: at or below it the soil-water factor is 0, so the vegetation does not transpire and, without seb_soil_type, the surface does not evaporate (with one, the bare soil's nearly dry pore air keeps it near zero) (seb_surface_layer_uses_moisture; giving it otherwise stops at start-up). Default 0.066, Noah-MP's loam (WLTSMC, STAS soil type 6). More...
 
amrex::Real seb_soil_moisture_fc = 0.329
 Field capacity [m^3/m^3]: at or above it the soil-water factor is 1, so without seb_soil_type the surface evaporates at the potential rate (seb_surface_layer_uses_moisture; giving it otherwise stops at start-up). Default 0.329, Noah-MP's loam (REFSMC, STAS soil type 6). More...
 
int seb_soil_type = 0
 Noah-MP soil category (STAS, 1-19, not 14 (water), as in NoahmpTable.TBL; see ERF_NoahMPSoilTable.H). The balance takes its wilting point (WLTSMC) and field capacity (REFSMC) – giving either seb_soil_moisture_wilt or seb_soil_moisture_fc as well is an error –, the surface heat capacity of the soil unless seb_surface_heat_capacity is given, with seb_surface_layer_uses_moisture the bare-soil resistance (vegetation or not), and with seb_surface_layer_uses_skin the surface layer's land roughness unless erf.most.z0 is given. 0 (the default): none of these. More...
 
int seb_vegetation_type = 0
 Noah-MP land-use category (modified IGBP MODIS, 1-20 except the unvegetated 15, 16 and 17, as in NoahmpTable.TBL; see ERF_NoahMPVegetationTable.H) of the vegetated fraction. With it, the surface's moisture availability comes from a canopy resistance (Jarvis, Noah-MP's parameters RS, RGL, HS, TOPT, RSMAX) for the vegetated fraction and a bare-soil resistance (Noah-MP's Sakaguchi-Zeng form, on seb_soil_type) for the rest, each in series with the aerodynamic one. Needs seb_surface_layer_uses_moisture and seb_soil_type. 0 (the default): bare soil, the soil's resistance alone (f_veg = 0). More...
 
amrex::Real seb_vegetation_fraction = 1.0
 Vegetated fraction of the surface [0, 1] (seb_vegetation_type; giving it otherwise stops at start-up). Default 1. More...
 
amrex::Real seb_leaf_area_index = -1.0
 Leaf area index [m^2/m^2] of the vegetated fraction (seb_vegetation_type; giving it otherwise stops at start-up). Default: the land-use category's monthly values interpolated to the run's start date and time (start_datetime), as Noah-MP does with its table LAI (noahmp_day_of_year: day 0 at 00:00 on 1 January), shifted half a year when erf.rad_cons_lat < 0 (one latitude for the domain, where Noah-MP uses each column's); fixed for the run. More...
 
amrex::Real seb_land_roughness = -1.0
 Land roughness length [m] the coupled surface layer takes when erf.most.z0 is not given (derived, not an input): with seb_surface_layer_uses_skin and seb_soil_type, f_veg Z0MVT + (1 - f_veg) Z0SOIL from Noah-MP's tables (f_veg = 0 without seb_vegetation_type); -1 otherwise. ERF::InitData_post hands it to the zlo surface layer as it builds it (SurfaceLayer::set_default_roughness). More...
 
amrex::Real seb_hfx_default = 0.0
 Fallback SEB sensible heat flux [W/m^2]. More...
 
amrex::Real seb_lh_default = 0.0
 Fallback SEB latent heat flux [W/m^2]. More...
 
amrex::Real seb_grdflx_default = 0.0
 Fallback SEB ground heat flux [W/m^2]. The force-restore restoring term already represents the flux into the soil, so a nonzero value with seb_prognostic_enable counts that flux twice. More...
 
amrex::Real seb_q_sfc_default = 0.0
 Fallback SEB surface moisture, and the initial value of the prognostic one. With seb_prognostic_enable q_s follows prognostic_dqs_dt, a volumetric water content [m^3/m^3] of the top seb_moisture_layer_depth_m of soil; with a land model that has one, the balance shows the land model's 2 m mixing ratio [kg/kg] instead. More...
 
amrex::Real seb_t_deep_default = 300.0
 Fallback SEB deep soil temperature [K]. More...
 
amrex::Real seb_q_deep_default = 0.0
 Deep soil moisture the prognostic q_s restores to, in q_s's units (see seb_q_sfc_default). More...
 
bool seb_diagnostic_enable = false
 Enable diagnostic SEB residual computation and reporting. When true, computes and reports SEB residual = (SW_net + LW_net) - H - LE - G. When false (default), no residual computation or new diagnostic output. Requires seb_enable=true to be meaningful; if false but seb_enable=true, auto-enables internally. Note: this is diagnostic-only; it makes no prognostic T_s or flux update. Set seb_prognostic_enable for that. More...
 
bool seb_prognostic_enable = false
 Enable prognostic SEB surface temperature and moisture evolution. When true, integrates SEB residual forward in time to evolve T_s and q_s using force-restore formulation. When false (default), no prognostic update occurs. Requires seb_enable=true and seb_diagnostic_enable=true; auto-enables internally if needed. Only active when Noah-MP is NOT driving LSM fields at that level. More...
 
amrex::Real seb_surface_heat_capacity = 2.0e4
 Effective surface heat capacity [J/(m^2*K)]. Used in force-restore prognostic T_s equation: dT_s/dt = SEB_residual / C_s - (2*pi/tau)*(T_s - T_deep). Default 2.0e4 J/(m^2*K) represents a thin surface-active layer. With seb_soil_type it is derived from Noah-MP's soil instead (seb_force_restore_heat_capacity of the soil's heat capacity and conductivity at seb_q_sfc_default, over seb_restore_timescale_s) unless it is given explicitly. Only used when seb_prognostic_enable=true. Must be > 0: init_params() stops otherwise. More...
 
amrex::Real seb_restore_timescale_s = 86400.0
 Force-restore timescale for surface temperature [s]. Relaxation time constant toward T_deep in prognostic T_s equation. Default 86400.0 s (1 day) provides weak damping on diurnal timescales. Only used when seb_prognostic_enable=true. Must be > 0: init_params() stops otherwise. More...
 
amrex::Real seb_moisture_layer_depth_m = 0.1
 Effective surface moisture layer depth [m]. Used in force-restore prognostic q_s equation: dq_s/dt = -(LE/(L_v*rho_w*d_s)) - (1/tau_q)*(q_s - q_deep). Default 0.1 m represents a thin surface-active moisture layer. Only used when seb_prognostic_enable=true. Must be > 0: init_params() stops otherwise. More...
 
amrex::Real seb_moisture_restore_timescale_s = 86400.0
 Force-restore timescale for surface moisture [s]. Relaxation time constant toward q_deep in prognostic q_s equation. Default 86400.0 s (1 day) provides weak damping on diurnal timescales. Only used when seb_prognostic_enable=true. Must be > 0: init_params() stops otherwise. More...
 
amrex::Real seb_prognostic_t_min_k = 200.0
 Minimum clamping bound for prognostic surface temperature [K]. After each Euler update, T_s is clamped to [seb_prognostic_t_min_k, seb_prognostic_t_max_k] to prevent instability if dt is large relative to C_s/tau. Default 200.0 K (far below realistic surface temperatures). Only used when seb_prognostic_enable=true. More...
 
amrex::Real seb_prognostic_t_max_k = 340.0
 Maximum clamping bound for prognostic surface temperature [K]. After each Euler update, T_s is clamped to [seb_prognostic_t_min_k, seb_prognostic_t_max_k]. Default 340.0 K (above typical surface temperatures, but prevents unrealistic excursions). Only used when seb_prognostic_enable=true. More...
 
amrex::Real seb_prognostic_q_min = 0.0
 Minimum clamping bound for prognostic surface moisture [kg/kg]. After each Euler update, q_s is clamped to [seb_prognostic_q_min, seb_prognostic_q_max]. Default 0.0 kg/kg prevents negative moisture. Only used when seb_prognostic_enable=true. More...
 
amrex::Real seb_prognostic_q_max = 1.0
 Maximum clamping bound for prognostic surface moisture [kg/kg]. After each Euler update, q_s is clamped to [seb_prognostic_q_min, seb_prognostic_q_max]. Default 1.0 kg/kg ensures physically meaningful moisture. Only used when seb_prognostic_enable=true. More...
 
bool tau_lw_dynamic_enable = false
 Enable dynamic longwave optical depth diagnosis from moisture/clouds. When true, LW optical depth is computed per-level from qv and qc. When false (default), uses the static tau_lw_per_layer. Only used by the two-stream model and lw_enabled == true. More...
 
bool tau_sw_dynamic_enable = false
 
amrex::Real tau_sw_coeff_qv = 0.0
 Shortwave optical depth coefficient for water vapor [dimensionless]. Dynamic SW tau = tau_sw_coeff_qv * qv + tau_sw_coeff_qc * qc + tau_per_layer. Default 0.0 means tau is purely from static tau_per_layer (no dynamic component). Only used when tau_sw_dynamic_enable == true. More...
 
amrex::Real tau_sw_coeff_qc = 0.0
 Shortwave optical depth coefficient for cloud liquid water [dimensionless]. Default 0.0. When both coefficients are 0, dynamic path still invoked but yields tau_per_layer unchanged. Only used when tau_sw_dynamic_enable == true. More...
 
amrex::Real tau_lw_coeff_qv = 0.0
 Longwave optical depth coefficient for water vapor [dimensionless]. Dynamic LW tau = tau_lw_coeff_qv * qv + tau_lw_coeff_qc * qc + tau_lw_per_layer. Default 0.0 means tau is purely from static tau_lw_per_layer (no dynamic component). Only used when tau_lw_dynamic_enable == true. More...
 
amrex::Real tau_lw_coeff_qc = 0.0
 Longwave optical depth coefficient for cloud liquid water [dimensionless]. Default 0.0. When both coefficients are 0, dynamic path still invoked but yields tau_lw_per_layer unchanged. Only used when tau_lw_dynamic_enable == true. More...
 
bool cloud_fraction_prog_enable = false
 Enable prognostic cloud fraction diagnosis from RH/qc. When true, cloud fraction is computed per-level from relative humidity and cloud water. When false (default), uses the static cloud_fraction. Only used by the two-stream model. More...
 
amrex::Real cloud_fraction_rh_min = 0.0
 Minimum relative humidity threshold for cloud fraction diagnosis [0, 1]. Cloud fraction ramps from 0 at rh < cloud_fraction_rh_min to 1 at rh >= cloud_fraction_rh_max. Default 0.0 means cloud fraction depends primarily on qc content. Only used when cloud_fraction_prog_enable == true. More...
 
amrex::Real cloud_fraction_rh_max = 1.0
 Maximum relative humidity threshold for cloud fraction diagnosis [0, 1]. Must be >= cloud_fraction_rh_min. Cloud fraction saturates to 1 at this RH. Default 1.0 means cloud fraction increases linearly from rh_min to 1.0 RH. Only used when cloud_fraction_prog_enable == true. More...
 
amrex::Real cloud_fraction_qc_scale = 1.0e-3
 Cloud water [kg/kg] at which the liquid-water term alone gives a cloud fraction of 1: cf += min(1, qc / cloud_fraction_qc_scale). Default 1.0e-3 kg/kg, so a typical stratus cloud water saturates the term. Only used when cloud_fraction_prog_enable == true. More...
 
bool aerosol_enable = false
 Enable prescribed bulk aerosol/turbidity optical depth. When true, aerosol optical depth is added on top of existing tau_base + cloud + dynamic-moisture contributions. When false (default), there is no aerosol contribution. Only used by the two-stream model and sw_enabled == true. More...
 
AerosolProfileType aerosol_profile_type = AerosolProfileType::Constant
 Aerosol optical depth profile type: Constant, Exponential, or Table. More...
 
amrex::Real aerosol_tau_per_layer = 0.0
 Constant aerosol optical depth per layer [dimensionless]. Used for AerosolProfileType::Constant profile. Default 0.0 (no aerosol contribution). Only used when aerosol_enable == true and aerosol_profile_type == Constant. More...
 
amrex::Real aerosol_scale_height_m = 2000.0
 Scale height for exponential aerosol profile [m]. Controls decay rate: tau_aerosol(k) = aerosol_tau_surface * exp(-z(k) / scale_height). Default 2000.0 m (typical scale height for tropospheric aerosols). Only used when aerosol_enable == true and aerosol_profile_type == Exponential. More...
 
amrex::Real aerosol_tau_surface = 0.0
 Total-column aerosol optical depth at surface [dimensionless]. Used for AerosolProfileType::Exponential profile as the surface boundary condition. Default 0.0 (no aerosol contribution). Only used when aerosol_enable == true and aerosol_profile_type == Exponential. More...
 
Inputs shared with the RRTMGP interface

The two-stream model reads the sun, site and surface-temperature inputs under the same keys, with the same meaning, as the RRTMGP interface (Source/Radiation/RRTMGP/ERF_Radiation.H), so a deck switches between the two models by changing erf.radiation_model alone.

amrex::Real fixed_solar_zenith_angle = -9999.0
 erf.fixed_solar_zenith_angle: the COSINE of the solar zenith angle (mu0), as RRTMGP takes it, applied to every column when > 0. Otherwise (default) the sun follows the calendar: start_datetime sets the date and time, the position is evaluated at rad_cons_lat/lon or at the per-column latitude and longitude when the grid carries them. More...
 
amrex::Real fixed_total_solar_irradiance = -9999.0
 erf.fixed_total_solar_irradiance: top-of-atmosphere irradiance [W/m^2] when >= 0. Otherwise (default) 1360.9 W/m^2 scaled by the Earth-Sun distance factor of the date, as RRTMGP does. More...
 
amrex::Real rad_t_sfc = -1.0
 erf.rad_t_sfc: surface temperature [K] used as the longwave boundary condition wherever no land-surface model, surface layer or prognostic surface energy balance supplies one; also the initial value of the prognostic surface temperature. Required, as for RRTMGP. More...
 
amrex::Real rad_cons_lat = 39.809860
 erf.rad_cons_lat / erf.rad_cons_lon: site latitude and longitude [degrees] when the grid has no lat/lon fields (RRTMGP defaults). More...
 
amrex::Real rad_cons_lon = -98.555183
 
int rad_orbital_year = -9999
 erf.rad_orbital_year and the orbital overrides: negative means the year of the timestamp and the Berger (1978) values for that year. More...
 
amrex::Real rad_orbital_eccentricity = -9999.0
 
amrex::Real rad_orbital_obliquity = -9999.0
 
amrex::Real rad_orbital_mvelp = -9999.0
 

Detailed Description

Container holding radiation-related choices and parameters.

Manages the runtime selection and configuration of radiation solvers.

The two-stream solver builds up from a clear-sky, no-scattering column of uniform optical depth. On top of that it offers height-varying optical depth (a cloud layer) with cloud-fraction masking, which blends clear-sky and cloudy-column fluxes, and a diffuse shortwave component from a two-stream scattering approximation parameterized by single-scattering albedo and asymmetry factor, with independent clear-sky and cloud values. Every addition is off by default, so the defaults reproduce the plain clear-sky column.

Member Function Documentation

◆ clamp_high()

static void RadChoice::clamp_high ( const char *  key,
amrex::Real &  value,
amrex::Real  hi 
)
inlinestatic
838  {
839  if (value > hi) {
840  if (amrex::ParallelDescriptor::IOProcessor()) {
841  amrex::Print() << "WARNING: erf.radiation." << key << " = " << value
842  << " is above its maximum " << hi << "; using " << hi << "\n";
843  }
844  value = hi;
845  }
846  }

Referenced by init_params().

Here is the caller graph for this function:

◆ clamp_low()

static void RadChoice::clamp_low ( const char *  key,
amrex::Real &  value,
amrex::Real  lo 
)
inlinestatic

Read radiation options from the input parameter database.

Parameters
[in]two_stream_selectedWhether the two-stream solver is the selected model.
[in]pp_prefixParmParse prefix for the ERF input namespace (e.g., "erf").

Queries:

  • erf.radiation_model = TwoStream (read by SolverChoice) selects the model
  • erf.radiation.sw_enabled (bool, optional, default true)
  • erf.radiation.lw_enabled (bool, optional, default true)
  • erf.radiation.tau_per_layer (real, optional)
  • erf.radiation.tau_lw_per_layer (real, optional)
  • erf.fixed_solar_zenith_angle, erf.fixed_total_solar_irradiance, erf.rad_t_sfc (required), erf.rad_cons_lat, erf.rad_cons_lon, erf.rad_orbital_year, erf.rad_orbital_eccentricity, erf.rad_orbital_obliquity, erf.rad_orbital_mvelp: the RRTMGP interface's keys, with its meanings (see the members above)
  • erf.radiation.tau_model (string "per_layer"|"mass", optional, default "per_layer")
  • erf.radiation.sw_kabs_dry, sw_kscat_dry, sw_kabs_vapor, sw_kext_cloud (real, optional, mass model)
  • erf.radiation.sw_cloud_omega, sw_cloud_g (real, optional, mass model)
  • erf.radiation.lw_mass_absorption_enable (bool, optional, default false)
  • erf.radiation.lw_kabs_dry (real, optional, default 1.0e-4 m^2/kg)
  • erf.radiation.lw_kabs_vapor (real, optional, default 0.1 m^2/kg)
  • erf.radiation.lw_kabs_cloud (real, optional, default 158.0 m^2/kg)
  • erf.radiation.surface_albedo_sw_diffuse (real, optional, default -1 = same as direct)
  • erf.radiation.v (int, optional, debug verbosity)
  • erf.radiation.diag_file (string, optional)
  • erf.radiation.tau_profile_type (string "constant"|"cloud_layer", optional)
  • erf.radiation.cloud_base_height_m (real, optional)
  • erf.radiation.cloud_top_height_m (real, optional)
  • erf.radiation.cloud_tau_per_layer (real, optional)
  • erf.radiation.cloud_fraction (real, optional)
  • erf.radiation.single_scattering_albedo (real, optional)
  • erf.radiation.asymmetry_factor (real, optional)
  • erf.radiation.cloud_single_scattering_albedo (real, optional)
  • erf.radiation.cloud_asymmetry_factor (real, optional)
  • erf.radiation.diag_enable (bool, optional, default false)
  • erf.radiation.diag_stdout_enable (bool, optional, default true)
  • erf.radiation.diag_tagged_enable (bool, optional, default true)
  • erf.radiation.diag_regtest_line_enable (bool, optional, default true)
  • erf.radiation.diag_csv_enable (bool, optional, default true)
  • erf.radiation.diag_callsite_mode (string, optional, default "both")
  • erf.radiation.diag_dedup_tol (real, optional, default 1e-12)
  • erf.radiation.tau_sw_dynamic_enable (bool, optional, default false)
  • erf.radiation.tau_lw_dynamic_enable (bool, optional, default false)
  • erf.radiation.tau_sw_coeff_qv (real, optional, default 0.0)
  • erf.radiation.tau_sw_coeff_qc (real, optional, default 0.0)
  • erf.radiation.tau_lw_coeff_qv (real, optional, default 0.0)
  • erf.radiation.tau_lw_coeff_qc (real, optional, default 0.0)
  • erf.radiation.cloud_fraction_prog_enable (bool, optional, default false)
  • erf.radiation.cloud_fraction_rh_min (real, optional, default 0.0)
  • erf.radiation.cloud_fraction_rh_max (real, optional, default 1.0)
  • erf.radiation.cloud_fraction_qc_scale (real, optional, default 1.0e-3)
  • erf.radiation.aerosol_enable (bool, optional, default false)
  • erf.radiation.aerosol_profile_type (string "constant"|"exponential"|"table", optional, default "constant")
  • erf.radiation.aerosol_tau_per_layer (real, optional, default 0.0)
  • erf.radiation.aerosol_scale_height_m (real, optional, default 2000.0)
  • erf.radiation.aerosol_tau_surface (real, optional, default 0.0)
  • erf.radiation.seb_enable (bool, optional, default false)
  • erf.radiation.seb_sw_flux_default (real, optional, default 0.0)
  • erf.radiation.seb_lw_flux_default (real, optional, default 0.0)
  • erf.radiation.seb_turbulent_flux_source (string "surface_layer"|"defaults", optional, default "surface_layer")
  • erf.radiation.seb_surface_layer_uses_skin (bool, optional, default false)
  • erf.radiation.seb_surface_layer_uses_moisture (bool, optional, default false)
  • erf.radiation.seb_soil_moisture_wilt (real, optional, default 0.066, 0 <= wilt < fc)
  • erf.radiation.seb_soil_moisture_fc (real, optional, default 0.329, wilt < fc <= 1)
  • erf.radiation.seb_soil_type (int, optional, default 0 = unset; 1-19, a Noah-MP STAS soil category)
  • erf.radiation.seb_vegetation_type (int, optional, default 0 = unset; 1-20 except 15-17 (no vegetation), a Noah-MP MODIS land-use category)
  • erf.radiation.seb_vegetation_fraction (real, optional, default 1, in [0, 1])
  • erf.radiation.seb_leaf_area_index (real, optional, default from the table at the start date, >= 0)
  • erf.radiation.seb_hfx_default (real, optional, default 0.0)
  • erf.radiation.seb_lh_default (real, optional, default 0.0)
  • erf.radiation.seb_grdflx_default (real, optional, default 0.0)
  • erf.radiation.seb_q_sfc_default (real, optional, default 0.0)
  • erf.radiation.seb_t_deep_default (real, optional, default 300.0)
  • erf.radiation.seb_q_deep_default (real, optional, default 0.0)
  • erf.radiation.seb_diagnostic_enable (bool, optional, default false)
  • erf.radiation.seb_prognostic_enable (bool, optional, default false)
  • erf.radiation.seb_surface_heat_capacity (real, optional, default 2.0e4, > 0, stops at start-up otherwise)
  • erf.radiation.seb_restore_timescale_s (real, optional, default 86400.0, > 0, stops at start-up otherwise)
  • erf.radiation.seb_moisture_layer_depth_m (real, optional, default 0.1, > 0, stops at start-up otherwise)
  • erf.radiation.seb_moisture_restore_timescale_s (real, optional, default 86400.0, > 0, stops at start-up otherwise)
  • erf.radiation.seb_prognostic_t_min_k (real, optional, default 200.0)
  • erf.radiation.seb_prognostic_t_max_k (real, optional, default 340.0)
  • erf.radiation.seb_prognostic_q_min (real, optional, default 0.0, clamped to [0, 1])
  • erf.radiation.seb_prognostic_q_max (real, optional, default 1.0, clamped to [0, 1])

Sub-option queries are only performed when the two-stream model is selected.

Bring an out-of-range input back into its valid range and say so. Every erf.radiation.* value with a physical range passes through one of these, so a typo in a deck is reported instead of silently corrected.

828  {
829  if (value < lo) {
830  if (amrex::ParallelDescriptor::IOProcessor()) {
831  amrex::Print() << "WARNING: erf.radiation." << key << " = " << value
832  << " is below its minimum " << lo << "; using " << lo << "\n";
833  }
834  value = lo;
835  }
836  }

Referenced by init_params().

Here is the caller graph for this function:

◆ init_params()

void RadChoice::init_params ( bool  two_stream_selected,
std::string  pp_prefix 
)
inline
859  {
860  amrex::ParmParse pp(pp_prefix);
861  enabled = two_stream_selected;
862 
863  // A refined hierarchy is supported: every level runs its own column sweep
864  // and writes its own heating rates. The one requirement is that each
865  // level's grids span that level's domain in z, because the sweep imposes
866  // top-of-atmosphere and surface boundary conditions at the ends of a box.
867  // That is checked where the grids exist, not here: ERF_RefineBox.cpp for
868  // an explicit erf.boxN refinement box, and TwoStreamRadiation::define_level
869  // for every path including tagged refinement and regrid.
870 
871  // Only query sub-options if the two-stream model is selected
872  if (enabled) {
873  pp.query("radiation.sw_enabled", sw_enabled);
874  pp.query("radiation.lw_enabled", lw_enabled);
875  pp.query("radiation.tau_per_layer", tau_per_layer);
876  pp.query("radiation.tau_lw_per_layer", tau_lw_per_layer);
877 
878  // The sun, the site and the surface temperature come from the keys the
879  // RRTMGP interface reads, so the two models share one set of inputs.
880  // ParmParse ignores a key nobody reads, so a deck still carrying one of
881  // the earlier two-stream-only keys would run with silently different
882  // settings: stop and name the replacement instead.
883  static const char* retired_keys[][2] = {
884  {"radiation.solar_zenith",
885  "erf.fixed_solar_zenith_angle, which is the cosine of the angle (60 degrees is 0.5)"},
886  {"radiation.solar_zenith_deg",
887  "erf.fixed_solar_zenith_angle, which is the cosine of the angle (60 degrees is 0.5)"},
888  {"radiation.S0", "erf.fixed_total_solar_irradiance"},
889  {"radiation.earth_sun_distance_enable",
890  "nothing: leave erf.fixed_total_solar_irradiance unset and the irradiance follows the date"},
891  {"radiation.surface_temp_k", "erf.rad_t_sfc"},
892  {"radiation.solar_geometry_dynamic_enable",
893  "nothing: leave erf.fixed_solar_zenith_angle unset and the sun follows start_datetime"},
894  {"radiation.latitude_deg", "erf.rad_cons_lat"},
895  {"radiation.longitude_deg", "erf.rad_cons_lon"},
896  {"radiation.day_of_year", "start_datetime"},
897  {"radiation.time_zone_offset_hours",
898  "nothing: start_datetime is UTC and the longitude sets the local solar time"},
899  };
900  for (const auto& entry : retired_keys) {
901  if (pp.contains(entry[0])) {
902  amrex::Abort(std::string("erf.") + entry[0] + " is no longer read by the "
903  "two-stream model; use " + entry[1] + ".");
904  }
905  }
906  pp.query("fixed_solar_zenith_angle", fixed_solar_zenith_angle);
907  if (fixed_solar_zenith_angle > 1.0) {
908  amrex::Abort("erf.fixed_solar_zenith_angle = " + std::to_string(fixed_solar_zenith_angle) +
909  " is the cosine of the solar zenith angle (as for RRTMGP) and cannot "
910  "exceed 1; 60 degrees is 0.5.");
911  }
912  pp.query("fixed_total_solar_irradiance", fixed_total_solar_irradiance);
913  if (!pp.query("rad_t_sfc", rad_t_sfc)) {
914  amrex::Abort("erf.radiation_model = TwoStream needs erf.rad_t_sfc, the surface "
915  "temperature [K] used where no land-surface model or surface layer "
916  "supplies one (the same input RRTMGP requires).");
917  }
918  if (!std::isfinite(rad_t_sfc) || rad_t_sfc <= 0.0) {
919  amrex::Abort("erf.rad_t_sfc = " + std::to_string(rad_t_sfc) + " must be a positive temperature [K].");
920  }
921  pp.query("rad_cons_lat", rad_cons_lat);
922  pp.query("rad_cons_lon", rad_cons_lon);
923  if (!std::isfinite(rad_cons_lat) || rad_cons_lat < -90.0 || rad_cons_lat > 90.0) {
924  amrex::Abort("erf.rad_cons_lat = " + std::to_string(rad_cons_lat) + " must lie in [-90, 90] degrees.");
925  }
926  if (!std::isfinite(rad_cons_lon) || rad_cons_lon < -180.0 || rad_cons_lon > 180.0) {
927  amrex::Abort("erf.rad_cons_lon = " + std::to_string(rad_cons_lon) + " must lie in [-180, 180] degrees.");
928  }
929  pp.query("rad_orbital_year", rad_orbital_year);
930  pp.query("rad_orbital_eccentricity", rad_orbital_eccentricity);
931  pp.query("rad_orbital_obliquity", rad_orbital_obliquity);
932  pp.query("rad_orbital_mvelp", rad_orbital_mvelp);
933  if (pp.contains("rad_freq_in_steps") && amrex::ParallelDescriptor::IOProcessor()) {
934  amrex::Print() << "WARNING: erf.rad_freq_in_steps is not read by the two-stream model, "
935  "which runs every step.\n";
936  }
937  std::string tau_model_str = "per_layer";
938  pp.query("radiation.tau_model", tau_model_str);
939  if (tau_model_str == "per_layer") {
940  tau_model = TauModel::PerLayer;
941  } else if (tau_model_str == "mass") {
942  tau_model = TauModel::Mass;
943  } else {
944  // The two models give very different column optical depths, so say so
945  // rather than let a misspelling quietly pick the default.
946  tau_model = TauModel::PerLayer;
947  if (amrex::ParallelDescriptor::IOProcessor()) {
948  amrex::Print() << "WARNING: unknown erf.radiation.tau_model '"
949  << tau_model_str << "'; valid values are per_layer "
950  "and mass. Using per_layer.\n";
951  }
952  }
953  pp.query("radiation.sw_kabs_dry", sw_kabs_dry);
954  pp.query("radiation.sw_kscat_dry", sw_kscat_dry);
955  pp.query("radiation.sw_kabs_vapor", sw_kabs_vapor);
956  pp.query("radiation.sw_kext_cloud", sw_kext_cloud);
957  pp.query("radiation.sw_cloud_omega", sw_cloud_omega);
958  pp.query("radiation.sw_cloud_g", sw_cloud_g);
959  clamp_low("sw_kabs_dry", sw_kabs_dry, 0.0);
960  clamp_low("sw_kscat_dry", sw_kscat_dry, 0.0);
961  clamp_low("sw_kabs_vapor", sw_kabs_vapor, 0.0);
962  clamp_low("sw_kext_cloud", sw_kext_cloud, 0.0);
963  clamp_low("sw_cloud_omega", sw_cloud_omega, 0.0);
964  clamp_high("sw_cloud_omega", sw_cloud_omega, 1.0);
965  clamp_low("sw_cloud_g", sw_cloud_g, -1.0);
966  clamp_high("sw_cloud_g", sw_cloud_g, 1.0);
967  pp.query("radiation.lw_mass_absorption_enable", lw_mass_absorption_enable);
968  pp.query("radiation.lw_kabs_dry", lw_kabs_dry);
969  pp.query("radiation.lw_kabs_vapor", lw_kabs_vapor);
970  pp.query("radiation.lw_kabs_cloud", lw_kabs_cloud);
971  clamp_low("lw_kabs_dry", lw_kabs_dry, 0.0);
972  clamp_low("lw_kabs_vapor", lw_kabs_vapor, 0.0);
973  clamp_low("lw_kabs_cloud", lw_kabs_cloud, 0.0);
974  pp.query("radiation.v", verbosity);
975  pp.query("radiation.diag_file", diag_file);
976 
977  // Cloud optical properties (all optional; the defaults leave the
978  // column clear-sky)
979  std::string tau_profile_type_str = "constant";
980  pp.query("radiation.tau_profile_type", tau_profile_type_str);
981  if (tau_profile_type_str == "constant") {
982  tau_profile_type = TauProfileType::Constant;
983  } else if (tau_profile_type_str == "cloud_layer") {
984  tau_profile_type = TauProfileType::CloudLayer;
985  } else {
986  // Falling back to constant drops a requested cloud layer, so say so.
987  tau_profile_type = TauProfileType::Constant;
988  if (amrex::ParallelDescriptor::IOProcessor()) {
989  amrex::Print() << "WARNING: unknown erf.radiation.tau_profile_type '"
990  << tau_profile_type_str << "'; valid values are "
991  "constant and cloud_layer. Using constant, so no "
992  "cloud layer is applied.\n";
993  }
994  }
995  pp.query("radiation.cloud_base_height_m", cloud_base_height_m);
996  pp.query("radiation.cloud_top_height_m", cloud_top_height_m);
997  pp.query("radiation.cloud_tau_per_layer", cloud_tau_per_layer);
998  pp.query("radiation.cloud_fraction", cloud_fraction);
999 
1000  // Parameter validation (R5/R5'): clip cloud_fraction to [0, 1]
1001  clamp_low("cloud_fraction", cloud_fraction, 0.0);
1002  clamp_high("cloud_fraction", cloud_fraction, 1.0);
1003  clamp_low("cloud_tau_per_layer", cloud_tau_per_layer, 0.0);
1006  }
1007 
1008  // Scattering parameters (all optional; the defaults leave the
1009  // shortwave direct-beam only)
1010  pp.query("radiation.single_scattering_albedo", single_scattering_albedo);
1011  pp.query("radiation.asymmetry_factor", asymmetry_factor);
1012  pp.query("radiation.cloud_single_scattering_albedo", cloud_single_scattering_albedo);
1013  pp.query("radiation.cloud_asymmetry_factor", cloud_asymmetry_factor);
1014 
1015  // Parameter validation (R5/R5'): clip albedos to [0, 1] and
1016  // asymmetry factors to [-1, 1]
1017  clamp_low("single_scattering_albedo", single_scattering_albedo, 0.0);
1018  clamp_high("single_scattering_albedo", single_scattering_albedo, 1.0);
1019  clamp_low("asymmetry_factor", asymmetry_factor, -1.0);
1020  clamp_high("asymmetry_factor", asymmetry_factor, 1.0);
1021  clamp_low("cloud_single_scattering_albedo", cloud_single_scattering_albedo, 0.0);
1022  clamp_high("cloud_single_scattering_albedo", cloud_single_scattering_albedo, 1.0);
1023  clamp_low("cloud_asymmetry_factor", cloud_asymmetry_factor, -1.0);
1024  clamp_high("cloud_asymmetry_factor", cloud_asymmetry_factor, 1.0);
1025 
1026  // Runtime diagnostics controls (all optional; every channel is on
1027  // by default)
1028  pp.query("radiation.diag_enable", diag_enable);
1029  pp.query("radiation.diag_stdout_enable", diag_stdout_enable);
1030  pp.query("radiation.diag_tagged_enable", diag_tagged_enable);
1031  pp.query("radiation.diag_regtest_line_enable", diag_regtest_line_enable);
1032  pp.query("radiation.diag_csv_enable", diag_csv_enable);
1033  pp.query("radiation.diag_callsite_mode", diag_callsite_mode);
1034  pp.query("radiation.diag_dedup_tol", diag_dedup_tol);
1035 
1036  // Validate the call-site mode
1037  if (diag_callsite_mode != "both" &&
1038  diag_callsite_mode != "pre_only" &&
1039  diag_callsite_mode != "post_only") {
1040  if (amrex::ParallelDescriptor::IOProcessor()) {
1041  amrex::Print() << "WARNING: unknown erf.radiation.diag_callsite_mode '"
1042  << diag_callsite_mode << "'; valid values are both, "
1043  "pre_only and post_only. Using both.\n";
1044  }
1045  diag_callsite_mode = "both";
1046  }
1047  // Ensure dedup tolerance is non-negative
1048  clamp_low("diag_dedup_tol", diag_dedup_tol, 0.0);
1049 
1050  // Surface heterogeneity fallback parameters (all optional; only used
1051  // when hetero
1052  // LSM/radiation interface fields are absent or invalid)
1053  pp.query("radiation.surface_albedo_sw", surface_albedo_sw);
1054  pp.query("radiation.surface_emissivity_lw", surface_emissivity_lw);
1055  pp.query("radiation.surface_albedo_sw_diffuse", surface_albedo_sw_diffuse);
1056  clamp_high("surface_albedo_sw_diffuse", surface_albedo_sw_diffuse, 1.0);
1057 
1058  // Clamp albedo/emissivity to [0, 1]
1059  clamp_low("surface_albedo_sw", surface_albedo_sw, 0.0);
1060  clamp_high("surface_albedo_sw", surface_albedo_sw, 1.0);
1061  clamp_low("surface_emissivity_lw", surface_emissivity_lw, 0.0);
1062  clamp_high("surface_emissivity_lw", surface_emissivity_lw, 1.0);
1063 
1064  // Dynamic optical depth diagnosis from moisture/clouds
1065  // (all optional; disabled by default)
1066  pp.query("radiation.tau_sw_dynamic_enable", tau_sw_dynamic_enable);
1067  pp.query("radiation.tau_lw_dynamic_enable", tau_lw_dynamic_enable);
1068  pp.query("radiation.tau_sw_coeff_qv", tau_sw_coeff_qv);
1069  pp.query("radiation.tau_sw_coeff_qc", tau_sw_coeff_qc);
1070  pp.query("radiation.tau_lw_coeff_qv", tau_lw_coeff_qv);
1071  pp.query("radiation.tau_lw_coeff_qc", tau_lw_coeff_qc);
1072 
1073  // Clamp the dynamic tau coefficients
1074  // to nonnegative (negative would give unphysical behavior)
1075  clamp_low("tau_sw_coeff_qv", tau_sw_coeff_qv, 0.0);
1076  clamp_low("tau_sw_coeff_qc", tau_sw_coeff_qc, 0.0);
1077  clamp_low("tau_lw_coeff_qv", tau_lw_coeff_qv, 0.0);
1078  clamp_low("tau_lw_coeff_qc", tau_lw_coeff_qc, 0.0);
1079 
1080  // Prognostic cloud fraction diagnosis from RH/qc
1081  // (all optional; disabled by default)
1082  pp.query("radiation.cloud_fraction_prog_enable", cloud_fraction_prog_enable);
1083  pp.query("radiation.cloud_fraction_rh_min", cloud_fraction_rh_min);
1084  pp.query("radiation.cloud_fraction_rh_max", cloud_fraction_rh_max);
1085  pp.query("radiation.cloud_fraction_qc_scale", cloud_fraction_qc_scale);
1086 
1087  // Clamp the cloud fraction parameters
1088  // to physically reasonable ranges
1089  clamp_low("cloud_fraction_rh_min", cloud_fraction_rh_min, 0.0);
1090  clamp_high("cloud_fraction_rh_min", cloud_fraction_rh_min, 1.0);
1091  clamp_low("cloud_fraction_rh_max", cloud_fraction_rh_max, 0.0);
1092  clamp_high("cloud_fraction_rh_max", cloud_fraction_rh_max, 1.0);
1095  }
1096  clamp_low("cloud_fraction_qc_scale", cloud_fraction_qc_scale, 0.0);
1097 
1098  // Prescribed bulk aerosol/turbidity optical depth
1099  // (all optional; disabled by default)
1100  pp.query("radiation.aerosol_enable", aerosol_enable);
1101 
1102  // Parse aerosol profile type as string
1103  std::string aerosol_profile_type_str = "constant";
1104  pp.query("radiation.aerosol_profile_type", aerosol_profile_type_str);
1105  if (aerosol_profile_type_str == "constant") {
1106  aerosol_profile_type = AerosolProfileType::Constant;
1107  } else if (aerosol_profile_type_str == "exponential") {
1108  aerosol_profile_type = AerosolProfileType::Exponential;
1109  } else if (aerosol_profile_type_str == "table") {
1110  // The table lookup is not implemented and contributes no optical
1111  // depth. Keep the selection so the run is not silently given a
1112  // different profile, and say what it means.
1113  aerosol_profile_type = AerosolProfileType::Table;
1114  if (amrex::ParallelDescriptor::IOProcessor()) {
1115  amrex::Print() << "WARNING: erf.radiation.aerosol_profile_type = table is "
1116  "not implemented and contributes no aerosol optical "
1117  "depth. Use constant or exponential.\n";
1118  }
1119  } else {
1120  // Falling through to constant would hide a misspelling.
1121  aerosol_profile_type = AerosolProfileType::Constant;
1122  if (amrex::ParallelDescriptor::IOProcessor()) {
1123  amrex::Print() << "WARNING: unknown erf.radiation.aerosol_profile_type '"
1124  << aerosol_profile_type_str << "'; valid values are "
1125  "constant and exponential. Using constant.\n";
1126  }
1127  }
1128 
1129  pp.query("radiation.aerosol_tau_per_layer", aerosol_tau_per_layer);
1130  pp.query("radiation.aerosol_scale_height_m", aerosol_scale_height_m);
1131  pp.query("radiation.aerosol_tau_surface", aerosol_tau_surface);
1132 
1133  // Clamp the aerosol parameters
1134  // to physically reasonable ranges
1135  clamp_low("aerosol_tau_per_layer", aerosol_tau_per_layer, 0.0);
1136  clamp_low("aerosol_tau_surface", aerosol_tau_surface, 0.0);
1137  reset_nonpositive("aerosol_scale_height_m", aerosol_scale_height_m, 2000.0);
1138 
1139  // Simplified SEB infrastructure fallback parameters
1140  pp.query("radiation.seb_enable", seb_enable);
1141  pp.query("radiation.seb_use_radiation_fluxes", seb_use_radiation_fluxes);
1142  pp.query("radiation.seb_sw_flux_default", seb_sw_flux_default);
1143  pp.query("radiation.seb_lw_flux_default", seb_lw_flux_default);
1144  // Through the AMREX_ENUM, case-insensitive and ignoring underscores, so
1145  // surface_layer, SurfaceLayer and surfacelayer all select SurfaceLayer. The
1146  // parser throws on any other value; turn that into an abort naming the input.
1147  try {
1148  pp.query_enum_sloppy("radiation.seb_turbulent_flux_source",
1150  } catch (...) {
1151  std::string value;
1152  pp.query("radiation.seb_turbulent_flux_source", value);
1153  amrex::Abort("erf.radiation.seb_turbulent_flux_source must be surface_layer "
1154  "or defaults, not '" + value + "'");
1155  }
1156  pp.query("radiation.seb_surface_layer_uses_skin", seb_surface_layer_uses_skin);
1157  pp.query("radiation.seb_surface_layer_uses_moisture", seb_surface_layer_uses_moisture);
1158  pp.query("radiation.seb_soil_moisture_wilt", seb_soil_moisture_wilt);
1159  pp.query("radiation.seb_soil_moisture_fc", seb_soil_moisture_fc);
1160  pp.query("radiation.seb_soil_type", seb_soil_type);
1161  if (seb_soil_type != 0) {
1162  if (pp.contains("radiation.seb_soil_moisture_wilt") ||
1163  pp.contains("radiation.seb_soil_moisture_fc")) {
1164  amrex::Abort("erf.radiation.seb_soil_type sets the wilting point and field "
1165  "capacity from Noah-MP's soil table; do not also give "
1166  "seb_soil_moisture_wilt or seb_soil_moisture_fc");
1167  }
1169  if (soil == nullptr || !(soil->smc_ref > soil->smc_wilt)) {
1170  amrex::Abort("erf.radiation.seb_soil_type = " + std::to_string(seb_soil_type) +
1171  " is not a Noah-MP soil category with a field capacity above its "
1172  "wilting point (1-19, not 14, water; see ERF_NoahMPSoilTable.H)");
1173  }
1175  seb_soil_moisture_fc = soil->smc_ref;
1176  }
1177  pp.query("radiation.seb_vegetation_type", seb_vegetation_type);
1178  pp.query("radiation.seb_vegetation_fraction", seb_vegetation_fraction);
1179  pp.query("radiation.seb_leaf_area_index", seb_leaf_area_index);
1180  if (seb_vegetation_type != 0) {
1182  if (veg == nullptr) {
1183  amrex::Abort("erf.radiation.seb_vegetation_type = " + std::to_string(seb_vegetation_type) +
1184  " is not a Noah-MP MODIS land-use category (1-20; see "
1185  "ERF_NoahMPVegetationTable.H)");
1186  }
1187  // Snow and ice (15), barren (16) and water (17) have no vegetation in the table
1188  // (Z0MVT = 0, LAI 0 all year): Noah-MP treats such a surface as bare ground.
1189  if (!(veg->z0 > 0.0)) {
1190  amrex::Abort("erf.radiation.seb_vegetation_type = " + std::to_string(seb_vegetation_type) +
1191  " has no vegetation in Noah-MP's table (Z0MVT = 0, LAI 0 all year). "
1192  "For bare land leave seb_vegetation_type at 0: the soil's resistance "
1193  "and roughness (Z0SOIL) then apply.");
1194  }
1196  amrex::Abort("erf.radiation.seb_vegetation_type needs "
1197  "erf.radiation.seb_surface_layer_uses_moisture = true and "
1198  "erf.radiation.seb_soil_type (the bare-soil resistance uses the "
1199  "soil's porosity and Clapp-Hornberger b)");
1200  }
1201  if (!(std::isfinite(seb_vegetation_fraction) && seb_vegetation_fraction >= 0.0 &&
1202  seb_vegetation_fraction <= 1.0)) {
1203  amrex::Abort("erf.radiation.seb_vegetation_fraction must be in [0, 1]; got " +
1204  std::to_string(seb_vegetation_fraction));
1205  }
1206  if (pp.contains("radiation.seb_leaf_area_index")) {
1207  if (!(std::isfinite(seb_leaf_area_index) && seb_leaf_area_index >= 0.0)) {
1208  amrex::Abort("erf.radiation.seb_leaf_area_index must be >= 0; got " +
1209  std::to_string(seb_leaf_area_index));
1210  }
1211  } else {
1212  // The table's monthly LAI at the start date and time, as Noah-MP interpolates it
1213  // (its day of the year counts from 0 at 00:00 on 1 January).
1214  std::string start;
1215  amrex::ParmParse pp_top;
1216  amrex::Real day = 0.0, days_in_year = 0.0;
1217  if (!pp_top.query("start_datetime", start) ||
1218  !noahmp_day_of_year(start, day, days_in_year)) {
1219  amrex::Abort("erf.radiation.seb_vegetation_type: give "
1220  "erf.radiation.seb_leaf_area_index, or a valid start_datetime "
1221  "(YYYY-MM-DD HH:MM:SS) so that it can be taken from the table");
1222  }
1223  seb_leaf_area_index = noahmp_leaf_area_index(*veg, day, days_in_year,
1224  rad_cons_lat < 0.0);
1225  if (amrex::ParallelDescriptor::IOProcessor()) {
1226  amrex::Print() << "NOTE: erf.radiation.seb_leaf_area_index = "
1227  << seb_leaf_area_index << ", Noah-MP's table value for land-use "
1228  "category " << seb_vegetation_type << " at " << start
1229  << ", fixed for the run.\n";
1230  }
1231  }
1232  }
1233  pp.query("radiation.seb_hfx_default", seb_hfx_default);
1234  pp.query("radiation.seb_lh_default", seb_lh_default);
1235  pp.query("radiation.seb_grdflx_default", seb_grdflx_default);
1236  pp.query("radiation.seb_q_sfc_default", seb_q_sfc_default);
1237  pp.query("radiation.seb_t_deep_default", seb_t_deep_default);
1238  pp.query("radiation.seb_q_deep_default", seb_q_deep_default);
1239 
1240  // SEB diagnostic mode
1241  pp.query("radiation.seb_diagnostic_enable", seb_diagnostic_enable);
1242 
1243  // Auto-enable seb_enable if seb_diagnostic_enable is requested but seb_enable is false
1245  seb_enable = true; // Internal auto-enable for safety/simplicity
1246  }
1247 
1248  // SEB prognostic mode parameters
1249  pp.query("radiation.seb_prognostic_enable", seb_prognostic_enable);
1250  pp.query("radiation.seb_surface_heat_capacity", seb_surface_heat_capacity);
1251  pp.query("radiation.seb_restore_timescale_s", seb_restore_timescale_s);
1252  pp.query("radiation.seb_moisture_layer_depth_m", seb_moisture_layer_depth_m);
1253  pp.query("radiation.seb_moisture_restore_timescale_s", seb_moisture_restore_timescale_s);
1254  pp.query("radiation.seb_prognostic_t_min_k", seb_prognostic_t_min_k);
1255  pp.query("radiation.seb_prognostic_t_max_k", seb_prognostic_t_max_k);
1256  pp.query("radiation.seb_prognostic_q_min", seb_prognostic_q_min);
1257  pp.query("radiation.seb_prognostic_q_max", seb_prognostic_q_max);
1258 
1259  // The prognostic update needs the SEB fields and the residual, so
1260  // requesting it turns on the infrastructure it depends on. Report that,
1261  // since it changes settings the user did not set.
1263  if (amrex::ParallelDescriptor::IOProcessor()) {
1264  amrex::Print() << "NOTE: erf.radiation.seb_prognostic_enable = true "
1265  "also enables seb_enable and "
1266  "seb_diagnostic_enable, which it depends on.\n";
1267  }
1268  seb_enable = true;
1269  seb_diagnostic_enable = true;
1270  }
1271 
1272  if (!std::isfinite(seb_sw_flux_default)) seb_sw_flux_default = 0.0;
1273  if (!std::isfinite(seb_lw_flux_default)) seb_lw_flux_default = 0.0;
1274  if (!std::isfinite(seb_hfx_default)) seb_hfx_default = 0.0;
1275  if (!std::isfinite(seb_lh_default)) seb_lh_default = 0.0;
1276  if (!std::isfinite(seb_grdflx_default)) seb_grdflx_default = 0.0;
1277  if (!std::isfinite(seb_q_sfc_default)) seb_q_sfc_default = 0.0;
1278  reset_nonpositive("seb_t_deep_default", seb_t_deep_default, 300.0);
1279  if (!std::isfinite(seb_q_deep_default)) seb_q_deep_default = 0.0;
1280 
1281  seb_sw_flux_default = amrex::max(amrex::Real(-2000.0), amrex::min(amrex::Real(2000.0), seb_sw_flux_default));
1282  seb_lw_flux_default = amrex::max(amrex::Real(-2000.0), amrex::min(amrex::Real(2000.0), seb_lw_flux_default));
1283  seb_hfx_default = amrex::max(amrex::Real(-2000.0), amrex::min(amrex::Real(2000.0), seb_hfx_default));
1284  seb_lh_default = amrex::max(amrex::Real(-2000.0), amrex::min(amrex::Real(2000.0), seb_lh_default));
1285  seb_grdflx_default = amrex::max(amrex::Real(-2000.0), amrex::min(amrex::Real(2000.0), seb_grdflx_default));
1286  seb_q_sfc_default = amrex::max(amrex::Real(0.0), amrex::min(amrex::Real(1.0), seb_q_sfc_default));
1287  seb_q_deep_default = amrex::max(amrex::Real(0.0), amrex::min(amrex::Real(1.0), seb_q_deep_default));
1288 
1289  // Two-way coupling needs a skin that evolves, and a balance that removes the
1290  // flux the surface layer computes from it.
1292  if (!seb_prognostic_enable) {
1293  amrex::Abort("erf.radiation.seb_surface_layer_uses_skin = true needs "
1294  "erf.radiation.seb_prognostic_enable = true: without it the "
1295  "skin temperature does not evolve");
1296  }
1297  if (seb_turbulent_flux_source != SEBTurbulentFluxSource::SurfaceLayer) {
1298  amrex::Abort("erf.radiation.seb_surface_layer_uses_skin = true needs "
1299  "erf.radiation.seb_turbulent_flux_source = surface_layer: the "
1300  "balance must remove the heat flux the surface layer computes "
1301  "from the skin");
1302  }
1303  }
1304 
1305  // Moisture coupling: the surface mixing ratio is q_sat at the skin temperature, so
1306  // it needs the skin coupling; and beta needs a wilting point below field capacity.
1307  // The wilting point and field capacity: checked whenever they are given or used.
1308  if (seb_surface_layer_uses_moisture || pp.contains("radiation.seb_soil_moisture_wilt") ||
1309  pp.contains("radiation.seb_soil_moisture_fc")) {
1310  if (!(std::isfinite(seb_soil_moisture_wilt) && std::isfinite(seb_soil_moisture_fc) &&
1312  seb_soil_moisture_fc <= 1.0)) {
1313  amrex::Abort("erf.radiation.seb_soil_moisture_wilt and seb_soil_moisture_fc must "
1314  "satisfy 0 <= wilt < fc <= 1 (volumetric water contents); got wilt = " +
1315  std::to_string(seb_soil_moisture_wilt) + ", fc = " +
1316  std::to_string(seb_soil_moisture_fc));
1317  }
1318  }
1319  // Inputs that only the moisture coupling or a vegetation type use: say so rather than
1320  // ignore them.
1322  (pp.contains("radiation.seb_soil_moisture_wilt") ||
1323  pp.contains("radiation.seb_soil_moisture_fc"))) {
1324  amrex::Abort("erf.radiation.seb_soil_moisture_wilt and seb_soil_moisture_fc are used "
1325  "only with erf.radiation.seb_surface_layer_uses_moisture = true");
1326  }
1327  if (seb_vegetation_type == 0 &&
1328  (pp.contains("radiation.seb_vegetation_fraction") ||
1329  pp.contains("radiation.seb_leaf_area_index"))) {
1330  amrex::Abort("erf.radiation.seb_vegetation_fraction and seb_leaf_area_index are used "
1331  "only with erf.radiation.seb_vegetation_type");
1332  }
1333 
1336  amrex::Abort("erf.radiation.seb_surface_layer_uses_moisture = true needs "
1337  "erf.radiation.seb_surface_layer_uses_skin = true: the surface "
1338  "mixing ratio is the saturation value at the balance's skin "
1339  "temperature");
1340  }
1342  amrex::ParallelDescriptor::IOProcessor()) {
1343  amrex::Print() << "NOTE: erf.radiation.seb_surface_layer_uses_moisture: the soil "
1344  "starts at or below the wilting point (seb_q_sfc_default = "
1345  << seb_q_sfc_default << ", seb_soil_moisture_wilt = "
1346  << seb_soil_moisture_wilt << "), so its soil-water factor is zero: "
1347  << (seb_soil_type != 0
1348  ? "no transpiration, and the bare soil's pore air is nearly "
1349  "dry (Noah-MP's relative humidity exp(psi g / (R_v T))), so it "
1350  "hardly evaporates and may take up vapour."
1351  : "no evaporation at all.")
1352  << " Set seb_q_sfc_default (and seb_q_deep_default, which q_s "
1353  "restores to) to the soil's water content if that is not meant.\n";
1354  }
1355  // q_s restores toward q_deep, which defaults to 0: a forgotten q_deep dries the soil
1356  // over seb_moisture_restore_timescale_s.
1358  amrex::ParallelDescriptor::IOProcessor()) {
1359  amrex::Print() << "NOTE: erf.radiation.seb_surface_layer_uses_moisture: "
1360  "seb_q_deep_default = " << seb_q_deep_default
1361  << " is below the wilting point (" << seb_soil_moisture_wilt
1362  << "), and q_s restores toward it over seb_moisture_restore_timescale_s"
1363  " (" << seb_moisture_restore_timescale_s << " s), drying the soil."
1364  " Set seb_q_deep_default to the deep soil's water content if that "
1365  "is not meant.\n";
1366  }
1367  }
1368 
1369  // The restoring term -(2 pi / tau)(T_s - T_deep) of the force-restore update
1370  // is the ground heat flux, so a ground flux in the balance as well removes
1371  // that heat twice.
1372  if (seb_prognostic_enable && seb_grdflx_default != 0.0 &&
1373  amrex::ParallelDescriptor::IOProcessor()) {
1374  amrex::Print() << "WARNING: erf.radiation.seb_grdflx_default = " << seb_grdflx_default
1375  << " with seb_prognostic_enable: the force-restore term already "
1376  "carries the ground heat flux, so this counts it twice.\n";
1377  }
1378 
1379 
1380  // Validate the prognostic parameters: each must be positive and finite when given
1381  // (the defaults are), so a typo stops here rather than running on another value.
1382  auto require_positive = [] (const char* name, amrex::Real value) {
1383  if (!(std::isfinite(value) && value > 0.0)) {
1384  amrex::Abort(std::string("erf.radiation.") + name + " must be > 0; got " +
1385  std::to_string(value));
1386  }
1387  };
1388  require_positive("seb_surface_heat_capacity", seb_surface_heat_capacity);
1389  require_positive("seb_restore_timescale_s", seb_restore_timescale_s);
1390  require_positive("seb_moisture_layer_depth_m", seb_moisture_layer_depth_m);
1391  require_positive("seb_moisture_restore_timescale_s", seb_moisture_restore_timescale_s);
1392 
1393  // With a Noah-MP soil, the surface heat capacity of that soil at its initial water
1394  // content: the layer the restore period's temperature wave reaches.
1395  // The coupled surface layer's land roughness, from the same tables.
1397  const NoahMPVegetationParams* veg = (seb_vegetation_type != 0)
1399  const amrex::Real f_veg = veg ? seb_vegetation_fraction : amrex::Real(0.0);
1400  seb_land_roughness = f_veg * (veg ? veg->z0 : amrex::Real(0.0)) +
1401  (amrex::Real(1.0) - f_veg) * noahmp_soil_roughness;
1402  // At least min(Z0MVT, Z0SOIL) > 0: the categories with Z0MVT = 0 stop above.
1404  "erf.radiation.seb_*: the land roughness from Noah-MP's tables is not positive");
1405  }
1406 
1407  // A value given explicitly stands.
1408  if (seb_prognostic_enable && seb_soil_type != 0) {
1410  const amrex::Real theta = amrex::min(seb_q_sfc_default, soil->smc_max);
1412  const amrex::Real lambda = seb_soil_thermal_conductivity(theta, soil->smc_max, soil->quartz);
1414  const bool given = pp.contains("radiation.seb_surface_heat_capacity");
1415  if (!given) { seb_surface_heat_capacity = derived; }
1416  if (amrex::ParallelDescriptor::IOProcessor()) {
1417  amrex::Print() << "NOTE: erf.radiation.seb_surface_heat_capacity = "
1418  << seb_surface_heat_capacity << " J/m^2/K"
1419  << (given ? " as given; Noah-MP soil category " :
1420  ", from Noah-MP soil category ")
1421  << seb_soil_type << " at a water content of " << theta
1422  << " (heat capacity " << c << " J/m^3/K, conductivity " << lambda
1423  << " W/m/K) over " << seb_restore_timescale_s << " s"
1424  << (given ? " gives " + std::to_string(derived) : std::string())
1425  << ".\n";
1426  }
1427  }
1428 
1429  // Clamp temperature bounds
1430  if (!std::isfinite(seb_prognostic_t_min_k)) seb_prognostic_t_min_k = 200.0;
1431  if (!std::isfinite(seb_prognostic_t_max_k)) seb_prognostic_t_max_k = 340.0;
1436  }
1437 
1438  // Clamp moisture bounds
1439  if (!std::isfinite(seb_prognostic_q_min)) seb_prognostic_q_min = 0.0;
1440  if (!std::isfinite(seb_prognostic_q_max)) seb_prognostic_q_max = 1.0;
1441  seb_prognostic_q_min = amrex::max(amrex::Real(0.0), amrex::min(amrex::Real(1.0), seb_prognostic_q_min));
1442  seb_prognostic_q_max = amrex::max(amrex::Real(0.0), amrex::min(amrex::Real(1.0), seb_prognostic_q_max));
1447  }
1448 
1449  }
1450 
1451 }
ParmParse pp("prob")
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
constexpr amrex::Real noahmp_soil_roughness
Definition: ERF_NoahMPSoilTable.H:42
const NoahMPSoilParams * noahmp_soil_params(int category) noexcept
The parameters of STAS soil category category (1-19), as Noah-MP reads them.
Definition: ERF_NoahMPSoilTable.H:49
constexpr amrex::Real noahmp_soil_heat_capacity
Definition: ERF_NoahMPSoilTable.H:35
amrex::Real noahmp_leaf_area_index(const NoahMPVegetationParams &params, amrex::Real day, amrex::Real days_in_year, bool southern) noexcept
Leaf area index of params on day of year day, interpolated between the monthly values as Noah-MP does...
Definition: ERF_NoahMPVegetationTable.H:98
const NoahMPVegetationParams * noahmp_vegetation_params(int category) noexcept
The parameters of MODIS land-use category category (1-20), as Noah-MP reads them.
Definition: ERF_NoahMPVegetationTable.H:41
bool noahmp_day_of_year(const std::string &datetime, amrex::Real &day, amrex::Real &days_in_year)
The day of the year, as Noah-MP counts it, of a date "YYYY-MM-DD[ HH:MM[:SS]]" (ERF's start_datetime)...
Definition: ERF_NoahMPVegetationTable.H:130
std::string name
Definition: ERF_Plotfile2DCatalog.cpp:105
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real seb_soil_thermal_conductivity(amrex::Real theta, amrex::Real theta_sat, amrex::Real quartz)
Thermal conductivity of unfrozen soil [W/m/K], Noah-MP's Johansen form (SoilThermalPropertyMod): soli...
Definition: ERF_SimplifiedSEB.H:352
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real seb_force_restore_heat_capacity(amrex::Real lambda, amrex::Real c, amrex::Real tau)
Surface heat capacity [J/m^2/K] of the force-restore balance for a soil of volumetric heat capacity c...
Definition: ERF_SimplifiedSEB.H:374
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real seb_soil_heat_capacity(amrex::Real theta, amrex::Real theta_sat, amrex::Real c_soil)
Volumetric heat capacity of unfrozen soil [J/m^3/K], as Noah-MP forms it (SoilThermalPropertyMod): wa...
Definition: ERF_SimplifiedSEB.H:338
@ theta
Definition: ERF_Kessler.H:26
@ tmp
Definition: ERF_AdvanceWSM6.cpp:116
Definition: ERF_Derive.cpp:172
Definition: ERF_NoahMPSoilTable.H:20
amrex::Real smc_ref
REFSMC reference soil moisture, field capacity [m^3/m^3].
Definition: ERF_NoahMPSoilTable.H:24
amrex::Real smc_wilt
WLTSMC wilting point [m^3/m^3].
Definition: ERF_NoahMPSoilTable.H:27
amrex::Real smc_max
MAXSMC saturated soil moisture (porosity) [m^3/m^3].
Definition: ERF_NoahMPSoilTable.H:23
amrex::Real quartz
QTZ quartz fraction [1].
Definition: ERF_NoahMPSoilTable.H:28
Definition: ERF_NoahMPVegetationTable.H:23
amrex::Real z0
Z0MVT momentum roughness length of the vegetation [m].
Definition: ERF_NoahMPVegetationTable.H:29
amrex::Real lw_kabs_dry
Dry-air gray LW mass absorption coefficient [m^2/kg].
Definition: ERF_RadStruct.H:204
bool aerosol_enable
Enable prescribed bulk aerosol/turbidity optical depth. When true, aerosol optical depth is added on ...
Definition: ERF_RadStruct.H:700
TauModel tau_model
Optical depth model: "per_layer" (default, fixed tau per layer) or "mass" (from the layer mass path i...
Definition: ERF_RadStruct.H:171
amrex::Real sw_kabs_vapor
Mass model, SW: water-vapor gray absorption coefficient [m^2/kg].
Definition: ERF_RadStruct.H:180
amrex::Real cloud_top_height_m
Cloud layer top height [m]. Only used when tau_profile_type == CloudLayer. Must be >= cloud_base_heig...
Definition: ERF_RadStruct.H:292
static void reset_nonpositive(const char *key, amrex::Real &value, amrex::Real fallback)
Definition: ERF_RadStruct.H:847
amrex::Real aerosol_tau_surface
Total-column aerosol optical depth at surface [dimensionless]. Used for AerosolProfileType::Exponenti...
Definition: ERF_RadStruct.H:732
int rad_orbital_year
erf.rad_orbital_year and the orbital overrides: negative means the year of the timestamp and the Berg...
Definition: ERF_RadStruct.H:161
amrex::Real fixed_solar_zenith_angle
erf.fixed_solar_zenith_angle: the COSINE of the solar zenith angle (mu0), as RRTMGP takes it,...
Definition: ERF_RadStruct.H:136
bool sw_enabled
Enable shortwave (solar) radiation computation. Only used by the two-stream model.
Definition: ERF_RadStruct.H:98
amrex::Real cloud_asymmetry_factor
Cloud scattering asymmetry factor in [-1, 1], used instead of asymmetry_factor for levels where the c...
Definition: ERF_RadStruct.H:347
int seb_vegetation_type
Noah-MP land-use category (modified IGBP MODIS, 1-20 except the unvegetated 15, 16 and 17,...
Definition: ERF_RadStruct.H:471
std::string diag_file
Output file path for radiation diagnostics CSV. Paths are relative to the simulation working director...
Definition: ERF_RadStruct.H:222
static void clamp_high(const char *key, amrex::Real &value, amrex::Real hi)
Definition: ERF_RadStruct.H:837
amrex::Real tau_lw_per_layer
Longwave optical depth per layer (constant for all layers). Used in gray-gas LW two-stream solver....
Definition: ERF_RadStruct.H:118
amrex::Real surface_albedo_sw
Shortwave surface albedo fallback [0, 1] for per-column heterogeneous-surface-property resolution....
Definition: ERF_RadStruct.H:356
amrex::Real surface_emissivity_lw
Longwave surface emissivity fallback [0, 1] for per-column heterogeneous-surface-property resolution....
Definition: ERF_RadStruct.H:371
amrex::Real rad_orbital_mvelp
Definition: ERF_RadStruct.H:164
amrex::Real seb_grdflx_default
Fallback SEB ground heat flux [W/m^2]. The force-restore restoring term already represents the flux i...
Definition: ERF_RadStruct.H:512
amrex::Real diag_dedup_tol
Tolerance for time equality in duplicate guard [s]. Times within this tolerance are considered equal....
Definition: ERF_RadStruct.H:273
amrex::Real seb_restore_timescale_s
Force-restore timescale for surface temperature [s]. Relaxation time constant toward T_deep in progno...
Definition: ERF_RadStruct.H:569
std::string diag_callsite_mode
Call-site filtering mode: "both" (pre+post rows), "pre_only", or "post_only".
Definition: ERF_RadStruct.H:266
bool diag_regtest_line_enable
Enable RADIATION_DIAG: line emission. Controls regtest-parsing diagnostics line. Default true.
Definition: ERF_RadStruct.H:253
amrex::Real sw_kext_cloud
Mass model, SW: cloud-water extinction coefficient m^2/kg.
Definition: ERF_RadStruct.H:183
amrex::Real tau_sw_coeff_qv
Shortwave optical depth coefficient for water vapor [dimensionless]. Dynamic SW tau = tau_sw_coeff_qv...
Definition: ERF_RadStruct.H:636
amrex::Real fixed_total_solar_irradiance
erf.fixed_total_solar_irradiance: top-of-atmosphere irradiance [W/m^2] when >= 0. Otherwise (default)...
Definition: ERF_RadStruct.H:143
bool tau_lw_dynamic_enable
Enable dynamic longwave optical depth diagnosis from moisture/clouds. When true, LW optical depth is ...
Definition: ERF_RadStruct.H:627
amrex::Real seb_lh_default
Fallback SEB latent heat flux [W/m^2].
Definition: ERF_RadStruct.H:505
amrex::Real seb_moisture_restore_timescale_s
Force-restore timescale for surface moisture [s]. Relaxation time constant toward q_deep in prognosti...
Definition: ERF_RadStruct.H:585
amrex::Real seb_lw_flux_default
Fallback SEB surface net longwave flux [W/m^2].
Definition: ERF_RadStruct.H:397
amrex::Real tau_sw_coeff_qc
Shortwave optical depth coefficient for cloud liquid water [dimensionless]. Default 0....
Definition: ERF_RadStruct.H:644
amrex::Real aerosol_tau_per_layer
Constant aerosol optical depth per layer [dimensionless]. Used for AerosolProfileType::Constant profi...
Definition: ERF_RadStruct.H:716
bool seb_surface_layer_uses_skin
Two-way coupling with the zlo surface layer: the surface layer takes its land surface temperature fro...
Definition: ERF_RadStruct.H:413
amrex::Real seb_q_sfc_default
Fallback SEB surface moisture, and the initial value of the prognostic one. With seb_prognostic_enabl...
Definition: ERF_RadStruct.H:520
amrex::Real rad_orbital_eccentricity
Definition: ERF_RadStruct.H:162
amrex::Real single_scattering_albedo
Clear-sky (background gas) single-scattering albedo in [0, 1] for the SW diffuse (scattering) two-str...
Definition: ERF_RadStruct.H:318
bool diag_csv_enable
Enable CSV file append behavior. When false, no file writes; other enabled streams may still print....
Definition: ERF_RadStruct.H:260
bool tau_sw_dynamic_enable
Definition: ERF_RadStruct.H:628
amrex::Real seb_t_deep_default
Fallback SEB deep soil temperature [K].
Definition: ERF_RadStruct.H:525
AerosolProfileType aerosol_profile_type
Aerosol optical depth profile type: Constant, Exponential, or Table.
Definition: ERF_RadStruct.H:709
amrex::Real seb_prognostic_t_max_k
Maximum clamping bound for prognostic surface temperature [K]. After each Euler update,...
Definition: ERF_RadStruct.H:602
amrex::Real rad_t_sfc
erf.rad_t_sfc: surface temperature [K] used as the longwave boundary condition wherever no land-surfa...
Definition: ERF_RadStruct.H:151
bool seb_prognostic_enable
Enable prognostic SEB surface temperature and moisture evolution. When true, integrates SEB residual ...
Definition: ERF_RadStruct.H:550
bool seb_use_radiation_fluxes
Take the SEB's net surface shortwave and longwave fluxes from the two-stream sweep itself (per column...
Definition: ERF_RadStruct.H:387
amrex::Real seb_prognostic_t_min_k
Minimum clamping bound for prognostic surface temperature [K]. After each Euler update,...
Definition: ERF_RadStruct.H:594
amrex::Real tau_lw_coeff_qc
Longwave optical depth coefficient for cloud liquid water [dimensionless]. Default 0....
Definition: ERF_RadStruct.H:660
amrex::Real rad_orbital_obliquity
Definition: ERF_RadStruct.H:163
amrex::Real cloud_fraction
Cloud fraction in [0, 1] used to blend clear-sky and cloudy-column fluxes: F = (1 - cloud_fraction) *...
Definition: ERF_RadStruct.H:308
amrex::Real cloud_single_scattering_albedo
Cloud single-scattering albedo in [0, 1], used instead of single_scattering_albedo for levels where t...
Definition: ERF_RadStruct.H:338
amrex::Real lw_kabs_cloud
Cloud-water LW mass absorption coefficient m^2/kg.
Definition: ERF_RadStruct.H:210
amrex::Real sw_cloud_omega
Mass model, SW: cloud-water single-scattering albedo.
Definition: ERF_RadStruct.H:186
amrex::Real sw_kscat_dry
Mass model, SW: dry-air (Rayleigh) scattering coefficient [m^2/kg], omega = 1, g = 0.
Definition: ERF_RadStruct.H:177
amrex::Real sw_kabs_dry
Mass model, SW: dry-air gray absorption coefficient [m^2/kg].
Definition: ERF_RadStruct.H:174
amrex::Real seb_soil_moisture_wilt
Wilting point [m^3/m^3]: at or below it the soil-water factor is 0, so the vegetation does not transp...
Definition: ERF_RadStruct.H:439
amrex::Real seb_leaf_area_index
Leaf area index [m^2/m^2] of the vegetated fraction (seb_vegetation_type; giving it otherwise stops a...
Definition: ERF_RadStruct.H:486
amrex::Real asymmetry_factor
Clear-sky (background gas) scattering asymmetry factor in [-1, 1] (0 = isotropic scattering,...
Definition: ERF_RadStruct.H:326
static void clamp_low(const char *key, amrex::Real &value, amrex::Real lo)
Read radiation options from the input parameter database.
Definition: ERF_RadStruct.H:827
bool seb_surface_layer_uses_moisture
Two-way coupling of moisture as well: the surface layer takes its land surface mixing ratio from the ...
Definition: ERF_RadStruct.H:430
amrex::Real cloud_fraction_qc_scale
Cloud water [kg/kg] at which the liquid-water term alone gives a cloud fraction of 1: cf += min(1,...
Definition: ERF_RadStruct.H:692
bool cloud_fraction_prog_enable
Enable prognostic cloud fraction diagnosis from RH/qc. When true, cloud fraction is computed per-leve...
Definition: ERF_RadStruct.H:668
amrex::Real seb_prognostic_q_max
Maximum clamping bound for prognostic surface moisture [kg/kg]. After each Euler update,...
Definition: ERF_RadStruct.H:618
bool lw_enabled
Enable longwave (thermal) radiation computation. Only used by the two-stream model.
Definition: ERF_RadStruct.H:104
int seb_soil_type
Noah-MP soil category (STAS, 1-19, not 14 (water), as in NoahmpTable.TBL; see ERF_NoahMPSoilTable....
Definition: ERF_RadStruct.H:459
amrex::Real seb_soil_moisture_fc
Field capacity [m^3/m^3]: at or above it the soil-water factor is 1, so without seb_soil_type the sur...
Definition: ERF_RadStruct.H:447
amrex::Real surface_albedo_sw_diffuse
Shortwave surface albedo for diffuse light [0,1]. A negative value (default) uses surface_albedo_sw f...
Definition: ERF_RadStruct.H:362
amrex::Real cloud_base_height_m
Cloud layer base height [m]. Only used when tau_profile_type == CloudLayer.
Definition: ERF_RadStruct.H:286
amrex::Real lw_kabs_vapor
Water-vapor gray LW mass absorption coefficient [m^2/kg].
Definition: ERF_RadStruct.H:207
amrex::Real tau_per_layer
Shortwave optical depth per layer (constant for all layers). Used in Beer-Lambert direct-beam formula...
Definition: ERF_RadStruct.H:111
amrex::Real seb_moisture_layer_depth_m
Effective surface moisture layer depth [m]. Used in force-restore prognostic q_s equation: dq_s/dt = ...
Definition: ERF_RadStruct.H:577
amrex::Real seb_vegetation_fraction
Vegetated fraction of the surface [0, 1] (seb_vegetation_type; giving it otherwise stops at start-up)...
Definition: ERF_RadStruct.H:477
SEBTurbulentFluxSource seb_turbulent_flux_source
Source of the SEB's sensible and latent heat fluxes when no land-surface model supplies them: "surfac...
Definition: ERF_RadStruct.H:404
amrex::Real tau_lw_coeff_qv
Longwave optical depth coefficient for water vapor [dimensionless]. Dynamic LW tau = tau_lw_coeff_qv ...
Definition: ERF_RadStruct.H:652
amrex::Real seb_hfx_default
Fallback SEB sensible heat flux [W/m^2].
Definition: ERF_RadStruct.H:500
amrex::Real cloud_fraction_rh_max
Maximum relative humidity threshold for cloud fraction diagnosis [0, 1]. Must be >= cloud_fraction_rh...
Definition: ERF_RadStruct.H:684
amrex::Real sw_cloud_g
Mass model, SW: cloud-water asymmetry factor.
Definition: ERF_RadStruct.H:189
amrex::Real rad_cons_lon
Definition: ERF_RadStruct.H:155
bool lw_mass_absorption_enable
Gray longwave optical depth from the layer mass path instead of the fixed tau_lw_per_layer (also sele...
Definition: ERF_RadStruct.H:201
amrex::Real cloud_tau_per_layer
Additional optical depth per layer contributed by the cloud, added on top of the clear-sky tau_per_la...
Definition: ERF_RadStruct.H:300
amrex::Real aerosol_scale_height_m
Scale height for exponential aerosol profile [m]. Controls decay rate: tau_aerosol(k) = aerosol_tau_s...
Definition: ERF_RadStruct.H:724
amrex::Real seb_land_roughness
Land roughness length [m] the coupled surface layer takes when erf.most.z0 is not given (derived,...
Definition: ERF_RadStruct.H:495
bool diag_tagged_enable
Enable tagged [RAD][...] debug lines. Controls emission of bracketed-tag debug output....
Definition: ERF_RadStruct.H:246
amrex::Real seb_q_deep_default
Deep soil moisture the prognostic q_s restores to, in q_s's units (see seb_q_sfc_default).
Definition: ERF_RadStruct.H:531
amrex::Real rad_cons_lat
erf.rad_cons_lat / erf.rad_cons_lon: site latitude and longitude [degrees] when the grid has no lat/l...
Definition: ERF_RadStruct.H:154
amrex::Real seb_sw_flux_default
Fallback SEB surface net shortwave flux [W/m^2].
Definition: ERF_RadStruct.H:392
bool diag_enable
Master switch for radiation diagnostics emission. When false, no diagnostics output (stdout/tagged/re...
Definition: ERF_RadStruct.H:232
amrex::Real seb_prognostic_q_min
Minimum clamping bound for prognostic surface moisture [kg/kg]. After each Euler update,...
Definition: ERF_RadStruct.H:610
amrex::Real cloud_fraction_rh_min
Minimum relative humidity threshold for cloud fraction diagnosis [0, 1]. Cloud fraction ramps from 0 ...
Definition: ERF_RadStruct.H:676
bool seb_enable
Master switch for simplified SEB infrastructure. When false (default), no SEB MultiFabs are allocated...
Definition: ERF_RadStruct.H:377
bool diag_stdout_enable
Enable human-readable stdout diagnostics block. Controls tagged [RAD][...] debug line emission (when ...
Definition: ERF_RadStruct.H:239
bool enabled
True when erf.radiation_model = TwoStream. Set by init_params from the model SolverChoice read; the e...
Definition: ERF_RadStruct.H:92
int verbosity
Debug verbosity level (0=off, 1+=debug output). Gated debug prints only emit when this is >= 1.
Definition: ERF_RadStruct.H:216
amrex::Real seb_surface_heat_capacity
Effective surface heat capacity [J/(m^2*K)]. Used in force-restore prognostic T_s equation: dT_s/dt =...
Definition: ERF_RadStruct.H:561
TauProfileType tau_profile_type
Optical depth profile type: "constant" (default, the thickness-independent tau) or "cloud_layer" (add...
Definition: ERF_RadStruct.H:280
bool seb_diagnostic_enable
Enable diagnostic SEB residual computation and reporting. When true, computes and reports SEB residua...
Definition: ERF_RadStruct.H:541

Referenced by SolverChoice::init_params().

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

◆ reset_nonpositive()

static void RadChoice::reset_nonpositive ( const char *  key,
amrex::Real &  value,
amrex::Real  fallback 
)
inlinestatic
848  {
849  if (!std::isfinite(value) || value <= 0.0) {
850  if (amrex::ParallelDescriptor::IOProcessor()) {
851  amrex::Print() << "WARNING: erf.radiation." << key << " = " << value
852  << " must be positive; using " << fallback << "\n";
853  }
854  value = fallback;
855  }
856  }

Referenced by init_params().

Here is the caller graph for this function:

◆ uses_two_stream_radiation()

bool RadChoice::uses_two_stream_radiation ( ) const
inlinenoexcept

Check if two-stream radiation is active.

Returns
true when erf.radiation_model = TwoStream.
1459  {
1460  return enabled;
1461  }

Member Data Documentation

◆ aerosol_enable

bool RadChoice::aerosol_enable = false

Enable prescribed bulk aerosol/turbidity optical depth. When true, aerosol optical depth is added on top of existing tau_base + cloud + dynamic-moisture contributions. When false (default), there is no aerosol contribution. Only used by the two-stream model and sw_enabled == true.

Referenced by init_params().

◆ aerosol_profile_type

AerosolProfileType RadChoice::aerosol_profile_type = AerosolProfileType::Constant

Aerosol optical depth profile type: Constant, Exponential, or Table.

  • Constant: uniform aerosol tau per layer (aerosol_tau_per_layer).
  • Exponential: tau decays with height via tau_aerosol(k) = aerosol_tau_surface * exp(-z(k) / aerosol_scale_height_m).
  • Table: per-level tau prescribed via lookup (future extension, currently not supported). Default Constant. Only used when aerosol_enable == true.

Referenced by init_params().

◆ aerosol_scale_height_m

amrex::Real RadChoice::aerosol_scale_height_m = 2000.0

Scale height for exponential aerosol profile [m]. Controls decay rate: tau_aerosol(k) = aerosol_tau_surface * exp(-z(k) / scale_height). Default 2000.0 m (typical scale height for tropospheric aerosols). Only used when aerosol_enable == true and aerosol_profile_type == Exponential.

Referenced by init_params().

◆ aerosol_tau_per_layer

amrex::Real RadChoice::aerosol_tau_per_layer = 0.0

Constant aerosol optical depth per layer [dimensionless]. Used for AerosolProfileType::Constant profile. Default 0.0 (no aerosol contribution). Only used when aerosol_enable == true and aerosol_profile_type == Constant.

Referenced by init_params().

◆ aerosol_tau_surface

amrex::Real RadChoice::aerosol_tau_surface = 0.0

Total-column aerosol optical depth at surface [dimensionless]. Used for AerosolProfileType::Exponential profile as the surface boundary condition. Default 0.0 (no aerosol contribution). Only used when aerosol_enable == true and aerosol_profile_type == Exponential.

Referenced by init_params().

◆ asymmetry_factor

amrex::Real RadChoice::asymmetry_factor = 0.0

Clear-sky (background gas) scattering asymmetry factor in [-1, 1] (0 = isotropic scattering, close to 1 = strongly forward-scattering). Only meaningful when single_scattering_albedo

0. Default 0.0.

Referenced by init_params().

◆ cloud_asymmetry_factor

amrex::Real RadChoice::cloud_asymmetry_factor = 0.0

Cloud scattering asymmetry factor in [-1, 1], used instead of asymmetry_factor for levels where the cloud-layer optical depth enhancement applies. Default 0.0. Typical liquid water cloud droplet values are around 0.85 (strongly forward-scattering). Only meaningful when cloud_single_scattering_albedo > 0.

Referenced by init_params().

◆ cloud_base_height_m

amrex::Real RadChoice::cloud_base_height_m = 500.0

Cloud layer base height [m]. Only used when tau_profile_type == CloudLayer.

Referenced by init_params().

◆ cloud_fraction

amrex::Real RadChoice::cloud_fraction = 0.0

Cloud fraction in [0, 1] used to blend clear-sky and cloudy-column fluxes: F = (1 - cloud_fraction) * F_clear + cloud_fraction * F_cloudy. Default 0.0 (fully clear sky), which reduces exactly to the clear-sky column regardless of tau_profile_type.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ cloud_fraction_prog_enable

bool RadChoice::cloud_fraction_prog_enable = false

Enable prognostic cloud fraction diagnosis from RH/qc. When true, cloud fraction is computed per-level from relative humidity and cloud water. When false (default), uses the static cloud_fraction. Only used by the two-stream model.

Referenced by init_params().

◆ cloud_fraction_qc_scale

amrex::Real RadChoice::cloud_fraction_qc_scale = 1.0e-3

Cloud water [kg/kg] at which the liquid-water term alone gives a cloud fraction of 1: cf += min(1, qc / cloud_fraction_qc_scale). Default 1.0e-3 kg/kg, so a typical stratus cloud water saturates the term. Only used when cloud_fraction_prog_enable == true.

Referenced by init_params().

◆ cloud_fraction_rh_max

amrex::Real RadChoice::cloud_fraction_rh_max = 1.0

Maximum relative humidity threshold for cloud fraction diagnosis [0, 1]. Must be >= cloud_fraction_rh_min. Cloud fraction saturates to 1 at this RH. Default 1.0 means cloud fraction increases linearly from rh_min to 1.0 RH. Only used when cloud_fraction_prog_enable == true.

Referenced by init_params().

◆ cloud_fraction_rh_min

amrex::Real RadChoice::cloud_fraction_rh_min = 0.0

Minimum relative humidity threshold for cloud fraction diagnosis [0, 1]. Cloud fraction ramps from 0 at rh < cloud_fraction_rh_min to 1 at rh >= cloud_fraction_rh_max. Default 0.0 means cloud fraction depends primarily on qc content. Only used when cloud_fraction_prog_enable == true.

Referenced by init_params().

◆ cloud_single_scattering_albedo

amrex::Real RadChoice::cloud_single_scattering_albedo = 0.0

Cloud single-scattering albedo in [0, 1], used instead of single_scattering_albedo for levels where the cloud-layer optical depth enhancement applies (i.e., within [cloud_base_height_m, cloud_top_height_m] on the "cloudy" column evaluation). Default 0.0 leaves the cloud band non-scattering for SW_Cloud_Layer unless explicitly configured otherwise. Typical liquid water cloud values are close to 1 (e.g., 0.9999). Only used when tau_profile_type == CloudLayer.

Referenced by init_params().

◆ cloud_tau_per_layer

amrex::Real RadChoice::cloud_tau_per_layer = 0.5

Additional optical depth per layer contributed by the cloud, added on top of the clear-sky tau_per_layer/tau_lw_per_layer background within [cloud_base_height_m, cloud_top_height_m]. Only used when tau_profile_type == CloudLayer.

Referenced by init_params().

◆ cloud_top_height_m

amrex::Real RadChoice::cloud_top_height_m = 1000.0

Cloud layer top height [m]. Only used when tau_profile_type == CloudLayer. Must be >= cloud_base_height_m.

Referenced by init_params().

◆ diag_callsite_mode

std::string RadChoice::diag_callsite_mode = "both"

Call-site filtering mode: "both" (pre+post rows), "pre_only", or "post_only".

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ diag_csv_enable

bool RadChoice::diag_csv_enable = true

Enable CSV file append behavior. When false, no file writes; other enabled streams may still print. Default true.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ diag_dedup_tol

amrex::Real RadChoice::diag_dedup_tol = 1.0e-12

Tolerance for time equality in duplicate guard [s]. Times within this tolerance are considered equal. Default 1e-12.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ diag_enable

bool RadChoice::diag_enable = false

Master switch for radiation diagnostics emission. When false, no diagnostics output (stdout/tagged/regtest/csv). Default false: a run that did not ask for the diagnostics should not write a CSV row and a stdout block on every step. The per-stream switches below stay on by default, so setting this one input to true turns the whole set on.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ diag_file

std::string RadChoice::diag_file = "radiation_diag.dat"

Output file path for radiation diagnostics CSV. Paths are relative to the simulation working directory.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ diag_regtest_line_enable

bool RadChoice::diag_regtest_line_enable = true

Enable RADIATION_DIAG: line emission. Controls regtest-parsing diagnostics line. Default true.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ diag_stdout_enable

bool RadChoice::diag_stdout_enable = true

Enable human-readable stdout diagnostics block. Controls tagged [RAD][...] debug line emission (when verbosity >= 1). Default true.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ diag_tagged_enable

bool RadChoice::diag_tagged_enable = true

Enable tagged [RAD][...] debug lines. Controls emission of bracketed-tag debug output. Default true.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ enabled

bool RadChoice::enabled = false

True when erf.radiation_model = TwoStream. Set by init_params from the model SolverChoice read; the erf.radiation.* sub-options are read only then.

Referenced by TwoStreamRadiation::active(), TwoStreamRadiation::define_level(), init_params(), and uses_two_stream_radiation().

◆ fixed_solar_zenith_angle

amrex::Real RadChoice::fixed_solar_zenith_angle = -9999.0

erf.fixed_solar_zenith_angle: the COSINE of the solar zenith angle (mu0), as RRTMGP takes it, applied to every column when > 0. Otherwise (default) the sun follows the calendar: start_datetime sets the date and time, the position is evaluated at rad_cons_lat/lon or at the per-column latitude and longitude when the grid carries them.

Referenced by init_params().

◆ fixed_total_solar_irradiance

amrex::Real RadChoice::fixed_total_solar_irradiance = -9999.0

erf.fixed_total_solar_irradiance: top-of-atmosphere irradiance [W/m^2] when >= 0. Otherwise (default) 1360.9 W/m^2 scaled by the Earth-Sun distance factor of the date, as RRTMGP does.

Referenced by init_params().

◆ lw_enabled

bool RadChoice::lw_enabled = true

Enable longwave (thermal) radiation computation. Only used by the two-stream model.

Referenced by init_params().

◆ lw_kabs_cloud

amrex::Real RadChoice::lw_kabs_cloud = 158.0

Cloud-water LW mass absorption coefficient m^2/kg.

Referenced by init_params().

◆ lw_kabs_dry

amrex::Real RadChoice::lw_kabs_dry = 1.0e-4

Dry-air gray LW mass absorption coefficient [m^2/kg].

Referenced by init_params().

◆ lw_kabs_vapor

amrex::Real RadChoice::lw_kabs_vapor = 0.1

Water-vapor gray LW mass absorption coefficient [m^2/kg].

Referenced by init_params().

◆ lw_mass_absorption_enable

bool RadChoice::lw_mass_absorption_enable = false

Gray longwave optical depth from the layer mass path instead of the fixed tau_lw_per_layer (also selected by tau_model = mass): tau_lw(k) = rho dz (lw_kabs_dry + lw_kabs_vapor qv + lw_kabs_cloud qc) The cloud term is the Stephens (1978) emissivity, eps = 1 - exp(-a LWP) with a = 0.158 m^2/g, written as an optical depth. The column optical depth is then independent of the vertical resolution. The cloud-band, moisture-coefficient and aerosol additions still apply on top. Default false keeps tau_lw_per_layer.

Referenced by init_params().

◆ rad_cons_lat

amrex::Real RadChoice::rad_cons_lat = 39.809860

erf.rad_cons_lat / erf.rad_cons_lon: site latitude and longitude [degrees] when the grid has no lat/lon fields (RRTMGP defaults).

Referenced by init_params().

◆ rad_cons_lon

amrex::Real RadChoice::rad_cons_lon = -98.555183

Referenced by init_params().

◆ rad_orbital_eccentricity

amrex::Real RadChoice::rad_orbital_eccentricity = -9999.0

Referenced by init_params().

◆ rad_orbital_mvelp

amrex::Real RadChoice::rad_orbital_mvelp = -9999.0

Referenced by init_params().

◆ rad_orbital_obliquity

amrex::Real RadChoice::rad_orbital_obliquity = -9999.0

Referenced by init_params().

◆ rad_orbital_year

int RadChoice::rad_orbital_year = -9999

erf.rad_orbital_year and the orbital overrides: negative means the year of the timestamp and the Berger (1978) values for that year.

Referenced by init_params().

◆ rad_t_sfc

amrex::Real RadChoice::rad_t_sfc = -1.0

erf.rad_t_sfc: surface temperature [K] used as the longwave boundary condition wherever no land-surface model, surface layer or prognostic surface energy balance supplies one; also the initial value of the prognostic surface temperature. Required, as for RRTMGP.

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_diagnostic_enable

bool RadChoice::seb_diagnostic_enable = false

Enable diagnostic SEB residual computation and reporting. When true, computes and reports SEB residual = (SW_net + LW_net) - H - LE - G. When false (default), no residual computation or new diagnostic output. Requires seb_enable=true to be meaningful; if false but seb_enable=true, auto-enables internally. Note: this is diagnostic-only; it makes no prognostic T_s or flux update. Set seb_prognostic_enable for that.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_enable

bool RadChoice::seb_enable = false

Master switch for simplified SEB infrastructure. When false (default), no SEB MultiFabs are allocated and behavior is unchanged.

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), init_params(), TwoStreamRadiation::seb_hfx(), TwoStreamRadiation::seb_lh(), TwoStreamRadiation::seb_prognostic_active(), TwoStreamRadiation::seb_q_sfc(), and TwoStreamRadiation::seb_t_sfc().

◆ seb_grdflx_default

amrex::Real RadChoice::seb_grdflx_default = 0.0

Fallback SEB ground heat flux [W/m^2]. The force-restore restoring term already represents the flux into the soil, so a nonzero value with seb_prognostic_enable counts that flux twice.

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_hfx_default

amrex::Real RadChoice::seb_hfx_default = 0.0

Fallback SEB sensible heat flux [W/m^2].

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_land_roughness

amrex::Real RadChoice::seb_land_roughness = -1.0

Land roughness length [m] the coupled surface layer takes when erf.most.z0 is not given (derived, not an input): with seb_surface_layer_uses_skin and seb_soil_type, f_veg Z0MVT + (1 - f_veg) Z0SOIL from Noah-MP's tables (f_veg = 0 without seb_vegetation_type); -1 otherwise. ERF::InitData_post hands it to the zlo surface layer as it builds it (SurfaceLayer::set_default_roughness).

Referenced by init_params().

◆ seb_leaf_area_index

amrex::Real RadChoice::seb_leaf_area_index = -1.0

Leaf area index [m^2/m^2] of the vegetated fraction (seb_vegetation_type; giving it otherwise stops at start-up). Default: the land-use category's monthly values interpolated to the run's start date and time (start_datetime), as Noah-MP does with its table LAI (noahmp_day_of_year: day 0 at 00:00 on 1 January), shifted half a year when erf.rad_cons_lat < 0 (one latitude for the domain, where Noah-MP uses each column's); fixed for the run.

Referenced by init_params().

◆ seb_lh_default

amrex::Real RadChoice::seb_lh_default = 0.0

Fallback SEB latent heat flux [W/m^2].

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_lw_flux_default

amrex::Real RadChoice::seb_lw_flux_default = 0.0

Fallback SEB surface net longwave flux [W/m^2].

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_moisture_layer_depth_m

amrex::Real RadChoice::seb_moisture_layer_depth_m = 0.1

Effective surface moisture layer depth [m]. Used in force-restore prognostic q_s equation: dq_s/dt = -(LE/(L_v*rho_w*d_s)) - (1/tau_q)*(q_s - q_deep). Default 0.1 m represents a thin surface-active moisture layer. Only used when seb_prognostic_enable=true. Must be > 0: init_params() stops otherwise.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_moisture_restore_timescale_s

amrex::Real RadChoice::seb_moisture_restore_timescale_s = 86400.0

Force-restore timescale for surface moisture [s]. Relaxation time constant toward q_deep in prognostic q_s equation. Default 86400.0 s (1 day) provides weak damping on diurnal timescales. Only used when seb_prognostic_enable=true. Must be > 0: init_params() stops otherwise.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_prognostic_enable

bool RadChoice::seb_prognostic_enable = false

Enable prognostic SEB surface temperature and moisture evolution. When true, integrates SEB residual forward in time to evolve T_s and q_s using force-restore formulation. When false (default), no prognostic update occurs. Requires seb_enable=true and seb_diagnostic_enable=true; auto-enables internally if needed. Only active when Noah-MP is NOT driving LSM fields at that level.

Referenced by TwoStreamRadiation::advance(), init_params(), and TwoStreamRadiation::seb_prognostic_active().

◆ seb_prognostic_q_max

amrex::Real RadChoice::seb_prognostic_q_max = 1.0

Maximum clamping bound for prognostic surface moisture [kg/kg]. After each Euler update, q_s is clamped to [seb_prognostic_q_min, seb_prognostic_q_max]. Default 1.0 kg/kg ensures physically meaningful moisture. Only used when seb_prognostic_enable=true.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_prognostic_q_min

amrex::Real RadChoice::seb_prognostic_q_min = 0.0

Minimum clamping bound for prognostic surface moisture [kg/kg]. After each Euler update, q_s is clamped to [seb_prognostic_q_min, seb_prognostic_q_max]. Default 0.0 kg/kg prevents negative moisture. Only used when seb_prognostic_enable=true.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_prognostic_t_max_k

amrex::Real RadChoice::seb_prognostic_t_max_k = 340.0

Maximum clamping bound for prognostic surface temperature [K]. After each Euler update, T_s is clamped to [seb_prognostic_t_min_k, seb_prognostic_t_max_k]. Default 340.0 K (above typical surface temperatures, but prevents unrealistic excursions). Only used when seb_prognostic_enable=true.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_prognostic_t_min_k

amrex::Real RadChoice::seb_prognostic_t_min_k = 200.0

Minimum clamping bound for prognostic surface temperature [K]. After each Euler update, T_s is clamped to [seb_prognostic_t_min_k, seb_prognostic_t_max_k] to prevent instability if dt is large relative to C_s/tau. Default 200.0 K (far below realistic surface temperatures). Only used when seb_prognostic_enable=true.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_q_deep_default

amrex::Real RadChoice::seb_q_deep_default = 0.0

Deep soil moisture the prognostic q_s restores to, in q_s's units (see seb_q_sfc_default).

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_q_sfc_default

amrex::Real RadChoice::seb_q_sfc_default = 0.0

Fallback SEB surface moisture, and the initial value of the prognostic one. With seb_prognostic_enable q_s follows prognostic_dqs_dt, a volumetric water content [m^3/m^3] of the top seb_moisture_layer_depth_m of soil; with a land model that has one, the balance shows the land model's 2 m mixing ratio [kg/kg] instead.

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_restore_timescale_s

amrex::Real RadChoice::seb_restore_timescale_s = 86400.0

Force-restore timescale for surface temperature [s]. Relaxation time constant toward T_deep in prognostic T_s equation. Default 86400.0 s (1 day) provides weak damping on diurnal timescales. Only used when seb_prognostic_enable=true. Must be > 0: init_params() stops otherwise.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_soil_moisture_fc

amrex::Real RadChoice::seb_soil_moisture_fc = 0.329

Field capacity [m^3/m^3]: at or above it the soil-water factor is 1, so without seb_soil_type the surface evaporates at the potential rate (seb_surface_layer_uses_moisture; giving it otherwise stops at start-up). Default 0.329, Noah-MP's loam (REFSMC, STAS soil type 6).

Referenced by init_params().

◆ seb_soil_moisture_wilt

amrex::Real RadChoice::seb_soil_moisture_wilt = 0.066

Wilting point [m^3/m^3]: at or below it the soil-water factor is 0, so the vegetation does not transpire and, without seb_soil_type, the surface does not evaporate (with one, the bare soil's nearly dry pore air keeps it near zero) (seb_surface_layer_uses_moisture; giving it otherwise stops at start-up). Default 0.066, Noah-MP's loam (WLTSMC, STAS soil type 6).

Referenced by init_params().

◆ seb_soil_type

int RadChoice::seb_soil_type = 0

Noah-MP soil category (STAS, 1-19, not 14 (water), as in NoahmpTable.TBL; see ERF_NoahMPSoilTable.H). The balance takes its wilting point (WLTSMC) and field capacity (REFSMC) – giving either seb_soil_moisture_wilt or seb_soil_moisture_fc as well is an error –, the surface heat capacity of the soil unless seb_surface_heat_capacity is given, with seb_surface_layer_uses_moisture the bare-soil resistance (vegetation or not), and with seb_surface_layer_uses_skin the surface layer's land roughness unless erf.most.z0 is given. 0 (the default): none of these.

Referenced by init_params().

◆ seb_surface_heat_capacity

amrex::Real RadChoice::seb_surface_heat_capacity = 2.0e4

Effective surface heat capacity [J/(m^2*K)]. Used in force-restore prognostic T_s equation: dT_s/dt = SEB_residual / C_s - (2*pi/tau)*(T_s - T_deep). Default 2.0e4 J/(m^2*K) represents a thin surface-active layer. With seb_soil_type it is derived from Noah-MP's soil instead (seb_force_restore_heat_capacity of the soil's heat capacity and conductivity at seb_q_sfc_default, over seb_restore_timescale_s) unless it is given explicitly. Only used when seb_prognostic_enable=true. Must be > 0: init_params() stops otherwise.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_surface_layer_uses_moisture

bool RadChoice::seb_surface_layer_uses_moisture = false

Two-way coupling of moisture as well: the surface layer takes its land surface mixing ratio from the balance's surface water, so its moisture flux follows the soil and dries as the balance's q_s does. Without seb_soil_type it is beta * q_sat(T_s, p_s) + (1 - beta) * q_air with beta the soil-water factor clamp((q_s - seb_soil_moisture_wilt) / (seb_soil_moisture_fc - seb_soil_moisture_wilt), 0, 1). With seb_soil_type, the bare soil evaporates from its pore air (Noah-MP's relative humidity exp(psi g / (R_v T_s)) times q_sat) through Noah-MP's bare-soil resistance, and with seb_vegetation_type the canopy transpires through its own, each in series with the aerodynamic one (erf_surface_moisture::two_source_surface_mixing_ratio). q_s is then the volumetric water content [m^3/m^3] of the top seb_moisture_layer_depth_m of soil. Requires seb_surface_layer_uses_skin. Default false: the surface layer keeps its own surface moisture (erf.most.surf_moist).

Referenced by TwoStreamRadiation::define_level(), and init_params().

◆ seb_surface_layer_uses_skin

bool RadChoice::seb_surface_layer_uses_skin = false

Two-way coupling with the zlo surface layer: the surface layer takes its land surface temperature from the SEB's prognostic skin temperature T_s (converted to potential temperature), so its sensible heat flux responds to T_s. Requires seb_prognostic_enable and seb_turbulent_flux_source = surface_layer. Default false: the surface layer keeps its own temperature.

Referenced by init_params().

◆ seb_sw_flux_default

amrex::Real RadChoice::seb_sw_flux_default = 0.0

Fallback SEB surface net shortwave flux [W/m^2].

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_t_deep_default

amrex::Real RadChoice::seb_t_deep_default = 300.0

Fallback SEB deep soil temperature [K].

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ seb_turbulent_flux_source

SEBTurbulentFluxSource RadChoice::seb_turbulent_flux_source = SEBTurbulentFluxSource::SurfaceLayer

Source of the SEB's sensible and latent heat fluxes when no land-surface model supplies them: "surface_layer" (default) or "defaults". See SEBTurbulentFluxSource.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_use_radiation_fluxes

bool RadChoice::seb_use_radiation_fluxes = false

Take the SEB's net surface shortwave and longwave fluxes from the two-stream sweep itself (per column, absorbed fluxes positive) wherever the LSM does not expose them. When false (default) those fluxes are the LSM fields or, without an LSM, the seb_sw_flux_default and seb_lw_flux_default constants. Sensible, latent and ground heat fluxes are unaffected.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ seb_vegetation_fraction

amrex::Real RadChoice::seb_vegetation_fraction = 1.0

Vegetated fraction of the surface [0, 1] (seb_vegetation_type; giving it otherwise stops at start-up). Default 1.

Referenced by init_params().

◆ seb_vegetation_type

int RadChoice::seb_vegetation_type = 0

Noah-MP land-use category (modified IGBP MODIS, 1-20 except the unvegetated 15, 16 and 17, as in NoahmpTable.TBL; see ERF_NoahMPVegetationTable.H) of the vegetated fraction. With it, the surface's moisture availability comes from a canopy resistance (Jarvis, Noah-MP's parameters RS, RGL, HS, TOPT, RSMAX) for the vegetated fraction and a bare-soil resistance (Noah-MP's Sakaguchi-Zeng form, on seb_soil_type) for the rest, each in series with the aerodynamic one. Needs seb_surface_layer_uses_moisture and seb_soil_type. 0 (the default): bare soil, the soil's resistance alone (f_veg = 0).

Referenced by init_params().

◆ single_scattering_albedo

amrex::Real RadChoice::single_scattering_albedo = 0.0

Clear-sky (background gas) single-scattering albedo in [0, 1] for the SW diffuse (scattering) two-stream calculation. Default 0.0 means the clear-sky column is purely absorbing, and the diffuse SW contribution from the clear-sky column is exactly zero — reducing exactly to the direct-beam-only result. Only used by the two-stream model and sw_enabled == true.

Referenced by init_params().

◆ surface_albedo_sw

amrex::Real RadChoice::surface_albedo_sw = 0.3

Shortwave surface albedo fallback [0, 1] for per-column heterogeneous-surface-property resolution. Used when per-column LSM/radiation interface albedo field is unavailable or invalid. Default 0.3 represents typical land/water reflectivity. Only used when hetero surface fields not present or disabled.

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ surface_albedo_sw_diffuse

amrex::Real RadChoice::surface_albedo_sw_diffuse = -1.0

Shortwave surface albedo for diffuse light [0,1]. A negative value (default) uses surface_albedo_sw for both direct and diffuse light.

Referenced by init_params().

◆ surface_emissivity_lw

amrex::Real RadChoice::surface_emissivity_lw = 0.99

Longwave surface emissivity fallback [0, 1] for per-column heterogeneous-surface-property resolution. Used when per-column LSM/radiation interface emissivity field is unavailable or invalid. Default 0.99 represents typical land/water/ice emissivity (nearly blackbody). Only used when hetero surface fields not present or disabled.

Referenced by TwoStreamRadiation::advance(), TwoStreamRadiation::define_level(), and init_params().

◆ sw_cloud_g

amrex::Real RadChoice::sw_cloud_g = 0.85

Mass model, SW: cloud-water asymmetry factor.

Referenced by init_params().

◆ sw_cloud_omega

amrex::Real RadChoice::sw_cloud_omega = 0.9999

Mass model, SW: cloud-water single-scattering albedo.

Referenced by init_params().

◆ sw_enabled

bool RadChoice::sw_enabled = true

Enable shortwave (solar) radiation computation. Only used by the two-stream model.

Referenced by TwoStreamRadiation::advance(), and init_params().

◆ sw_kabs_dry

amrex::Real RadChoice::sw_kabs_dry = 4.0e-6

Mass model, SW: dry-air gray absorption coefficient [m^2/kg].

Referenced by init_params().

◆ sw_kabs_vapor

amrex::Real RadChoice::sw_kabs_vapor = 4.0e-3

Mass model, SW: water-vapor gray absorption coefficient [m^2/kg].

Referenced by init_params().

◆ sw_kext_cloud

amrex::Real RadChoice::sw_kext_cloud = 150.0

Mass model, SW: cloud-water extinction coefficient m^2/kg.

Referenced by init_params().

◆ sw_kscat_dry

amrex::Real RadChoice::sw_kscat_dry = 3.0e-6

Mass model, SW: dry-air (Rayleigh) scattering coefficient [m^2/kg], omega = 1, g = 0.

Referenced by init_params().

◆ tau_lw_coeff_qc

amrex::Real RadChoice::tau_lw_coeff_qc = 0.0

Longwave optical depth coefficient for cloud liquid water [dimensionless]. Default 0.0. When both coefficients are 0, dynamic path still invoked but yields tau_lw_per_layer unchanged. Only used when tau_lw_dynamic_enable == true.

Referenced by init_params().

◆ tau_lw_coeff_qv

amrex::Real RadChoice::tau_lw_coeff_qv = 0.0

Longwave optical depth coefficient for water vapor [dimensionless]. Dynamic LW tau = tau_lw_coeff_qv * qv + tau_lw_coeff_qc * qc + tau_lw_per_layer. Default 0.0 means tau is purely from static tau_lw_per_layer (no dynamic component). Only used when tau_lw_dynamic_enable == true.

Referenced by init_params().

◆ tau_lw_dynamic_enable

bool RadChoice::tau_lw_dynamic_enable = false

Enable dynamic longwave optical depth diagnosis from moisture/clouds. When true, LW optical depth is computed per-level from qv and qc. When false (default), uses the static tau_lw_per_layer. Only used by the two-stream model and lw_enabled == true.

Referenced by init_params().

◆ tau_lw_per_layer

amrex::Real RadChoice::tau_lw_per_layer = 1.0

Longwave optical depth per layer (constant for all layers). Used in gray-gas LW two-stream solver. Only used by the two-stream model.

Referenced by init_params().

◆ tau_model

TauModel RadChoice::tau_model = TauModel::PerLayer

Optical depth model: "per_layer" (default, fixed tau per layer) or "mass" (from the layer mass path in both bands; see TauModel).

Referenced by init_params().

◆ tau_per_layer

amrex::Real RadChoice::tau_per_layer = 0.05

Shortwave optical depth per layer (constant for all layers). Used in Beer-Lambert direct-beam formula. Only used by the two-stream model.

Referenced by init_params().

◆ tau_profile_type

TauProfileType RadChoice::tau_profile_type = TauProfileType::Constant

Optical depth profile type: "constant" (default, the thickness-independent tau) or "cloud_layer" (adds height-varying cloud optical depth between cloud_base_height_m and cloud_top_height_m).

Referenced by init_params().

◆ tau_sw_coeff_qc

amrex::Real RadChoice::tau_sw_coeff_qc = 0.0

Shortwave optical depth coefficient for cloud liquid water [dimensionless]. Default 0.0. When both coefficients are 0, dynamic path still invoked but yields tau_per_layer unchanged. Only used when tau_sw_dynamic_enable == true.

Referenced by init_params().

◆ tau_sw_coeff_qv

amrex::Real RadChoice::tau_sw_coeff_qv = 0.0

Shortwave optical depth coefficient for water vapor [dimensionless]. Dynamic SW tau = tau_sw_coeff_qv * qv + tau_sw_coeff_qc * qc + tau_per_layer. Default 0.0 means tau is purely from static tau_per_layer (no dynamic component). Only used when tau_sw_dynamic_enable == true.

Referenced by init_params().

◆ tau_sw_dynamic_enable

bool RadChoice::tau_sw_dynamic_enable = false

Referenced by init_params().

◆ verbosity

int RadChoice::verbosity = 0

Debug verbosity level (0=off, 1+=debug output). Gated debug prints only emit when this is >= 1.

Referenced by TwoStreamRadiation::advance(), and init_params().


The documentation for this struct was generated from the following file: