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

#include <ERF_DataStruct.H>

Collaboration diagram for SolverChoice:

Public Member Functions

void init_params (int max_level, std::string pp_prefix)
 Read solver-wide algorithmic options from the input parameter database. More...
 
void check_params (int max_level, const amrex::Vector< amrex::Geometry > &geom_vect, amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 > phys_bc_type)
 Validate solver options after geometry and boundary conditions are known. More...
 
void display (int max_level, std::string pp_prefix)
 Print the configured solver, physics, and transport options. More...
 
void build_coriolis_forcings_const_lat (std::string pp_prefix)
 Build constant-latitude Coriolis forcing parameters. More...
 
bool read_int_string (int max_level, const char *string_to_read, amrex::Vector< int > &vec_to_fill, int default_int)
 Read one integer value or one value per AMR level. More...
 
bool use_building_immersed_forcing (const amrex::Geometry &geom) const noexcept
 
bool use_perturbation (int lev) const
 Query whether any turbulent perturbation mode is enabled on a level. More...
 
bool use_direct_perturbation (int lev) const
 Query whether direct turbulent perturbations are enabled on a level. More...
 
bool use_source_perturbation (int lev) const
 Query whether source-term turbulent perturbations are enabled on a level. More...
 
bool use_wvel_perturbation (int lev) const
 Query whether vertical-velocity CPM perturbations are enabled on a level. More...
 
bool uses_shoc_family () const noexcept
 Query whether any SHOC-family PBL scheme is active. More...
 
bool host_owns_vertical_momentum_diffusion () const noexcept
 Test whether the host owns momentum diffusion. More...
 
bool host_owns_vertical_scalar_diffusion () const noexcept
 Test whether the host owns scalar diffusion. More...
 
bool pbl_suppresses_microphysics_condensation () const noexcept
 Query whether the active PBL scheme suppresses microphysics condensation. More...
 
bool any_perturbation () const
 Query whether any level uses a turbulent perturbation mode. More...
 
int perturbation_pblh_level (int lev) const
 
bool rad_uses_interface () const
 True for the models that run through the IRadiation interface (RRTMGP, Simple); the two-stream model has its own class. More...
 
bool rad_feeds_lsm () const
 True when the radiation model's outputs feed the land model (downwelling shortwave, downwelling longwave, solar zenith angle). RRTMGP writes them for any land model through lsm_output_ptrs; the two-stream model writes the broadband three for Noah-MP only (TwoStreamRadiation::write_land_forcing), since SLM wants the visible / near-infrared direct / diffuse split it does not compute. Both register the outputs in ERF::init_stuff and write them in ERF::advance_radiation; every site that encodes that rule must use this predicate so wiring another model in (e.g. Simple, which already runs through the interface) is one edit. More...
 

Static Public Member Functions

static void set_mesh_type (MeshType new_mesh_type)
 Override the globally selected mesh type. More...
 

Public Attributes

AdvChoice advChoice
 Advection-related options. More...
 
DiffChoice diffChoice
 Diffusion-related options. More...
 
DampingChoice dampingChoice
 Damping-related options. More...
 
SpongeChoice spongeChoice
 Sponge-layer options. More...
 
amrex::Vector< TurbChoice > turbChoice
 Turbulence options for each AMR level. More...
 
EBChoice ebChoice
 Embedded-boundary options. More...
 
RadChoice radChoice
 
RRTMGPSolarChoice rrtmgpSolarChoice
 
TopographicShadingChoice topographicChoice
 
int force_stage1_single_substep = 1
 Flag forcing a single substep in the first RK stage. More...
 
amrex::Vector< SubsteppingType > substepping_type
 Acoustic substepping type for each AMR level. More...
 
amrex::Vector< int > anelastic
 Per-level flag selecting anelastic dynamics. More...
 
amrex::Vector< AnelasticType > anelastic_type
 Per-level two-stage scheme used by the anelastic integrator. More...
 
amrex::Vector< int > fixed_density
 Per-level flag selecting fixed-density treatment; always 1 at an anelastic level. More...
 
amrex::Vector< int > project_initial_velocity
 Per-level flag for projecting the initial velocity. More...
 
amrex::Vector< int > buoyancy_type
 Per-level buoyancy formulation selector. More...
 
amrex::Vector< int > is_land
 Per-level land/water selector. More...
 
bool substepping_diag = false
 Whether to emit extra CFL diagnostics for compressible substepping. More...
 
amrex::Real beta_s = amrex::Real(0.1)
 Time off-centering coefficient for forward weighting. More...
 
bool use_variable_beta_s = false
 Whether beta_s varies on the w-faces with the terrain slope. More...
 
amrex::Real beta_s_min = amrex::Real(0.1)
 Lower bound of the spatially varying beta_s. More...
 
amrex::Real beta_s_max = amrex::Real(0.8)
 Upper bound of the spatially varying beta_s. More...
 
amrex::Real beta_d = amrex::Real(0.1)
 Divergence damping coefficient used in the acoustic substepping. More...
 
amrex::Vector< amrex::Vector< amrex::Real > > vert_implicit_fac
 Per-level, per-stage implicit vertical diffusion factors. More...
 
bool implicit_thermal_diffusion = true
 Whether implicit vertical thermal diffusion is included. More...
 
bool implicit_moisture_diffusion = true
 Whether implicit vertical moisture diffusion is included. More...
 
bool implicit_ke_diffusion = true
 Whether implicit vertical TKE diffusion is included. More...
 
bool implicit_momentum_diffusion = true
 Whether implicit vertical momentum diffusion is included. More...
 
bool implicit_before_substep = true
 Whether implicit diffusion is applied before acoustic substepping. More...
 
bool implicit_terrain_metric = false
 Whether the compact terrain-metric part of the vertical diffusion is solved implicitly. More...
 
int ncorr = 1
 Number of projection correction iterations. More...
 
std::string wall_dist_type = "poisson"
 
TerrainPoissonSolver terrain_poisson_solver = TerrainPoissonSolver::gmres_fft
 Projection solver on a terrain-fitted mesh: gmres_fft (default), mlmg or gmres_mlmg. More...
 
amrex::Real poisson_abstol = amrex::Real(1e-8)
 Absolute tolerance for the Poisson solve. More...
 
amrex::Real poisson_reltol = amrex::Real(1e-8)
 Relative tolerance for the Poisson solve. More...
 
bool test_mapfactor = false
 Whether to use test map scale factors. More...
 
amrex::Real test_mapfactor_amp = amrex::Real(0)
 Amplitude of the spatially varying test map scale factors on level 0 (0: not used). More...
 
int gradp_type = 0
 Terrain-fitted horizontal pressure-gradient formulation. More...
 
bool use_pert_pres_gradient = true
 Whether momentum equations use perturbational pressure gradients. More...
 
bool use_gravity = false
 Whether gravitational forcing is enabled. More...
 
bool use_coriolis = false
 Whether Coriolis forcing is enabled. More...
 
bool coriolis_3d = true
 Whether the three-dimensional Coriolis terms are included. More...
 
bool four_stream_radiation = false
 Whether the four-stream radiation approximation is enabled. More...
 
bool immersed_forcing_substep = false
 Whether immersed-forcing source terms are applied only during substeps. More...
 
bool forest_substep = false
 Whether canopy source terms are applied only during substeps. More...
 
amrex::Real if_Cd_momentum = amrex::Real(50.0)
 Immersed-forcing drag coefficient for momentum. More...
 
amrex::Real if_Cd_scalar = amrex::Real(10.0)
 Immersed-forcing drag coefficient for scalars. More...
 
bool if_implicit_drag = false
 
bool if_implicit_projection = false
 
amrex::Real if_z0 = amrex::Real(0.1)
 Immersed-forcing roughness length [m]. More...
 
amrex::Real if_surf_temp_flux = amrex::Real(1e-8)
 Immersed-forcing surface temperature flux [K m/s]. More...
 
amrex::Real if_init_surf_temp = zero
 Initial immersed-forcing surface temperature [K]. More...
 
amrex::Real if_surf_heating_rate = zero
 Immersed-forcing surface heating rate [K/hr]. More...
 
amrex::Real if_Olen_in = amrex::Real(1e-8)
 Input Obukhov length for immersed-forcing MOST [m]. More...
 
bool if_use_most = false
 Whether immersed-forcing MOST is enabled. More...
 
bool if_snap_partial_cells = false
 
bool if_stability_correction = false
 Whether immersed-forcing stability corrections are enabled. More...
 
bool if_fraction_stress = false
 erf.if_wall_form = fraction_stress: the wall stress of ERF_ImmersedWallCell.H in the wall cell of each column, with the wall face closed to diffusion; false is the legacy MOST relaxation at fixed 0.5/1.5 dz (the default, unchanged). More...
 
int if_wall_face_spacing = 2
 Spacing the face above the fraction-stress wall cell differences over: 0 the cell height, 1 the centroid spacing, 2 (default) the log spacing (ib_wall::face_above_factor). More...
 
bool if_wall_tke = false
 Hold the k-eqn TKE of the fraction-stress wall cell at its flat-ground wall value (ib_wall::wall_tke), as erf.dirichlet_k does over flat ground. More...
 
amrex::Real if_wall_tke_time_factor = amrex::Real(1.0)
 1 (the default) pins the wall cell after every stage and in the implicit TKE solve; a larger value relaxes toward the wall value as a source over that many steps. More...
 
bool if_flat_wall_dissipation = false
 Partial fraction-stress wall cells dissipate TKE with the length scale of flat ground's first cell; on by default with the fraction-stress law. More...
 
amrex::Real if_ws_floor = 0.001
 Wind-speed floor [m/s] in the per-step change limit of the building wall-law forcing. More...
 
amrex::Real if_damp_alpha = 0.5
 Immersed-forcing damping coefficient. More...
 
amrex::Real if_stability_wind_floor = amrex::Real(0.0)
 Wind-speed floor [m/s] behind the friction velocity of the wall law's stability estimate (0: none). More...
 
amrex::Real if_psi_cap_factor = amrex::Real(1.0)
 Cap on psi_m in the immersed momentum wall law as a fraction of ln(z/z0) (1: none). More...
 
amrex::Real if_small_volfrac = amrex::Real(0.005)
 Immersed-forcing solid fraction below which a cell or face counts as fluid; read from eb2.small_volfrac (default 0.005), the same value the EB build uses. More...
 
std::string if_average_down = "plain"
 Cell average down over immersed-forcing levels: "plain" (the default, the plain cell average) or "fluid_mass" (the fine cells weighted by their fluid mass, coarse cells solid on their own level kept; see if_average_down in ERF_Utils.H). More...
 
amrex::Real if_cf_mismatch_warning = amrex::Real(0.75)
 Spread of the fine solid fractions under a coarse cell along a lateral coarse/fine face at or above which the start-up warning counts the cell (the levels describe the surface differently there); 0 turns the check off. More...
 
bool cf_loglaw_fill = false
 Share the flux of the first coarse face above a wall among its fine sub-faces at the lateral coarse/fine faces by ln(1 + z/z0) at their heights above the wall, instead of the linear interpolation; the immersed surface or a surface-layer bottom, constant dz. More...
 
amrex::Real cf_loglaw_z0 = amrex::Real(-1.0)
 Roughness length [m] of that share; by default erf.if_z0 with immersed forcing, else the inputs' erf.most.z0 or erf.zlo.most.z0 (0.1 m when neither is given). More...
 
bool use_lagged_delta_rt = true
 Whether to use lagged delta terms for moving terrain. More...
 
bool rebalance_wrf_input = true
 Whether to rebalance states from wrfinput and wrfbdy data. More...
 
amrex::Real gravity
 Effective gravitational acceleration. More...
 
amrex::Real c_p = Cp_d
 Specific heat at constant pressure for dry air [J/(kg-K)]. More...
 
amrex::Real rdOcp
 Ratio of dry-air gas constant to c_p. More...
 
amrex::Real grid_stretching_ratio = 0
 Vertical grid stretching ratio. More...
 
amrex::Real dz0 = zero
 Initial vertical grid spacing for stretched-grid setup. More...
 
amrex::Real coriolis_factor = zero
 Twice the planetary rotation rate used for Coriolis forcing. More...
 
amrex::Real cosphi = zero
 Cosine of the latitude used for Coriolis forcing. More...
 
amrex::Real sinphi = zero
 Sine of the latitude used for Coriolis forcing. More...
 
bool custom_rhotheta_forcing = false
 Whether custom rho-theta forcing is enabled. More...
 
bool custom_moisture_forcing = false
 Whether custom moisture forcing is enabled. More...
 
bool custom_w_subsidence = false
 Whether custom vertical subsidence is enabled. More...
 
bool do_theta_advection = true
 Whether custom vertical subsidence is applied to rho-theta. More...
 
bool do_mom_advection = true
 Whether custom vertical subsidence is applied to momentum. More...
 
bool custom_geostrophic_profile = false
 Whether a custom geostrophic wind profile is used. More...
 
bool custom_forcing_prim_vars = false
 Whether custom forcing operates on primitive variables. More...
 
bool spatial_rhotheta_forcing = false
 Whether spatially varying rho-theta forcing is enabled. More...
 
bool spatial_moisture_forcing = false
 Whether spatially varying moisture forcing is enabled. More...
 
bool nudging_from_input_sounding = false
 Whether solution fields are nudged toward input sounding data. More...
 
bool nudging_from_observations = false
 Whether solution fields are nudged toward observations at stations. More...
 
amrex::Real nudging_u_z1 = amrex::Real(-1.0e36)
 
amrex::Real nudging_u_z2 = amrex::Real(1.0e36)
 
amrex::Real nudging_t_z1 = zero
 
amrex::Real nudging_t_z2 = amrex::Real(10000.0)
 
amrex::Real nudging_q_z1 = zero
 
amrex::Real nudging_q_z2 = amrex::Real(10000.0)
 
bool nudging_u = true
 
bool nudging_t = true
 
bool nudging_q = true
 
bool large_scale_forcing = false
 
std::string lsf_file = ""
 
amrex::Real lsf_timescale = zero
 
bool use_rotate_surface_flux = false
 Whether MOST surface fluxes are rotated with terrain. More...
 
bool use_eamxx_shoc = false
 Whether any level uses the EAMxx SHOC PBL scheme. More...
 
bool use_native_shoc = false
 Whether any level uses the native SHOC PBL scheme. More...
 
ShocTransportMode shoc_transport_mode = ShocTransportMode::StateUpdate
 
ShocMomentumTransport shoc_momentum_transport = ShocMomentumTransport::StateUpdate
 
bool transport_scalar = true
 Whether the passive scalar component is transported. More...
 
bool time_avg_vel = false
 Whether time-averaged velocity fields are output. More...
 
bool compute_mean_vars = false
 
std::string mean_vars_reset_mode = "plotfile"
 
amrex::Real mean_vars_reset_time = -one
 
amrex::Vector< PerturbationType > pert_type
 Turbulent perturbation type for each AMR level. More...
 
bool perturbation_auto {false}
 Select LES nests, using parent winds and a PBL ancestor's height, or the nearest LES ancestor's diagnostic when no PBL scheme is present. Defaults to true for WRFInput and Metgrid initialization, false otherwise. More...
 
amrex::Real perturbation_auto_period {amrex::Real(600.0)}
 Seconds between automatic parent-wind and PBL-height updates. More...
 
amrex::Real perturbation_auto_pbl_fraction {amrex::Real(0.9)}
 Fraction of the selected ancestor's PBL height occupied by perturbations. More...
 
bool use_num_diff {false}
 Whether sixth-order numerical diffusion is enabled. More...
 
amrex::Real num_diff_coeff {zero}
 Numerical diffusion coefficient after input scaling. More...
 
CouplingType coupling_type
 Multilevel coupling strategy. More...
 
MoistureType moisture_type
 Moisture or microphysics model. More...
 
int sbm_nbins {4}
 
int sbm_moment_mode {1}
 
int sbm_cloud_rain_split {-1}
 
bool sbm_test_native_qc_write_fault {false}
 
bool sbm_test_donor_cfl_fault {false}
 
amrex::Vector< amrex::Real > sbm_edges
 
amrex::Vector< amrex::Real > sbm_pivots
 
amrex::Vector< amrex::Real > sbm_fixture_initial_state
 
WindFarmType windfarm_type
 Wind-farm model. More...
 
WindFarmLocType windfarm_loc_type
 Coordinate system for wind-farm turbine locations. More...
 
LandSurfaceType lsm_type
 Land-surface model. More...
 
UrbanType urban_type
 
amrex::Vector< int > urban_enabled_lev
 
RadiationType rad_type
 Radiation model. More...
 
bool use_coupled_sst = false
 
ABLDriverType abl_driver_type
 Atmospheric boundary-layer driver type. More...
 
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_pressure_grad
 Applied ABL pressure-gradient forcing vector. More...
 
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_geo_forcing
 Applied geostrophic-wind forcing vector. More...
 
std::string abl_geo_wind_table
 Path to a time-varying geostrophic wind table. More...
 
bool have_geo_wind_profile {false}
 Whether a geostrophic wind profile has been configured. More...
 
bool variable_coriolis {false}
 Whether spatially varying Coriolis forcing is enabled. More...
 
int ave_plane {2}
 Averaging plane index used by diagnostics. More...
 
MoistureComponentIndices moisture_indices
 Index map of the moisture data carried by the active scheme: conserved-state components for the species and qmoist slots for the moist diagnostics. More...
 
bool moisture_tight_coupling {false}
 Whether moisture updates use tight coupling. More...
 
std::string windfarm_loc_table
 Wind-farm location table path. More...
 
std::string windfarm_spec_table
 Wind-farm turbine specification table path. More...
 
std::string windfarm_spec_table_extra
 Additional wind-farm turbine specification table path. More...
 
std::string windfarm_blade_table
 Wind-farm blade table path. More...
 
std::string windfarm_airfoil_tables
 Wind-farm airfoil table paths. More...
 
amrex::Real sampling_distance_by_D = -one
 Turbine inflow sampling distance normalized by rotor diameter. More...
 
amrex::Real turb_disk_angle = -one
 Turbine disk angle from the x axis [deg]. More...
 
amrex::Real windfarm_x_shift = -one
 Wind-farm x-coordinate shift. More...
 
amrex::Real windfarm_y_shift = -one
 Wind-farm y-coordinate shift. More...
 
amrex::Real bdy_nudge_factor = amrex::Real(10.0)
 Boundary sponge nudging factor. More...
 
bool use_wrf_bdy_density = true
 
bool use_wrf_bdy_qc_qi = false
 Whether WRF cloud water and active cloud ice are ingested at real boundaries. More...
 
amrex::Real bdy_rho_nudge_factor = amrex::Real(-1.0)
 
int bdy_moist_nudge_type = 1
 Moist-variable nudging strategy in boundary regions. More...
 
bool avg_grid_faces_to_nodes {false}
 
bool wrfinput_zlevels_from_file {true}
 
bool interp_atmos_from_coarse {false}
 
bool do_forest_drag {false}
 Whether forest canopy drag is enabled. More...
 
bool forest_biophysics {false}
 
bool forest_biophysics_heat {false}
 
amrex::Real forest_leaf_theta_fixed {-one}
 
CanopyTurbulence canopyTurb
 
amrex::Real const_massflux_u = zero
 Target constant mass flux in the x direction. More...
 
amrex::Real const_massflux_v = zero
 Target constant mass flux in the y direction. More...
 
amrex::Real const_massflux_tau = one
 Relaxation time scale for constant-mass-flux forcing. More...
 
amrex::Real const_massflux_layer_lo = amrex::Real(-bogus_large_value)
 Lower height of the constant-mass-flux forcing layer. More...
 
amrex::Real const_massflux_layer_hi = amrex::Real( bogus_large_value)
 Upper height of the constant-mass-flux forcing layer. More...
 
int massflux_klo {0}
 Lower vertical index for constant-mass-flux forcing. More...
 
int massflux_khi {0}
 Upper vertical index for constant-mass-flux forcing. More...
 
std::string hindcast_boundary_data_dir
 Directory containing hindcast lateral boundary data. More...
 
std::string hindcast_surface_data_dir
 Directory containing hindcast surface boundary data. More...
 
amrex::Real hindcast_data_interval_in_hrs = -one
 Time interval between hindcast data files [hr]. More...
 
bool hindcast_lateral_forcing = false
 Whether hindcast lateral forcing is enabled. More...
 
bool hindcast_surface_bcs = false
 Whether hindcast surface boundary conditions are enabled. More...
 
amrex::Real hindcast_lateral_sponge_strength = -one
 Strength of the hindcast lateral sponge layer. More...
 
amrex::Real hindcast_lateral_sponge_length = -one
 Length of the hindcast lateral sponge layer. More...
 
amrex::Real hindcast_zhi_sponge_strength = -one
 Strength of the upper hindcast sponge layer. More...
 
amrex::Real hindcast_zhi_sponge_length = -one
 Length of the upper hindcast sponge layer. More...
 
bool hindcast_zhi_sponge_damping = false
 Whether upper-boundary hindcast sponge damping is enabled. More...
 
bool io_hurricane_eye_tracker = false
 Whether hurricane-eye tracking output is enabled. More...
 
amrex::Real hurricane_eye_latitude = -1e10
 Initial hurricane-eye latitude. More...
 
amrex::Real hurricane_eye_longitude = -1e10
 Initial hurricane-eye longitude. More...
 
bool is_init_for_ensemble = false
 Whether initialization is for an ensemble simulation. More...
 
int n_ensemble = -1
 Number of ensemble members. More...
 
amrex::Real ens_pert_correlated_radius = -1.0
 Spatial correlation radius for ensemble perturbations. More...
 
amrex::Real ens_pert_amplitude = -1.0
 Amplitude of ensemble initialization perturbations. More...
 
std::string coarse_bckgnd_data_file
 Coarse background data file used for ensemble initialization. More...
 

Static Public Attributes

static InitType init_type = InitType::None
 Initial-condition source selected for the run. More...
 
static SoundingType sounding_type = SoundingType::Ideal
 Interpretation used for input sounding profiles. More...
 
static TerrainType terrain_type = TerrainType::None
 Terrain or immersed-boundary representation. More...
 
static bool flat_terrain = false
 Permit fixed-index planar averages after validating a flat fitted mesh. More...
 
static BuildingsType buildings_type = BuildingsType::None
 Building representation. More...
 
static bool buildings_fc_factories = false
 Use native face-centered EB factories for immersed buildings on a static fitted mesh. More...
 
static bool use_real_bcs = false
 Whether real-data lateral boundary conditions are used. More...
 
static MeshType mesh_type = MeshType::ConstantDz
 Vertical mesh representation. More...
 

Detailed Description

Container holding many of the algorithmic options and parameters

Member Function Documentation

◆ any_perturbation()

bool SolverChoice::any_perturbation ( ) const
inline

Query whether any level uses a turbulent perturbation mode.

Returns
True if at least one configured level has source, direct, CPM, or CPM_W perturbations.
2905  {
2906  for (const auto& type : pert_type) {
2907  if (type == PerturbationType::Source ||
2908  type == PerturbationType::Direct ||
2909  type == PerturbationType::CPM ||
2910  type == PerturbationType::CPM_W) {
2911  return true;
2912  }
2913  }
2914  return false;
2915  }
amrex::Vector< PerturbationType > pert_type
Turbulent perturbation type for each AMR level.
Definition: ERF_DataStruct.H:2932

Referenced by check_params().

Here is the caller graph for this function:

◆ build_coriolis_forcings_const_lat()

void SolverChoice::build_coriolis_forcings_const_lat ( std::string  pp_prefix)
inline

Build constant-latitude Coriolis forcing parameters.

Parameters
pp_prefixParmParse prefix for the ERF input namespace.
2509  {
2510  amrex::ParmParse pp(pp_prefix);
2511 
2512  // Read the rotational time period (in seconds)
2513  double rot_time_period = 86400.0;
2514  pp.queryAdd("rotational_time_period", rot_time_period);
2515 
2516  coriolis_factor = static_cast<amrex::Real>(4.0 * PI / rot_time_period);
2517 
2518  pp.queryAdd("coriolis_3d", coriolis_3d);
2519 
2520  // Convert to radians
2521  amrex::Real latitude_for_coriolis = amrex::Real(90.0);
2522  pp.queryAdd("latitude", latitude_for_coriolis);
2523  latitude_for_coriolis *= (PI/amrex::Real(180.));
2524  sinphi = std::sin(latitude_for_coriolis);
2525 
2526  // Note: cosphi defaults to 0
2527  if (coriolis_3d) {
2528  cosphi = std::cos(latitude_for_coriolis);
2529  }
2530 
2531  amrex::Print() << "Coriolis frequency, f = " << coriolis_factor * sinphi << " 1/s" << std::endl;
2532 
2533  if (abl_driver_type == ABLDriverType::GeostrophicWind) {
2534  // Read in the geostrophic wind -- we only use this to construct
2535  // the forcing term so no need to keep it
2536  amrex::Vector<amrex::Real> abl_geo_wind(3);
2537  pp.queryarr("abl_geo_wind",abl_geo_wind);
2538 
2539  if(!pp.queryAdd("abl_geo_wind_table",abl_geo_wind_table)) {
2540  abl_geo_forcing = {
2541  -coriolis_factor * (abl_geo_wind[1]*sinphi - abl_geo_wind[2]*cosphi),
2542  coriolis_factor * abl_geo_wind[0]*sinphi,
2543  -coriolis_factor * abl_geo_wind[0]*cosphi
2544  };
2545  } else {
2546  amrex::Print() << "NOTE: abl_geo_wind_table provided, ignoring input abl_geo_wind" << std::endl;
2547  }
2548  }
2549  }
ParmParse pp("prob")
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:46
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::Real coriolis_factor
Twice the planetary rotation rate used for Coriolis forcing.
Definition: ERF_DataStruct.H:2745
std::string abl_geo_wind_table
Path to a time-varying geostrophic wind table.
Definition: ERF_DataStruct.H:2985
amrex::Real cosphi
Cosine of the latitude used for Coriolis forcing.
Definition: ERF_DataStruct.H:2746
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_geo_forcing
Applied geostrophic-wind forcing vector.
Definition: ERF_DataStruct.H:2984
ABLDriverType abl_driver_type
Atmospheric boundary-layer driver type.
Definition: ERF_DataStruct.H:2982
amrex::Real sinphi
Sine of the latitude used for Coriolis forcing.
Definition: ERF_DataStruct.H:2747
bool coriolis_3d
Whether the three-dimensional Coriolis terms are included.
Definition: ERF_DataStruct.H:2690

Referenced by init_params().

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

◆ check_params()

void SolverChoice::check_params ( int  max_level,
const amrex::Vector< amrex::Geometry > &  geom_vect,
amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 >  phys_bc_type 
)
inline

Validate solver options after geometry and boundary conditions are known.

Parameters
max_levelMaximum AMR level configured for the run.
geom_vectGeometry for each AMR level.
phys_bc_typePhysical boundary-condition types.
2105  {
2106  // The weighted average down acts only where covered coarse cells are averaged down
2107  if (if_average_down == "fluid_mass") {
2108  if (max_level > 0 && coupling_type == CouplingType::TwoWay) {
2109  amrex::Print() << "Immersed forcing: erf.if_average_down = fluid_mass (the cell average down "
2110  << "over refined levels is weighted by the fluid mass of the fine cells)\n";
2111  } else {
2112  amrex::Warning("erf.if_average_down = fluid_mass has no effect without refined levels "
2113  "(amr.max_level > 0) and erf.coupling_type = TwoWay");
2114  }
2115  }
2116  if (if_fraction_stress) {
2117  // The face-above spacing factor is bounded only while z0 < dz/4 (then d2 > d1 for
2118  // every solid fraction and the fluid centroid of a full wall cell sits above 2 z0)
2119  for (int lev = 0; lev <= max_level; ++lev) {
2120  const amrex::Real dz = geom_vect[lev].CellSize(2);
2121  if (!(if_z0 < amrex::Real(0.25) * dz)) {
2122  amrex::Abort("erf.if_wall_form = fraction_stress needs erf.if_z0 < dz/4 on every level (level " +
2123  std::to_string(lev) + ": z0 = " + std::to_string(if_z0) + " m, dz = " +
2124  std::to_string(dz) + " m)");
2125  }
2126  }
2127  }
2129  bool any_keqn = false;
2130  for (int lev = 0; lev <= max_level; ++lev) {
2131  any_keqn = any_keqn || (turbChoice[lev].rans_type == RANSType::kEqn);
2132  }
2133  if (!any_keqn) {
2134  amrex::Abort("erf.if_wall_tke and erf.if_flat_wall_dissipation act on the k-eqn RANS closure: "
2135  "set erf.rans_type = kEqn on a level, or turn them off (erf.if_flat_wall_dissipation = false)");
2136  }
2137  }
2138  if (if_fraction_stress) {
2139  amrex::Print() << "Immersed forcing: erf.if_wall_form = fraction_stress (wall stress in the wall cell, "
2140  << "the wall face closed to diffusion; face spacing "
2141  << ((if_wall_face_spacing == 2) ? "log" : (if_wall_face_spacing == 1) ? "physical" : "grid")
2142  << ", wall TKE " << (if_wall_tke ? "on" : "off")
2143  << ", flat-wall dissipation " << (if_flat_wall_dissipation ? "on" : "off") << ")\n";
2144  }
2145  // The log-law coarse/fine fill acts only on refined levels
2146  if (cf_loglaw_fill) {
2147  const bool immersed = (terrain_type == TerrainType::ImmersedForcing ||
2148  buildings_type == BuildingsType::ImmersedForcing);
2149  if (!immersed && phys_bc_type[amrex::Orientation(amrex::Direction::z, amrex::Orientation::low)] != ERF_BC::surface_layer) {
2150  amrex::Abort("erf.cf_loglaw_fill needs an immersed surface (erf.terrain_type or "
2151  "erf.buildings_type = ImmersedForcing) or zlo.type = surface_layer");
2152  }
2153  if (max_level > 0) {
2154  amrex::Print() << "Coarse/fine faces: erf.cf_loglaw_fill = true (the wall coarse face's flux is shared "
2155  << "among its fine sub-faces by the integral of ln(1 + z/z0), z0 = " << cf_loglaw_z0 << " m)\n";
2156  } else {
2157  amrex::Warning("erf.cf_loglaw_fill has no effect without refined levels (amr.max_level > 0)");
2158  }
2159  }
2161  (terrain_type == TerrainType::EB || terrain_type == TerrainType::ImmersedForcing)) {
2162  amrex::Abort("Automatic perturbations currently support flat, stretched, and fitted-terrain meshes; "
2163  "immersed/embedded terrain requires a ground-relative parent PBL-height conversion");
2164  }
2165 #if 0
2166  // Warn for PBL models and moisture - these may not yet be compatible
2167  for (int lev = 0; lev <= max_level; lev++) {
2168  if ((moisture_type != MoistureType::None) && (turbChoice[lev].pbl_type != PBLType::None)) {
2169  amrex::Warning("\n*** WARNING: Moisture may not yet be compatible with PBL models, \n proceed with caution ***");
2170  }
2171  }
2172 #endif
2173  //
2174  // Buoyancy type check
2175  //
2176  for (int lev = 0; lev <= max_level; lev++) {
2177  if (buoyancy_type[lev] != 1 && buoyancy_type[lev] != 2 && buoyancy_type[lev] != 3 && buoyancy_type[lev] != 4) {
2178  amrex::Error("buoyancy_type must be 1, 2, 3 or 4");
2179  }
2180  }
2181 
2182  if (!use_lagged_delta_rt && !(terrain_type == TerrainType::MovingFittedMesh)) {
2183  amrex::Error("Can't turn off lagged_delta_rt when terrain not moving");
2184  }
2185 
2186  //
2187  // Wind farm checks
2188  //
2189  if (windfarm_type==WindFarmType::SimpleAD and sampling_distance_by_D < zero) {
2190  amrex::Error("To use simplified actuator disks, you need to provide a variable"
2191  " erf.sampling_distance_by_D in the inputs which specifies the upstream"
2192  " distance as a factor of the turbine diameter at which the incoming free stream"
2193  " velocity will be computed at.");
2194  }
2195  if ( (windfarm_type==WindFarmType::SimpleAD ||
2196  windfarm_type==WindFarmType::GeneralAD ) && turb_disk_angle < zero) {
2197  amrex::Error("To use simplified actuator disks, you need to provide a variable"
2198  " erf.turb_disk_angle_from_x in the inputs which is the angle of the face of the"
2199  " turbine disk from the x-axis. A turbine facing an oncoming flow in the x-direction"
2200  " will have turb_disk_angle value of 90 deg.");
2201  }
2202  if (windfarm_loc_type == WindFarmLocType::lat_lon and (windfarm_x_shift < zero or windfarm_y_shift < zero)) {
2203  amrex::Error("You are using windfarms with latitude-logitude option to position the turbines."
2204  " For this you should provide the inputs erf.windfarm_x_shift and"
2205  " erf.windfarm_y_shift which are the values by which the bounding box of the"
2206  " windfarm is shifted from the x and the y axes.");
2207  }
2208 
2209 
2210  if ( (const_massflux_u != 0) && !(geom_vect[0].isPeriodic(0)) ) {
2211  amrex::Error("Constant mass flux (in x) should be used with periodic boundaries");
2212  }
2213 
2214  if ( (const_massflux_v != 0) && !(geom_vect[0].isPeriodic(1)) ) {
2215  amrex::Error("Constant mass flux (in y) should be used with periodic boundaries");
2216  }
2217 
2218  // Mesoscale diffusion -- test if LES appropriate with this dx,dy
2219  for (int lev = 0; lev <= max_level; lev++) {
2220  if ((geom_vect[lev].CellSize(0) > amrex::Real(2000.)) || (geom_vect[lev].CellSize(1) > amrex::Real(2000.)))
2221  {
2222  if ( (turbChoice[lev].les_type == LESType::Smagorinsky) && !turbChoice[lev].smag2d ) {
2223  amrex::Warning("Should use 2-D Smagorinsky for mesoscale resolution");
2224  } else if (turbChoice[lev].les_type == LESType::Deardorff) {
2225  amrex::Warning("Should not use Deardorff LES for mesoscale resolution");
2226  }
2227  }
2228  }
2229 
2230  // Turn off implicit solve if we have no diffusion
2231  bool l_use_kturb = turbChoice[0].use_kturb;
2232  for (int lev = 1; lev <= max_level; lev++) {
2233  l_use_kturb = (l_use_kturb || turbChoice[lev].use_kturb);
2234  }
2235  bool l_use_diff = ( (diffChoice.molec_diff_type != MolecDiffType::None) || l_use_kturb );
2236 
2237  for (int lev = 0; lev <= max_level; lev++) {
2238  bool l_implicit_diff = (vert_implicit_fac[lev][0] > zero ||
2239  vert_implicit_fac[lev][1] > zero ||
2240  vert_implicit_fac[lev][2] > zero);
2241  if (l_implicit_diff && !l_use_diff) {
2242  amrex:: Print() << "No molecular or turbulent diffusion, turning off implicit solve at level " << lev << std::endl;
2243  vert_implicit_fac[lev][0] = zero;
2244  vert_implicit_fac[lev][1] = zero;
2245  vert_implicit_fac[lev][2] = zero;
2246  }
2247  }
2248 
2249  // Two-way coupling refluxes the diffusive fluxes of the slow scalars, but not on an EB mesh
2250  if (coupling_type == CouplingType::TwoWay && terrain_type == TerrainType::EB &&
2251  max_level > 0 && l_use_diff) {
2252  amrex::Warning("erf.coupling_type = TwoWay with erf.terrain_type = EB does not reflux the "
2253  "diffusive fluxes: diffusion does not conserve the scalars across "
2254  "coarse/fine boundaries");
2255  }
2256 
2257  // The implicit terrain metric is a change to the vertical implicit solves on a
2258  // terrain-fitted mesh; refuse it where it could not do anything. This comes after
2259  // every block that can turn the implicit solve off.
2261  if (mesh_type != MeshType::VariableDz) {
2262  amrex::Abort("erf.implicit_terrain_metric = true requires a terrain-fitted mesh with "
2263  "non-flat terrain (erf.terrain_type = StaticFittedMesh or MovingFittedMesh); "
2264  "on a flat or a purely stretched mesh there are no terrain-metric terms");
2265  }
2266  // In a stage without the implicit solve the whole averaged metric term is explicit
2267  // for that stage. On the steep ridge test the option gained little with 1 1 0
2268  // and ran worse than without it with anelastic MidPoint (measured before the exact
2269  // split: 15 s instead of 30 s), while 1 1 1 recovered the full time step. The rule
2270  // is measured, not derived: every stage must solve implicitly.
2271  for (int lev = 0; lev <= max_level; lev++) {
2272  for (int i = 0; i < 3; ++i) {
2273  if (vert_implicit_fac[lev][i] <= zero) {
2274  amrex::Abort("erf.implicit_terrain_metric = true needs the vertical implicit solve "
2275  "in every Runge-Kutta stage at every level, but erf.vert_implicit_fac "
2276  "is not positive in stage " + std::to_string(i+1) + " at level " +
2277  std::to_string(lev) + ". Set erf.vert_implicit_fac = 1 1 1; the "
2278  "option cannot be used where the implicit solve is turned off "
2279  "(erf.vert_implicit = false, every erf.implicit_*_diffusion = false, "
2280  "no molecular or turbulent diffusion, or anelastic, which solves in "
2281  "its first stage only or not at all)");
2282  }
2283  }
2284  }
2285  // The momentum solves carry most of the stiffness; with them explicit the option
2286  // treats only the scalar metric terms implicitly
2288  amrex::Print() << "WARNING: erf.implicit_terrain_metric = true with "
2289  << "erf.implicit_momentum_diffusion = false: the momentum terrain-metric "
2290  << "terms stay explicit; only the scalars are treated implicitly" << std::endl;
2291  }
2292  } else if (mesh_type == MeshType::VariableDz) {
2293  // On a terrain-fitted mesh the projected horizontal stresses carry K_h, and their
2294  // terrain-metric part K_h h^2 d2/dz2 is explicit in any stage without the implicit
2295  // solve. On steep slopes that limits the time step (steep test ridge: 45 s before
2296  // #4214 was fixed, 15 s after, at the default 1 1 0). Say so once at start-up.
2297  bool explicit_stage_with_kh = false;
2298  for (int lev = 0; lev <= max_level; lev++) {
2299  if (turbChoice[lev].les_type == LESType::None) { continue; }
2300  for (int i = 0; i < 3; ++i) {
2301  if (vert_implicit_fac[lev][i] <= zero) { explicit_stage_with_kh = true; }
2302  }
2303  }
2304  if (explicit_stage_with_kh) {
2305  amrex::Print() << "NOTE: terrain-fitted mesh with an LES closure (horizontal eddy "
2306  << "viscosity K_h) and an explicit vertical-diffusion stage "
2307  << "(erf.vert_implicit_fac has a zero): the terrain-metric term "
2308  << "K_h h^2 d2/dz2 stays explicit there and limits the time step on "
2309  << "steep slopes. To relax it, use erf.vert_implicit_fac = 1 1 1 with "
2310  << "erf.implicit_terrain_metric = true, or erf.smag2d_slope_limiter = true "
2311  << "for Smagorinsky2D; erf.diffusive_dt_check reports the limit."
2312  << std::endl;
2313  }
2314  }
2315 
2316  // Countergradient validation: ensure required implicit diffusion is enabled
2317  for (int lev = 0; lev <= max_level; lev++) {
2318  if (turbChoice[lev].enable_mrf_countergradient) {
2320  vert_implicit_fac[lev][0] > zero ||
2321  vert_implicit_fac[lev][1] > zero ||
2322  vert_implicit_fac[lev][2] > zero,
2323  "enable_mrf_countergradient requires vert_implicit_fac > 0");
2326  "enable_mrf_countergradient requires implicit_thermal_diffusion = true");
2330  "enable_mrf_countergradient with moisture requires implicit_moisture_diffusion = true");
2331  }
2332  }
2333  }
2334 
2335  for (int lev = 0; lev <= max_level; lev++) {
2336  turbChoice[lev].check_params(phys_bc_type);
2337  }
2338  }
@ surface_layer
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
@ None
Definition: ERF_LSM_Types.H:6
@ dz
Definition: ERF_AdvanceWDM6.cpp:273
MolecDiffType molec_diff_type
Selected molecular transport model.
Definition: ERF_DiffStruct.H:96
WindFarmLocType windfarm_loc_type
Coordinate system for wind-farm turbine locations.
Definition: ERF_DataStruct.H:2952
amrex::Real const_massflux_v
Target constant mass flux in the y direction.
Definition: ERF_DataStruct.H:3044
amrex::Vector< TurbChoice > turbChoice
Turbulence options for each AMR level.
Definition: ERF_DataStruct.H:2620
bool if_fraction_stress
erf.if_wall_form = fraction_stress: the wall stress of ERF_ImmersedWallCell.H in the wall cell of eac...
Definition: ERF_DataStruct.H:2714
bool implicit_moisture_diffusion
Whether implicit vertical moisture diffusion is included.
Definition: ERF_DataStruct.H:2661
MoistureType moisture_type
Moisture or microphysics model.
Definition: ERF_DataStruct.H:2942
amrex::Vector< int > buoyancy_type
Per-level buoyancy formulation selector.
Definition: ERF_DataStruct.H:2633
CouplingType coupling_type
Multilevel coupling strategy.
Definition: ERF_DataStruct.H:2941
amrex::Real const_massflux_u
Target constant mass flux in the x direction.
Definition: ERF_DataStruct.H:3043
amrex::Real sampling_distance_by_D
Turbine inflow sampling distance normalized by rotor diameter.
Definition: ERF_DataStruct.H:2999
amrex::Real windfarm_y_shift
Wind-farm y-coordinate shift.
Definition: ERF_DataStruct.H:3002
bool any_perturbation() const
Query whether any level uses a turbulent perturbation mode.
Definition: ERF_DataStruct.H:2904
amrex::Real if_z0
Immersed-forcing roughness length [m].
Definition: ERF_DataStruct.H:2706
bool implicit_thermal_diffusion
Whether implicit vertical thermal diffusion is included.
Definition: ERF_DataStruct.H:2660
bool perturbation_auto
Select LES nests, using parent winds and a PBL ancestor's height, or the nearest LES ancestor's diagn...
Definition: ERF_DataStruct.H:2933
static MeshType mesh_type
Vertical mesh representation.
Definition: ERF_DataStruct.H:2604
amrex::Real turb_disk_angle
Turbine disk angle from the x axis [deg].
Definition: ERF_DataStruct.H:3000
amrex::Real cf_loglaw_z0
Roughness length [m] of that share; by default erf.if_z0 with immersed forcing, else the inputs' erf....
Definition: ERF_DataStruct.H:2727
amrex::Real windfarm_x_shift
Wind-farm x-coordinate shift.
Definition: ERF_DataStruct.H:3001
bool use_lagged_delta_rt
Whether to use lagged delta terms for moving terrain.
Definition: ERF_DataStruct.H:2730
amrex::Vector< amrex::Vector< amrex::Real > > vert_implicit_fac
Per-level, per-stage implicit vertical diffusion factors.
Definition: ERF_DataStruct.H:2657
bool cf_loglaw_fill
Share the flux of the first coarse face above a wall among its fine sub-faces at the lateral coarse/f...
Definition: ERF_DataStruct.H:2726
bool implicit_terrain_metric
Whether the compact terrain-metric part of the vertical diffusion is solved implicitly.
Definition: ERF_DataStruct.H:2667
bool if_wall_tke
Hold the k-eqn TKE of the fraction-stress wall cell at its flat-ground wall value (ib_wall::wall_tke)...
Definition: ERF_DataStruct.H:2716
static TerrainType terrain_type
Terrain or immersed-boundary representation.
Definition: ERF_DataStruct.H:2589
bool if_flat_wall_dissipation
Partial fraction-stress wall cells dissipate TKE with the length scale of flat ground's first cell; o...
Definition: ERF_DataStruct.H:2718
std::string if_average_down
Cell average down over immersed-forcing levels: "plain" (the default, the plain cell average) or "flu...
Definition: ERF_DataStruct.H:2724
static BuildingsType buildings_type
Building representation.
Definition: ERF_DataStruct.H:2595
int if_wall_face_spacing
Spacing the face above the fraction-stress wall cell differences over: 0 the cell height,...
Definition: ERF_DataStruct.H:2715
DiffChoice diffChoice
Diffusion-related options.
Definition: ERF_DataStruct.H:2617
WindFarmType windfarm_type
Wind-farm model.
Definition: ERF_DataStruct.H:2951
bool implicit_momentum_diffusion
Whether implicit vertical momentum diffusion is included.
Definition: ERF_DataStruct.H:2663
Here is the call graph for this function:

◆ display()

void SolverChoice::display ( int  max_level,
std::string  pp_prefix 
)
inline

Print the configured solver, physics, and transport options.

Parameters
max_levelMaximum AMR level configured for the run.
pp_prefixParmParse prefix used to display nested choices.
2346  {
2347  amrex::Print() << "SOLVER CHOICE: " << std::endl;
2348  if (perturbation_auto) {
2349  amrex::Print() << "Automatic LES-nest perturbations: parent update period = "
2350  << perturbation_auto_period << " s, PBL height fraction = "
2351  << perturbation_auto_pbl_fraction << std::endl;
2352  }
2353  for (int lev = 0; lev <= max_level; lev++) {
2354  amrex::Print() << "At level " << lev << " : " << std::endl;
2355  if (anelastic[lev]) {
2356  amrex::Print() << " anelastic with no substepping, using the "
2357  << ((anelastic_type[lev] == AnelasticType::MidPoint) ? "MidPoint" : "RK2")
2358  << " integrator" << std::endl;
2359  } else {
2361  amrex::Print() << " compressible with no substepping" << std::endl;
2362  } else if (substepping_type[lev] == SubsteppingType::Implicit) {
2363  amrex::Print() << " compressible with implicit substepping" << std::endl;
2364  }
2365  }
2366  if (fixed_density[lev]) {
2367  amrex::Print() << " and fixed density" << std::endl;
2368  }
2369  }
2370 
2371  for (int lev = 0; lev <= max_level; lev++) {
2372  amrex::Print() << "vert_implicit_fac at level " << lev << " : "
2373  << vert_implicit_fac[lev][0] << " "
2374  << vert_implicit_fac[lev][1] << " "
2375  << vert_implicit_fac[lev][2];
2376  if (vert_implicit_fac[lev][0] > zero ||
2377  vert_implicit_fac[lev][1] > zero ||
2378  vert_implicit_fac[lev][2] > zero)
2379  {
2380  amrex::Print() << " (theta = " << implicit_thermal_diffusion
2381  << ", moisture = " << implicit_moisture_diffusion
2382  << ", tke = " << implicit_ke_diffusion
2383  << ", momenta = " << implicit_momentum_diffusion;
2385  amrex::Print() << "; terrain metric implicit";
2386  }
2387  amrex::Print() << ")";
2388  }
2389  }
2390  amrex::Print() << std::endl;
2391  amrex::Print() << "use_coriolis : " << use_coriolis << std::endl;
2392  amrex::Print() << "use_gravity : " << use_gravity << std::endl;
2393 
2394  if (moisture_type == MoistureType::SAM) {
2395  amrex::Print() << "Moisture Model: SAM" << std::endl;
2396  } else if (moisture_type == MoistureType::SAM_NoIce) {
2397  amrex::Print() << "Moisture Model: SAM No Ice" << std::endl;
2398  } else if (moisture_type == MoistureType::SAM_NoPrecip_NoIce) {
2399  amrex::Print() << "Moisture Model: SAM No Precip No Ice" << std::endl;
2400  } else if (moisture_type == MoistureType::Morrison) {
2401  amrex::Print() << "Moisture Model: Morrison" << std::endl;
2402  } else if (moisture_type == MoistureType::Morrison_NoIce) {
2403  amrex::Print() << "Moisture Model: Morrison_NoIce" << std::endl;
2404  } else if (moisture_type == MoistureType::WSM6) {
2405  amrex::Print() << "Moisture Model: WSM6" << std::endl;
2406  } else if (moisture_type == MoistureType::WDM6) {
2407  amrex::Print() << "Moisture Model: WDM6" << std::endl;
2408  } else if (moisture_type == MoistureType::Kessler) {
2409  amrex::Print() << "Moisture Model: Kessler" << std::endl;
2410  } else if (moisture_type == MoistureType::Kessler_NoRain) {
2411  amrex::Print() << "Moisture Model: Kessler No Rain" << std::endl;
2412  } else if (moisture_type == MoistureType::SatAdj) {
2413  amrex::Print() << "Moisture Model: Saturation Adjustment" << std::endl;
2414  } else if (moisture_type == MoistureType::SuperDroplets) {
2415  amrex::Print() << "Moisture Model: SuperDroplets" << std::endl;
2416  } else if (moisture_type == MoistureType::MoistNoCondensation) {
2417  amrex::Print() << "Moisture Model: MoistNoCondensation" << std::endl;
2418  } else if (moisture_type == MoistureType::SBM) {
2419  amrex::Print() << "Moisture Model: SBM mapped spectral advection (M3)" << std::endl;
2420  } else {
2421  amrex::Print() << "Moisture Model: None" << std::endl;
2422  }
2423 
2424  if (terrain_type == TerrainType::StaticFittedMesh) {
2425  amrex::Print() << "Terrain Type: StaticFittedMesh" << std::endl;
2426  } else if (terrain_type == TerrainType::MovingFittedMesh) {
2427  amrex::Print() << "Terrain Type: MovingFittedMesh" << std::endl;
2428  } else if (terrain_type == TerrainType::EB) {
2429  amrex::Print() << "Terrain Type: EB" << std::endl;
2430  ebChoice.display();
2431  } else if (terrain_type == TerrainType::ImmersedForcing) {
2432  amrex::Print() << "Terrain Type: ImmersedForcing" << std::endl;
2433  } else {
2434  amrex::Print() << "Terrain Type: None" << std::endl;
2435  }
2436 
2437  amrex::Print() << "Flat fitted terrain: "
2438  << (flat_terrain ? "true" : "false") << std::endl;
2439 
2440  if (buildings_type == BuildingsType::ImmersedForcing) {
2441  amrex::Print() << "Buildings Type: ImmersedForcing" << std::endl;
2442  } else {
2443  amrex::Print() << "Buildings Type: None" << std::endl;
2444  }
2445 
2446  if (mesh_type == MeshType::ConstantDz) {
2447  amrex::Print() << " Mesh Type: ConstantDz" << std::endl;
2448  } else if (mesh_type == MeshType::StretchedDz) {
2449  amrex::Print() << " Mesh Type: StretchedDz" << std::endl;
2450  } else if (mesh_type == MeshType::VariableDz) {
2451  amrex::Print() << " Mesh Type: VariableDz" << std::endl;
2452  } else {
2453  amrex::Error("No mesh_type set!");
2454  }
2455 
2456  amrex::Print() << "ABL Driver Type: " << std::endl;
2458  amrex::Print() << " None" << std::endl;
2459  } else if (abl_driver_type == ABLDriverType::PressureGradient) {
2460  amrex::Print() << " Pressure Gradient "
2461  << amrex::RealVect(abl_pressure_grad[0],abl_pressure_grad[1],abl_pressure_grad[2])
2462  << std::endl;
2463  } else if (abl_driver_type == ABLDriverType::GeostrophicWind) {
2464  amrex::Print() << " Geostrophic Wind "
2465  << amrex::RealVect(abl_geo_forcing[0],abl_geo_forcing[1],abl_geo_forcing[2])
2466  << std::endl;
2467  }
2468 
2469  if (max_level > 0) {
2470  amrex::Print() << "Coupling Type: " << std::endl;
2471  if (coupling_type == CouplingType::TwoWay) {
2472  amrex::Print() << " Two-way" << std::endl;
2473  } else if (coupling_type == CouplingType::OneWay) {
2474  amrex::Print() << " One-way" << std::endl;
2475  }
2476  }
2477 
2478  if (rad_type == RadiationType::RRTMGP) {
2479  amrex::Print() << "Radiation Model: RRTMGP" << std::endl;
2480  } else if (rad_type == RadiationType::Simple) {
2481  amrex::Print() << "Radiation Model: Simple" << std::endl;
2482  } else if (rad_type == RadiationType::TwoStream) {
2483  amrex::Print() << "Radiation Model: TwoStream" << std::endl;
2484  } else {
2485  amrex::Print() << "Radiation Model: None" << std::endl;
2486  }
2487 
2488  amrex::Print() << "Gradp_type : " << gradp_type << std::endl;
2489 
2490  for (int lev = 0; lev <= max_level; lev++) {
2491  amrex::Print() << "Buoyancy_type at level " << lev << " : " << buoyancy_type[lev] << std::endl;
2492  }
2493 
2494  advChoice.display(pp_prefix);
2495  diffChoice.display();
2498 
2499  for (int lev = 0; lev <= max_level; lev++) {
2500  turbChoice[lev].display(lev);
2501  }
2502  }
void display(std::string &pp_prefix)
Print the configured advection choices.
Definition: ERF_AdvStruct.H:245
void display()
Print the configured damping options.
Definition: ERF_DampingStruct.H:71
void display()
Print the configured diffusion options.
Definition: ERF_DiffStruct.H:79
void display()
Print the configured embedded-boundary options.
Definition: ERF_EBStruct.H:63
static bool flat_terrain
Permit fixed-index planar averages after validating a flat fitted mesh.
Definition: ERF_DataStruct.H:2592
amrex::Vector< int > fixed_density
Per-level flag selecting fixed-density treatment; always 1 at an anelastic level.
Definition: ERF_DataStruct.H:2631
amrex::Real perturbation_auto_period
Seconds between automatic parent-wind and PBL-height updates.
Definition: ERF_DataStruct.H:2934
EBChoice ebChoice
Embedded-boundary options.
Definition: ERF_DataStruct.H:2621
bool implicit_ke_diffusion
Whether implicit vertical TKE diffusion is included.
Definition: ERF_DataStruct.H:2662
bool use_gravity
Whether gravitational forcing is enabled.
Definition: ERF_DataStruct.H:2688
amrex::Vector< SubsteppingType > substepping_type
Acoustic substepping type for each AMR level.
Definition: ERF_DataStruct.H:2628
bool use_coriolis
Whether Coriolis forcing is enabled.
Definition: ERF_DataStruct.H:2689
AdvChoice advChoice
Advection-related options.
Definition: ERF_DataStruct.H:2616
SpongeChoice spongeChoice
Sponge-layer options.
Definition: ERF_DataStruct.H:2619
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_pressure_grad
Applied ABL pressure-gradient forcing vector.
Definition: ERF_DataStruct.H:2983
amrex::Vector< int > anelastic
Per-level flag selecting anelastic dynamics.
Definition: ERF_DataStruct.H:2629
amrex::Real perturbation_auto_pbl_fraction
Fraction of the selected ancestor's PBL height occupied by perturbations.
Definition: ERF_DataStruct.H:2935
int gradp_type
Terrain-fitted horizontal pressure-gradient formulation.
Definition: ERF_DataStruct.H:2683
DampingChoice dampingChoice
Damping-related options.
Definition: ERF_DataStruct.H:2618
amrex::Vector< AnelasticType > anelastic_type
Per-level two-stage scheme used by the anelastic integrator.
Definition: ERF_DataStruct.H:2630
RadiationType rad_type
Radiation model.
Definition: ERF_DataStruct.H:2956
void display()
Print the configured sponge-layer options.
Definition: ERF_SpongeStruct.H:85
Here is the call graph for this function:

◆ host_owns_vertical_momentum_diffusion()

bool SolverChoice::host_owns_vertical_momentum_diffusion ( ) const
inlinenoexcept

Test whether the host owns momentum diffusion.

Returns
True if ERF dycore does vertical diffusion of momentum.
2874  {
2875  if (use_eamxx_shoc) { return false; }
2876  if (!use_native_shoc) { return true; }
2878  }
bool shoc_disables_momentum_transport(ShocMomentumTransport mode)
Definition: ERF_ShocTransportStruct.H:47
bool use_native_shoc
Whether any level uses the native SHOC PBL scheme.
Definition: ERF_DataStruct.H:2788
ShocMomentumTransport shoc_momentum_transport
Definition: ERF_DataStruct.H:2792
bool use_eamxx_shoc
Whether any level uses the EAMxx SHOC PBL scheme.
Definition: ERF_DataStruct.H:2787

Referenced by init_params().

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

◆ host_owns_vertical_scalar_diffusion()

bool SolverChoice::host_owns_vertical_scalar_diffusion ( ) const
inlinenoexcept

Test whether the host owns scalar diffusion.

Returns
True if ERF dycore does vertical diffusion of scalars.
2885  {
2886  if (use_eamxx_shoc) { return false; }
2887  if (!use_native_shoc) { return true; }
2888  return false;
2889  }

Referenced by init_params().

Here is the caller graph for this function:

◆ init_params()

void SolverChoice::init_params ( int  max_level,
std::string  pp_prefix 
)
inline

Read solver-wide algorithmic options from the input parameter database.

Parameters
max_levelMaximum AMR level configured for the run.
pp_prefixParmParse prefix for the ERF input namespace.
723  {
724  amrex::ParmParse pp(pp_prefix);
725 
726  bool bogus_bool;
727  if (pp.query("use_terrain",bogus_bool) > 0) {
728  amrex::Error("The input use_terrain is deprecated. Set terrain_type instead.");
729  }
730 
731  if (pp.query("use_moist_background",bogus_bool) > 0) {
732  amrex::Error("The input use_moist_background is deprecated. Set init_type = MoistBaseState instead.");
733  }
734 
735  // Do we set map scale factors to myhalf instead of 1 for testing?
736  pp.queryAdd("test_mapfactor", test_mapfactor);
737 
738  // For testing: if nonzero, the map scale factors on level 0 vary smoothly in space,
739  // m = 1 + test_mapfactor_amp sin(2 pi x / Lx) cos(2 pi y / Ly), as if read from an init file
740  // there; finer levels take theirs from the coarser level, as a level without a file does
741  pp.queryAdd("test_mapfactor_amp", test_mapfactor_amp);
743  amrex::Abort("erf.test_mapfactor and erf.test_mapfactor_amp cannot be used together");
744  }
745 
746  // Which horizontal pressure gradient formulation to use with terrain fitted coords?
747  // 0: dp/dx with dp/dz correction (default)
748  // 1: gradient of vertically interpolated p, see Klemp 2011
749  pp.queryAdd("gradp_type", gradp_type);
751 
752  // For the lateral pressure gradient to be used in the momentum equation, should we
753  // take the x- and y-derivatives of the perturbational pressure or the full pressure?
754  pp.queryAdd("use_pert_pres_gradient", use_pert_pres_gradient);
755 
756  // What type of moisture model to use?
757  moisture_type = MoistureType::None; // Default
758  if (pp.query("moisture_type",moisture_type) > 0) {
759  amrex::Error("The input moisture_type is deprecated. Set moisture_model instead.");
760  }
761 
762  pp.query_enum_case_insensitive("moisture_model",moisture_type);
763 
764  // Test-only SBM failure injections. They remain disabled unless an
765  // integration test explicitly enables the corresponding option.
766  pp.queryAdd("sbm_test_native_qc_write_fault", sbm_test_native_qc_write_fault);
767  pp.queryAdd("sbm_test_donor_cfl_fault", sbm_test_donor_cfl_fault);
768  if (moisture_type != MoistureType::SBM &&
770  amrex::Error("SBM test fault-injection options require moisture_model=SBM");
771  }
772 
773  // Register the moisture data this scheme carries: conserved-state
774  // components and qmoist diagnostic slots alike. MoistureComponentIndices
775  // is the one place that mapping lives, and every consumer -- source terms,
776  // turbulence closures, and the plotfile/subvolume writers -- queries it
777  // instead of testing moisture_type.
779 
780  if (moisture_type == MoistureType::SBM) {
781  if (pp.contains("sbm_zero_transport_fixture")) {
782  bool legacy_zero_transport = false;
783  pp.get("sbm_zero_transport_fixture", legacy_zero_transport);
784  if (legacy_zero_transport) {
785  amrex::Error("erf.sbm_zero_transport_fixture=true is obsolete; M3 advances the mapped spectral state, so remove this option");
786  }
787  }
788  pp.queryAdd("sbm_nbins", sbm_nbins);
789  pp.queryAdd("sbm_moment_mode", sbm_moment_mode);
790  pp.queryAdd("sbm_cloud_rain_split", sbm_cloud_rain_split);
791  pp.queryarr("sbm_edges", sbm_edges);
792  pp.queryarr("sbm_pivots", sbm_pivots);
793  pp.queryarr("sbm_fixture_initial_state", sbm_fixture_initial_state);
794 
795  if (sbm_nbins < 2 || (sbm_moment_mode != 1 && sbm_moment_mode != 2)) {
796  amrex::Error("SBM requires sbm_nbins >= 2 and sbm_moment_mode equal to 1 or 2");
797  }
798  if (sbm_edges.empty()) {
799  sbm_edges.resize(static_cast<std::size_t>(sbm_nbins + 1));
800  sbm_pivots.resize(static_cast<std::size_t>(sbm_nbins));
801  for (int b = 0; b <= sbm_nbins; ++b) {
802  const amrex::Real fraction = static_cast<amrex::Real>(b) /
803  static_cast<amrex::Real>(sbm_nbins);
804  sbm_edges[static_cast<std::size_t>(b)] =
805  std::pow(amrex::Real(10.0), amrex::Real(-18.0) + amrex::Real(6.0) * fraction);
806  }
807  for (int b = 0; b < sbm_nbins; ++b) {
808  sbm_pivots[static_cast<std::size_t>(b)] = std::sqrt(
809  sbm_edges[static_cast<std::size_t>(b)] * sbm_edges[static_cast<std::size_t>(b + 1)]);
810  }
811  } else {
812  sbm_nbins = static_cast<int>(sbm_edges.size()) - 1;
813  if (sbm_nbins < 2) amrex::Error("sbm_edges must define at least two bins");
814  if (sbm_pivots.empty()) {
815  sbm_pivots.resize(static_cast<std::size_t>(sbm_nbins));
816  for (int b = 0; b < sbm_nbins; ++b) {
817  sbm_pivots[static_cast<std::size_t>(b)] = std::sqrt(
818  sbm_edges[static_cast<std::size_t>(b)] * sbm_edges[static_cast<std::size_t>(b + 1)]);
819  }
820  }
821  }
822  if (sbm_pivots.size() != static_cast<amrex::Long>(sbm_nbins)) {
823  amrex::Error("sbm_pivots must contain one value per SBM bin");
824  }
826  if (sbm_cloud_rain_split <= 0 || sbm_cloud_rain_split >= sbm_nbins) {
827  amrex::Error("sbm_cloud_rain_split must be strictly inside the liquid bin range");
828  }
829  const int expected_sbm_components = sbm_nbins * (sbm_moment_mode == 2 ? 2 : 1);
830  if (!sbm_fixture_initial_state.empty() &&
831  sbm_fixture_initial_state.size() != static_cast<amrex::Long>(expected_sbm_components)) {
832  amrex::Error("sbm_fixture_initial_state must match the full runtime SBM component count");
833  }
834  for (const amrex::Real value : sbm_fixture_initial_state) {
835  if (!std::isfinite(value) || value < amrex::Real(0.0)) {
836  amrex::Error("sbm_fixture_initial_state values must be finite and nonnegative");
837  }
838  }
839  }
840 
841  // Set a default for both dry and moist
842  buoyancy_type.resize(max_level+1);
843  for (int i = 0; i <= max_level; ++i) {
844  buoyancy_type[i] = 1; // uses Rhoprime
845  }
846 
848  pp.queryAdd("moisture_tight_coupling",moisture_tight_coupling);
849  }
850 
851  // Which expression (1,2/3 or 4) to use for buoyancy
852  int default_buoyancy_type = buoyancy_type[0];
853  read_int_string(max_level, "buoyancy_type", buoyancy_type, default_buoyancy_type);
854 
855  // What type of land surface model to use
856  lsm_type = LandSurfaceType::None; // Default
857  pp.query_enum_case_insensitive("land_surface_model",lsm_type);
858 
859  // What type of urban model to use and whether it is active at the given level
861  pp.query_enum_case_insensitive("urban_model", urban_type);
862  read_int_string(max_level, "urban_lev_active", urban_enabled_lev, 1);
863  for (int lev = 0; lev <= max_level; ++lev) {
864  if (urban_enabled_lev[lev] != 0 && urban_enabled_lev[lev] != 1) {
865  amrex::Error("urban_lev_active should be 0 or 1");
866  }
867  }
868 
869  // Will an external ocean coupler supply SST for part or all of the water
870  // cells this run? The surface layer needs to know this it in time to select
871  // ThetaCalcType::SURFACE_TEMPERATURE, which is long before the first
872  // ApplyOceanSurfaceState call.
873  pp.queryAdd("use_coupled_sst", use_coupled_sst);
874 
875  read_int_string(max_level, "is_land", is_land, 1);
876  for (int lev = 0; lev <= max_level; ++lev) {
877  if (is_land[lev] == 1) {
878  amrex::Print() << "Level " << lev << " is land" << std::endl;
879  } else if (is_land[lev] == 0) {
880  amrex::Print() << "Level " << lev << " is water" << std::endl;
881  } else {
882  amrex::Error("is_land should be 0 or 1");
883  }
884  }
885 
886  // What type of radiation model to use
887  rad_type = RadiationType::None; // Default
888  pp.query_enum_case_insensitive("radiation_model", rad_type);
889 
890  // Verify that radiation model cannot be RRTMGP if ERF was not compiled with RRTMGP
891 #ifndef ERF_USE_RRTMGP
892  if (rad_type == RadiationType::RRTMGP)
893  {
894  amrex::Error("ERF was not compiled with RRTMGP enabled!");
895  }
896 #endif
897 
898  // Is the terrain none, static or moving?
899  std::string terrain_type_temp = "";
900  pp.queryAdd("terrain_type", terrain_type_temp);
901  if (terrain_type_temp == "Moving") {
902  amrex::Error("erf.terrain_type = Moving is no longer supported; please replace Moving by MovingFittedMesh");
903  } else if (terrain_type_temp == "Static") {
904  amrex::Error("erf.terrain_type = Static is no longer supported; please replace Static by StaticFittedMesh");
905  } else {
906  pp.query_enum_case_insensitive("terrain_type",terrain_type);
907  }
908 
909  // Whether the terrain is flat - this allows planar averages (lsf, nudging) with StaticFittedMesh
910  pp.queryAdd("flat_terrain", flat_terrain);
911 
912  // Get buildings type
913  std::string buildings_type_temp = "";
914  pp.queryAdd("buildings_type", buildings_type_temp);
915  if (buildings_type_temp == "ImmersedForcing") {
916  buildings_type = BuildingsType::ImmersedForcing;
917  }
918  pp.queryAdd("buildings_fc_factories", buildings_fc_factories);
919 
920  //
921  // Read the init_type here to make sure we correctly set the mesh and terrain types
922  //
923  std::string init_type_temp_string;
924 
925  int found = pp.queryAdd("init_type",init_type_temp_string);
926 
927  if ( (init_type_temp_string == "Real") || (init_type_temp_string == "real") ) {
928  amrex::Error("erf.init_type = Real is deprecated; please replace Real by WRFInput");
929  } else if ( (init_type_temp_string == "Ideal") || (init_type_temp_string == "ideal") ) {
930  amrex::Error("erf.init_type = Ideal is deprecated; please replace Ideal by WRFInput");
931  } else {
932  pp.query_enum_case_insensitive("init_type",init_type);
933  use_real_bcs = ( (init_type == InitType::WRFInput) || (init_type == InitType::Metgrid) );
934  }
935 
936  if ( (init_type == InitType::WRFInput) || (init_type == InitType::Metgrid) ) {
937  if (terrain_type != TerrainType::StaticFittedMesh) {
938  amrex::Error("Only terrain_type = StaticFittedMesh are allowed with init_type = WRFInput or Metgrid");
939  }
940  }
941 
942  if (init_type == InitType::MoistBaseState) {
944  amrex::Error("Makes no sense to have moist base state with no moisture model");
945  }
946  }
947 
948  if (init_type == InitType::WRFInput) {
950  amrex::Error("Can't have moisture_type = None with init_type = WRFInput");
951  }
952 
953  // NetCDF wrfbdy lateral boundary file
954  std::string nc_bdy_file_temp_string;
955  bool has_bdy = pp.queryAdd("nc_bdy_file", nc_bdy_file_temp_string);
956  if (!has_bdy) use_real_bcs = false;
957 
958  bool use_real_bcs_temp = use_real_bcs;
959  pp.queryAdd("use_real_bcs", use_real_bcs_temp);
960  if (use_real_bcs && !use_real_bcs_temp) {
961  use_real_bcs = false;
962  }
963  }
964 
965  if (found == 0 || init_type == InitType::None) {
966  amrex::Print() << "init_type must now be set. The options are " << std::endl;
967  amrex::Print() << " Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, " << std::endl;
968  amrex::Print() << " ConstantDensity, Isentropic, MoistBaseState, or HindCast " << std::endl;
969  amrex::Error("Please add a string for init_type to your inputs file or command line");
970  }
971 
972  // How to interpret input_sounding
973  if (init_type == InitType::Input_Sounding) {
974  pp.query_enum_case_insensitive("sounding_type",sounding_type);
975  }
976 
977  if (terrain_type == TerrainType::StaticFittedMesh ||
978  terrain_type == TerrainType::MovingFittedMesh) {
979  mesh_type = MeshType::VariableDz;
980  }
981 
982  if (flat_terrain && terrain_type != TerrainType::StaticFittedMesh) {
983  amrex::Error("erf.flat_terrain requires terrain_type = StaticFittedMesh");
984  }
985 
986  // Refined levels over moving terrain are not supported: erf_substep_MT does not take the
987  // fluxes through coarse/fine faces from the coarse level (cf_flux_history_active)
988  if (terrain_type == TerrainType::MovingFittedMesh && max_level > 0) {
989  amrex::Error("erf.terrain_type = MovingFittedMesh requires amr.max_level = 0");
990  }
991 
992  // Immersed-forcing buildings need the terrain blanking that init_zphys builds, and
993  // init_zphys returns before building it when the terrain is EB
994  if (terrain_type == TerrainType::EB && buildings_type == BuildingsType::ImmersedForcing) {
995  amrex::Error("erf.buildings_type = ImmersedForcing is not supported with erf.terrain_type = EB");
996  }
997 
998  if ( (moisture_type == MoistureType::SAM ||
999  moisture_type == MoistureType::SAM_NoIce ||
1000  moisture_type == MoistureType::SAM_NoPrecip_NoIce ) &&
1001  (mesh_type == MeshType::VariableDz) )
1002  {
1003  amrex::Abort("SAM is not correct with variable dz -- choose another moisture model");
1004  }
1005 
1006  // queryAdd puts the default in the table, so ask whether the ratio was given first
1007  const bool have_stretching_ratio = pp.contains("grid_stretching_ratio");
1008  pp.queryAdd("grid_stretching_ratio", grid_stretching_ratio);
1009  if (grid_stretching_ratio != 0) {
1011  "The grid stretching ratio must be greater than 1");
1012  }
1013  // erf.initial_dz on its own asks for the stretching ratio to be solved for, so that
1014  // a first layer that thick stretches geometrically to close on prob_hi[2]. An
1015  // explicit erf.grid_stretching_ratio = 0 still means no stretching at all.
1016  const bool solve_stretching_ratio = !have_stretching_ratio && pp.contains("initial_dz");
1017  if (grid_stretching_ratio >= 1 || solve_stretching_ratio) {
1019  terrain_type = TerrainType::StaticFittedMesh;
1020  }
1021  if (mesh_type == MeshType::ConstantDz) {
1022  mesh_type = MeshType::StretchedDz;
1023  }
1024  pp.get("initial_dz", dz0);
1025  }
1026 
1027  // The stretched levels start at geometry.prob_lo[2]; erf.zsurface used to set the
1028  // bottom separately, and a flat surface did not follow it (#4442)
1029  if (pp.contains("zsurface")) {
1030  amrex::Abort("erf.zsurface is no longer supported: a stretched vertical grid now starts "
1031  "at geometry.prob_lo[2], so set the bottom of the domain there instead");
1032  }
1033 
1034  int n_zlevels = pp.countval("terrain_z_levels");
1035  if (n_zlevels > 0)
1036  {
1038  terrain_type = TerrainType::StaticFittedMesh;
1039  }
1040  if (mesh_type == MeshType::ConstantDz) {
1041  mesh_type = MeshType::StretchedDz;
1042  }
1043  }
1044 
1045  // Use lagged_delta_rt in the fast integrator?
1046  pp.queryAdd("use_lagged_delta_rt", use_lagged_delta_rt);
1047 
1048  // Average the input z-face heights onto the nodes, or reconstruct our own
1049  pp.queryAdd("avg_grid_faces_to_nodes",avg_grid_faces_to_nodes);
1050 
1051  // Build the ERF vertical grid from the file's own mean layer-thickness profile,
1052  // or from a single geometric stretch anchored on the file's first layer?
1053  pp.queryAdd("wrfinput_zlevels_from_file",wrfinput_zlevels_from_file);
1054 
1055  // Catch the old name for the flag above so the error says what to do
1056  // rather than silently ignoring the setting.
1057  if (pp.contains("use_wrf_height_grid")) {
1058  amrex::Abort("erf.use_wrf_height_grid has been renamed. "
1059  "Set erf.avg_grid_faces_to_nodes instead; it carries "
1060  "the same meaning (average the input z-face heights "
1061  "onto the nodes rather than reconstructing them).");
1062  }
1063 
1064  // Interpolate atmospheric state from coarse level instead of reading from wrfinput
1065  // when creating a finer level from coarse at a later time?
1066  pp.queryAdd("interp_atmos_from_coarse", interp_atmos_from_coarse);
1067 
1068  // Rebalance wrf state?
1069  pp.queryAdd("rebalance_wrf_input", rebalance_wrf_input);
1070 
1071  // Must rebalance if the nodal heights were reconstructed rather than averaged
1073  amrex::Print() << "Must rebalance when not averaging the input height grid. Setting rebalance_wrf_input to true \n";
1074  rebalance_wrf_input = true;
1075  }
1076 
1077  // These default to true but are used for unit testing
1078  pp.queryAdd("use_gravity", use_gravity);
1079 
1080  // Initializing from Metgrid or WRFInput without gravity makes no sense
1081  if ( !use_gravity && ( (init_type == InitType::WRFInput) || (init_type == InitType::Metgrid) ) ) {
1082  amrex::Print() << "Setting use_gravity to true due to init_type = WRFInput / Metgrid " << std::endl;
1083  use_gravity = true;
1084  }
1085 
1087 
1088  pp.queryAdd("c_p", c_p);
1089  rdOcp = R_d / c_p;
1090 
1091  // *******************************************************************************
1092  // Read anelastic etc and over-ride if necessary
1093  // *******************************************************************************
1094 
1095  read_int_string(max_level, "anelastic", anelastic, 0);
1096  const bool fixed_density_given =
1097  read_int_string(max_level, "fixed_density", fixed_density, 0);
1098  read_int_string(max_level, "project_initial_velocity", project_initial_velocity, 0);
1099 
1100  // The anelastic equations hold the density at its base-state value, so
1101  // fixed_density is forced to 1 at every anelastic level; a user value of 0
1102  // there is ignored, and we say so rather than drop it silently.
1103  bool any_anelastic = false;
1104  bool any_compress = false;
1105  for (int i = 0; i <= max_level; ++i) {
1106  if (anelastic[i] == 1) {
1107  if (fixed_density_given && fixed_density[i] == 0) {
1108  amrex::Print() << "WARNING: erf.fixed_density = 0 is ignored at level " << i
1109  << " because erf.anelastic = 1 there; the anelastic equations"
1110  << " always hold the density fixed in time." << std::endl;
1111  }
1112  project_initial_velocity[i] = 1;
1113  fixed_density[i] = 1; // Always fixed when anelastic
1114  buoyancy_type[i] = 3; // (This isn't actually used when anelastic is set)
1115  any_anelastic = true;
1116  } else {
1117  any_compress = true;
1118  }
1119  }
1120 
1122  amrex::Error("erf.moisture_model = SuperDroplets is not supported with "
1123  "erf.anelastic = 1: the Super-Droplet path currently uses "
1124  "the compressible equation of state. Use compressible "
1125  "dynamics or a supported Eulerian moisture model.");
1126  }
1127 
1128  // Want to have different immersed forcing defaults depending on anelastic or fully compressible.
1129  // We should have different starting values because the stability of the method is dependent on dt.
1130  // dt is coarser for anelastic --> need to loosen stiffness of immersed forcing.
1131  if (any_anelastic) {
1132  immersed_forcing_substep = false;
1133  if_Cd_momentum = amrex::Real(50.0);
1134  if_Cd_scalar = amrex::Real(5.0);
1135  } else {
1136  immersed_forcing_substep = true;
1137  if_Cd_momentum = amrex::Real(500.0);
1138  if_Cd_scalar = amrex::Real(50.0);
1139  }
1140 
1141  // *******************************************************************************
1142  // Read anelastic_type and allow for different values at each level
1143  // *******************************************************************************
1144  anelastic_type.resize(max_level+1);
1145 
1146  for (int i = 0; i <= max_level; i++) {
1147  anelastic_type[i] = AnelasticType::RK2;
1148  }
1149 
1150  for (int i = 0; i <= max_level; i++) {
1152  pp, "anelastic_type", anelastic_type[i], i, max_level);
1153  }
1154 
1155  if (pp.contains("anelastic_type") && !any_anelastic) {
1156  amrex::Print() << "Ignoring erf.anelastic_type because no level is anelastic" << std::endl;
1157  for (int i = 0; i <= max_level; i++) { anelastic_type[i] = AnelasticType::RK2; }
1158  }
1159 
1160  // *******************************************************************************
1161  // Read substepping_type and allow for different values at each level
1162  // *******************************************************************************
1163  substepping_type.resize(max_level+1);
1164 
1165  for (int i = 0; i <= max_level; i++) {
1166  substepping_type[i] = SubsteppingType::Implicit;
1167  }
1168 
1169  for (int i = 0; i <= max_level; i++) {
1171  pp, "substepping_type", substepping_type[i], i, max_level);
1172  }
1173 
1174  pp.queryAdd("substepping_diag", substepping_diag);
1175 
1176  pp.queryAdd("beta_s", beta_s);
1177 
1178  // Divergence damping coefficient for the forward projection of (rho theta)
1179  pp.queryAdd("beta_d", beta_d);
1180  if (!(beta_d >= amrex::Real(0.0) && beta_d <= amrex::Real(1.0))) {
1181  amrex::Abort("erf.beta_d must lie in [0, 1]; got " + std::to_string(beta_d));
1182  }
1183 
1184  // Spatially varying beta_s on the w-faces (implicit substepping only):
1185  // beta_s = max(beta_s_min, min(beta_s_max, h_xi^2 + h_eta^2))
1186  pp.queryAdd("use_variable_beta_s", use_variable_beta_s);
1187  pp.queryAdd("beta_s_min", beta_s_min);
1188  pp.queryAdd("beta_s_max", beta_s_max);
1189  if (use_variable_beta_s) {
1191  "erf.beta_s_min must be less than or equal to erf.beta_s_max");
1193  "erf.beta_s_min and erf.beta_s_max must lie in [-1, 1]");
1194  }
1195 
1196  // *******************************************************************************
1197  // Error check on deprecated input
1198  // *******************************************************************************
1199  int nvals_old = pp.countval("no_substepping");
1200  if (nvals_old > 0) {
1201  amrex::Error("The no_substepping flag is deprecated -- set substepping_type instead");
1202  }
1203 
1204  pp.queryAdd("ncorr", ncorr);
1205  // Wall distance on a terrain-fitted mesh (RANS): "poisson" (Tucker 2003
1206  // differential-equation distance) or "terrain_height" (height above the
1207  // local surface projected on its normal, no linear solve)
1208  pp.queryAdd("wall_dist_type", wall_dist_type);
1209  if (wall_dist_type != "poisson" && wall_dist_type != "terrain_height") {
1210  amrex::Error("erf.wall_dist_type must be poisson or terrain_height");
1211  }
1212  pp.queryAdd("poisson_abstol", poisson_abstol);
1213  pp.queryAdd("poisson_reltol", poisson_reltol);
1214  // Solver for the projection on a terrain-fitted mesh: FFT-preconditioned GMRES (default),
1215  // or amrex::MLTerrainPoisson with multigrid, alone or under GMRES
1216  pp.query_enum_case_insensitive("terrain_poisson_solver", terrain_poisson_solver);
1217  if (pp.contains("terrain_poisson_solver") &&
1218  (mesh_type != MeshType::VariableDz || terrain_type == TerrainType::EB)) {
1219  amrex::Print() << "WARNING: erf.terrain_poisson_solver is ignored: it applies only to the "
1220  << "projection on a terrain-fitted mesh (erf.terrain_type = StaticFittedMesh "
1221  << "or MovingFittedMesh)" << std::endl;
1222  }
1223 #ifdef AMREX_USE_FLOAT
1224  poisson_abstol = amrex::max(poisson_abstol,amrex::Real(1e-6));
1225  poisson_reltol = amrex::max(poisson_reltol,amrex::Real(1e-6));
1226 #endif
1227  for (int lev = 0; lev <= max_level; lev++) {
1228  if (anelastic[lev] != 0)
1229  {
1231  }
1232  }
1233 
1234  pp.queryAdd("force_stage1_single_substep", force_stage1_single_substep);
1235 
1236  // Include Coriolis forcing?
1237  pp.queryAdd("use_coriolis", use_coriolis);
1238  pp.queryAdd("variable_coriolis", variable_coriolis);
1239 
1240  // Include four stream radiation approximation
1241  pp.queryAdd("four_stream_radiation", four_stream_radiation);
1242 
1243  // flags for whether to apply other source terms in substep only
1244  pp.queryAdd("immersed_forcing_substep", immersed_forcing_substep); // apply immersed forcing source terms in substep only
1245  pp.queryAdd("forest_substep", forest_substep); // apply canopy-related source terms in substep only
1246 
1247  // Fixed-leaf-temperature canopy heat exchange
1248  pp.query("forest_biophysics", forest_biophysics);
1249  pp.query("forest_biophysics_heat", forest_biophysics_heat);
1250  pp.query("forest_leaf_theta_fixed", forest_leaf_theta_fixed);
1251 
1254  "forest_biophysics_heat requires forest_biophysics = true");
1258  "forest_biophysics_heat requires a positive forest_leaf_theta_fixed");
1261  "forest_leaf_theta_fixed requires forest_biophysics_heat = true");
1262 
1263  // Canopy terms of the k-eqn RANS model (erf.forest_canopy_*); the
1264  // checks that need the forest and the turbulence model are in
1265  // ERF::ReadParameters, once both are known
1267 
1268  // immersed forcing parameters
1269  pp.queryAdd("if_Cd_momentum", if_Cd_momentum);
1270  pp.queryAdd("if_Cd_scalar", if_Cd_scalar);
1271  pp.queryAdd("if_implicit_drag", if_implicit_drag); // flag for implicit vs. explicit drag formulation
1272  pp.queryAdd("if_z0", if_z0);
1273  pp.queryAdd("if_surf_temp_flux", if_surf_temp_flux);
1274  pp.queryAdd("if_init_surf_temp", if_init_surf_temp);
1275 
1276  pp.queryAdd("if_surf_heating_rate", if_surf_heating_rate);
1277 
1278  // Modify rate to be in units of K / s rather than K / hr
1279  if_surf_heating_rate /= amrex::Real(3600.0); // [K/s]
1280 
1281  pp.queryAdd("if_Olen", if_Olen_in);
1282  pp.queryAdd("if_use_most",if_use_most);
1283  pp.queryAdd("if_snap_partial_cells",if_snap_partial_cells);
1284  // The snapped staircase puts full-strength forcing on every wall face,
1285  // whose explicit relaxation rate (Cd / dx per substep) sits at the
1286  // stability limit and fails where faces stack at rims and corners; the
1287  // point-implicit form holds at any rate, so the snap uses it.
1289  amrex::Print() << "erf.if_snap_partial_cells: using the point-implicit drag (erf.if_implicit_drag = true)\n";
1290  if_implicit_drag = true;
1291  }
1292  pp.queryAdd("if_stability_correction",if_stability_correction);
1293 
1294  // Wall law of the terrain immersed forcing (erf-model/ERF#4134): "legacy" (the default)
1295  // relaxes the top partial cell toward the log law at fixed 0.5/1.5 dz;
1296  // "fraction_stress" applies the wall stress of ERF_ImmersedWallCell.H in the wall cell
1297  // and closes the wall face to diffusion (form 7 of the kynema-sgf immersed terrain)
1298  std::string if_wall_form_in = "legacy";
1299  pp.queryAdd("if_wall_form", if_wall_form_in);
1300  if (if_wall_form_in == "fraction_stress") {
1301  if_fraction_stress = true;
1302  } else if (if_wall_form_in != "legacy") {
1303  amrex::Abort("erf.if_wall_form must be legacy or fraction_stress, not " + if_wall_form_in);
1304  }
1305  // Spacing of the face above the wall cell (fraction_stress only): "log" (default) gives
1306  // that face the relative error of flat ground's first interior face for a log profile,
1307  // "physical" the centroid spacing, "grid" the cell height (ib_wall::face_above_factor)
1308  // (the keys below are accepted at their default values with the legacy law, so one deck
1309  // can run both laws; any other value belongs to fraction_stress)
1310  std::string if_wall_face_spacing_in = "log";
1311  pp.queryAdd("if_wall_face_spacing", if_wall_face_spacing_in);
1312  if (if_wall_face_spacing_in != "log" && !if_fraction_stress) {
1313  amrex::Abort("erf.if_wall_face_spacing belongs to erf.if_wall_form = fraction_stress");
1314  }
1315  if (if_wall_face_spacing_in == "grid") { if_wall_face_spacing = 0; }
1316  else if (if_wall_face_spacing_in == "physical") { if_wall_face_spacing = 1; }
1317  else if (if_wall_face_spacing_in == "log") { if_wall_face_spacing = 2; }
1318  else { amrex::Abort("erf.if_wall_face_spacing must be log, physical or grid"); }
1319  // Wall value of the k-eqn TKE in the fraction-stress wall cell, (u*^3 + kappa B d1)^(2/3)
1320  // / Cmu0^2 (the value erf.dirichlet_k holds over flat ground): with a time factor of 1
1321  // (the default) the wall cell is held at it after every stage and in the implicit TKE
1322  // solve, as flat ground is; a larger factor relaxes toward it as a source over that many
1323  // steps (the kynema-sgf form)
1324  pp.queryAdd("if_wall_tke", if_wall_tke);
1325  pp.queryAdd("if_wall_tke_time_factor", if_wall_tke_time_factor);
1327  amrex::Abort("erf.if_wall_tke = true and erf.if_wall_tke_time_factor != 1 belong to erf.if_wall_form = fraction_stress");
1328  }
1329  if (!(if_wall_tke_time_factor >= one)) {
1330  amrex::Abort("erf.if_wall_tke_time_factor must be >= 1 (steps over which the wall TKE is relaxed)");
1331  }
1332  // Partial wall cells of the fraction-stress law dissipate TKE with the length scale of flat
1333  // ground's first cell (kynema-sgf KLAxell.flat_wall_dissipation); on by default with it.
1334  // query, not queryAdd: the default depends on erf.if_wall_form, so storing it would make a
1335  // later init_params in the same process (the unit tests) see it as given (cf. #4940)
1337  pp.query("if_flat_wall_dissipation", if_flat_wall_dissipation);
1339  amrex::Abort("erf.if_flat_wall_dissipation = true belongs to erf.if_wall_form = fraction_stress");
1340  }
1341  if (if_fraction_stress) {
1342  if (terrain_type != TerrainType::ImmersedForcing) {
1343  amrex::Abort("erf.if_wall_form = fraction_stress needs erf.terrain_type = ImmersedForcing");
1344  }
1345  if (buildings_type == BuildingsType::ImmersedForcing) {
1346  amrex::Abort("erf.if_wall_form = fraction_stress is not available with erf.buildings_type = ImmersedForcing");
1347  }
1348  if (!if_use_most) {
1349  amrex::Abort("erf.if_wall_form = fraction_stress is a wall law: it needs erf.if_use_most = true");
1350  }
1351  if (mesh_type != MeshType::ConstantDz) {
1352  amrex::Abort("erf.if_wall_form = fraction_stress needs a constant-dz mesh");
1353  }
1354  // The wall heat flux and the wall TKE are written by the slow scalar source; the
1355  // compressible fast substep (erf.immersed_forcing_substep) does not carry them
1357  amrex::Abort("erf.if_wall_form = fraction_stress runs with the anelastic model (erf.anelastic = 1 on "
1358  "every level); it does not support erf.immersed_forcing_substep = true");
1359  }
1360  // One surface condition (heat flux, surface temperature - optionally changing at
1361  // erf.if_surf_heating_rate - or Obukhov length; none is neutral, checked below); the
1362  // MOST stability functions always apply, as on the flat surface layer, so
1363  // erf.if_stability_correction (a legacy switch) must not be set
1365  amrex::Abort("erf.if_surf_heating_rate needs erf.if_init_surf_temp");
1366  }
1368  amrex::Abort("erf.if_wall_form = fraction_stress always applies the stability functions; "
1369  "erf.if_stability_correction is for the legacy wall law");
1370  }
1371  }
1372  pp.queryAdd("if_ws_floor",if_ws_floor);
1373  pp.queryAdd("if_damp_alpha",if_damp_alpha);
1374  // Opt-in WRF-style bounds on the wall law (erf-model/ERF#4016): the wind floor behind the
1375  // friction velocity of its stability estimate, and the cap on psi_m in the momentum law as
1376  // a fraction of ln(z/z0); 0 and 1 (the defaults) turn them off
1377  pp.queryAdd("if_stability_wind_floor",if_stability_wind_floor);
1378  pp.queryAdd("if_psi_cap_factor",if_psi_cap_factor);
1379  if (!(if_stability_wind_floor >= zero)) {
1380  amrex::Abort("erf.if_stability_wind_floor must be >= 0 [m/s] (0 leaves the wind as it is)");
1381  }
1382  if (!(if_psi_cap_factor > zero && if_psi_cap_factor <= one)) {
1383  amrex::Abort("erf.if_psi_cap_factor must be in (0, 1] (1 caps psi at ln(z/z0))");
1384  }
1385  // The cell average down over immersed-forcing levels (erf-model/ERF#4918): the plain
1386  // average (the default), or one weighted by the fluid mass of the fine cells
1387  pp.queryAdd("if_average_down", if_average_down);
1388  if (if_average_down != "plain" && if_average_down != "fluid_mass") {
1389  amrex::Abort("erf.if_average_down must be plain or fluid_mass");
1390  }
1391  // (queryAdd puts the default into the table, so the test is on the value, not on contains)
1392  if (if_average_down == "fluid_mass" &&
1393  terrain_type != TerrainType::ImmersedForcing && buildings_type != BuildingsType::ImmersedForcing)
1394  {
1395  amrex::Abort("erf.if_average_down = fluid_mass needs erf.terrain_type = ImmersedForcing "
1396  "or erf.buildings_type = ImmersedForcing");
1397  }
1398  // Warn at start-up where a lateral coarse/fine boundary crosses the immersed surface so
1399  // that the levels disagree: spread of the fine solid fractions under a coarse edge cell
1400  // at least this (0 turns the check off)
1401  pp.queryAdd("if_cf_mismatch_warning", if_cf_mismatch_warning);
1403  amrex::Abort("erf.if_cf_mismatch_warning must be in [0, 1] (a spread of solid fractions; 0 turns it off)");
1404  }
1405  // Log-law share of the wall coarse face's flux among its fine sub-faces at the lateral
1406  // coarse/fine faces (erf-model/ERF#4920): the immersed surface or a surface-layer bottom
1407  // (checked in check_params); constant dz, not EB terrain. The roughness length defaults
1408  // to erf.if_z0 with immersed forcing and to the inputs' erf.most.z0 or erf.zlo.most.z0
1409  // (0.1 m when neither is given) otherwise.
1410  pp.queryAdd("cf_loglaw_fill", cf_loglaw_fill);
1411  const bool z0_given = pp.query("cf_loglaw_z0", cf_loglaw_z0);
1412  if (z0_given && !cf_loglaw_fill) {
1413  amrex::Abort("erf.cf_loglaw_z0 belongs to erf.cf_loglaw_fill = true");
1414  }
1415  if (cf_loglaw_fill) {
1416  if (mesh_type != MeshType::ConstantDz) {
1417  amrex::Abort("erf.cf_loglaw_fill needs a constant-dz mesh");
1418  }
1419  if (terrain_type == TerrainType::EB) {
1420  amrex::Abort("erf.cf_loglaw_fill is not implemented for erf.terrain_type = EB "
1421  "(its wall is not the bottom of the domain)");
1422  }
1423  if (!z0_given) {
1424  if (terrain_type == TerrainType::ImmersedForcing || buildings_type == BuildingsType::ImmersedForcing) {
1425  cf_loglaw_z0 = if_z0;
1426  } else {
1427  // the roughness given in the inputs for the bottom surface layer
1428  // (erf.most.z0, or erf.zlo.most.z0 when the faces are set one by one); a
1429  // roughness a land model supplies later is not seen here
1430  cf_loglaw_z0 = amrex::Real(0.1);
1431  pp.query("most.z0", cf_loglaw_z0);
1432  pp.query("zlo.most.z0", cf_loglaw_z0);
1433  }
1434  }
1435  if (!(cf_loglaw_z0 > zero)) {
1436  amrex::Abort("erf.cf_loglaw_z0 must be > 0 [m] (the roughness length of the log-law coarse/fine fill)");
1437  }
1438  }
1439  // Say so when a bound is set and the wall law's stability estimate is in use
1440  if ((terrain_type == TerrainType::ImmersedForcing || buildings_type == BuildingsType::ImmersedForcing) &&
1441  (if_use_most || if_surf_temp_flux != amrex::Real(1e-8) || if_Olen_in != amrex::Real(1e-8)) &&
1442  (if_psi_cap_factor < one || if_stability_wind_floor > zero))
1443  {
1444  amrex::Print() << "Immersed wall law: erf.if_psi_cap_factor = " << if_psi_cap_factor
1445  << ", erf.if_stability_wind_floor = " << if_stability_wind_floor
1446  << " m/s (WRF-style bounds; the defaults 1 and 0 turn them off)\n";
1447  }
1448 
1449  if ((if_init_surf_temp > zero && if_surf_temp_flux != amrex::Real(1e-8)) ||
1450  (if_init_surf_temp > zero && if_Olen_in != amrex::Real(1e-8)) ||
1451  (if_Olen_in != amrex::Real(1e-8) && if_surf_temp_flux != amrex::Real(1e-8)))
1452  {
1453  amrex::Error("Can only specify one of init_surf_temp, surf_temp_flux, or Olen");
1454  }
1455  if (if_Olen_in == zero &&
1456  (terrain_type == TerrainType::ImmersedForcing || buildings_type == BuildingsType::ImmersedForcing)) {
1457  amrex::Abort("erf.if_Olen = 0 is not an Obukhov length: give a nonzero length [m] (a large |L| is near neutral)");
1458  }
1459 
1460  // The immersed forcing's "almost fluid" threshold (erf-model/ERF#4226). It is recorded
1461  // under eb2.small_volfrac here, in ReadParameters, before ERF::initializeEB runs, so the
1462  // EB build (which covers cells below it), the blanking and the forcing kernels all use
1463  // the same value, and a deck without the key gets 0.005 rather than AMReX's 1e-14.
1464  if (terrain_type == TerrainType::ImmersedForcing || buildings_type == BuildingsType::ImmersedForcing) {
1465  amrex::ParmParse pp_eb2("eb2");
1466  pp_eb2.queryAdd("small_volfrac", if_small_volfrac);
1467  if (!(if_small_volfrac >= zero && if_small_volfrac < one)) {
1468  amrex::Abort("eb2.small_volfrac must be in [0, 1) with immersed forcing");
1469  }
1470  }
1471 
1472  // Implicit drag of the immersed forcing inside the anelastic projection (erf-model/ERF#4919
1473  // for terrain, #4887 for buildings): each face momentum becomes (m* - grad phi) / (1 + dt rate),
1474  // with rate the drag rate of the source term on that face, and the solid is not frozen
1475  // afterwards, so the projected field stays divergence free in the solid too
1476  pp.queryAdd("if_implicit_projection", if_implicit_projection);
1477  if (if_implicit_projection) {
1478  const bool if_terrain = (terrain_type == TerrainType::ImmersedForcing);
1479  const bool if_buildings = (buildings_type == BuildingsType::ImmersedForcing);
1480  if (!if_terrain && !if_buildings) {
1481  amrex::Abort("erf.if_implicit_projection needs erf.terrain_type = ImmersedForcing or "
1482  "erf.buildings_type = ImmersedForcing");
1483  }
1484  if (if_terrain && if_buildings) {
1485  amrex::Abort("erf.if_implicit_projection is not implemented for erf.terrain_type = ImmersedForcing "
1486  "together with erf.buildings_type = ImmersedForcing");
1487  }
1488  if (mesh_type != MeshType::ConstantDz) {
1489  amrex::Abort("erf.if_implicit_projection needs a constant-dz mesh");
1490  }
1491  for (int lev = 0; lev <= max_level; ++lev) {
1492  if (!anelastic[lev]) {
1493  amrex::Abort("erf.if_implicit_projection needs erf.anelastic = 1 on every level");
1494  }
1495  }
1496 #ifndef ERF_USE_FFT
1497  amrex::Abort("erf.if_implicit_projection needs a build with FFT (its GMRES solve is FFT-preconditioned)");
1498 #endif
1499  }
1500 
1501  // Flag to do MOST rotations with terrain
1502  pp.queryAdd("use_rotate_surface_flux",use_rotate_surface_flux);
1504  AMREX_ASSERT_WITH_MESSAGE(terrain_type != TerrainType::None,"MOST stress rotations are only valid with terrain!");
1505  }
1506 
1507  // Which external forcings?
1508  abl_driver_type = ABLDriverType::None; // Default: no ABL driver for simulating classical fluid dynamics problems
1509  pp.query_enum_case_insensitive("abl_driver_type",abl_driver_type);
1510  pp.queryAdd("const_massflux_u", const_massflux_u);
1511  pp.queryAdd("const_massflux_v", const_massflux_v);
1512  pp.queryAdd("const_massflux_tau", const_massflux_tau);
1513  // The control divides by tau; tau <= 0 gives no source or one that drives the flow
1514  // away from the target
1515  if (!(const_massflux_tau > amrex::Real(0))) {
1516  amrex::Abort("erf.const_massflux_tau must be > 0 (got " +
1517  std::to_string(const_massflux_tau) + ")");
1518  }
1519  pp.queryAdd("const_massflux_layer_lo", const_massflux_layer_lo);
1520  pp.queryAdd("const_massflux_layer_hi", const_massflux_layer_hi);
1521 
1522  // Which type of inflow turbulent generation
1523  // Real-data initialization uses parent controls unless explicitly overridden.
1524  perturbation_auto = (init_type == InitType::WRFInput || init_type == InitType::Metgrid);
1525  pp.queryAdd("perturbation_auto", perturbation_auto);
1526  pp.queryAdd("perturbation_auto_period", perturbation_auto_period);
1527  pp.queryAdd("perturbation_auto_pbl_fraction", perturbation_auto_pbl_fraction);
1528  if (perturbation_auto &&
1529  (!(perturbation_auto_period > zero) || !std::isfinite(perturbation_auto_period) ||
1531  amrex::Abort("Automatic perturbations require perturbation_auto_period > 0 and "
1532  "0 < perturbation_auto_pbl_fraction <= 1");
1533  }
1534  pert_type.resize(max_level+1);
1535  for (int lev = 0; lev <= max_level; ++lev) {
1536  pert_type[lev] = PerturbationType::None; // Default
1538  pp, "perturbation_type", pert_type[lev], lev, max_level);
1539  }
1540 
1541  amrex::Vector<amrex::Real> abl_pressure_grad_in = {zero, zero, zero};
1542  pp.queryarr("abl_pressure_grad",abl_pressure_grad_in);
1543  for(int i = 0; i < AMREX_SPACEDIM; ++i) abl_pressure_grad[i] = abl_pressure_grad_in[i];
1544 
1545  amrex::Vector<amrex::Real> abl_geo_forcing_in = {zero, zero, zero};
1546  if(pp.queryarr("abl_geo_forcing",abl_geo_forcing_in)) {
1547  amrex::Print() << "Specified abl_geo_forcing: (";
1548  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
1549  abl_geo_forcing[i] = abl_geo_forcing_in[i];
1550  amrex::Print() << abl_geo_forcing[i] << " ";
1551  }
1552  amrex::Print() << ")" << std::endl;
1553  }
1554 
1555  if (use_coriolis)
1556  {
1558  }
1559 
1560  pp.queryAdd("add_custom_rhotheta_forcing", custom_rhotheta_forcing);
1561  pp.queryAdd("add_custom_moisture_forcing", custom_moisture_forcing);
1562  pp.queryAdd("add_custom_w_subsidence", custom_w_subsidence);
1563  pp.queryAdd("add_do_theta_advection", do_theta_advection); // If true, apply custom subsidence to (rho*theta) when add_custom_w_subsidence is used
1564  pp.queryAdd("add_do_mom_advection", do_mom_advection); // If true, apply custom subsidence to momentum when add_custom_w_subsidence is used
1565  pp.queryAdd("add_custom_geostrophic_profile", custom_geostrophic_profile);
1566  pp.queryAdd("custom_forcing_uses_primitive_vars", custom_forcing_prim_vars);
1567  pp.queryAdd("spatial_rhotheta_forcing", spatial_rhotheta_forcing);
1568  pp.queryAdd("spatial_moisture_forcing", spatial_moisture_forcing);
1569 
1570  pp.queryAdd("nudging_from_input_sounding", nudging_from_input_sounding);
1571 
1572  // Nudging towards observations at stations; the stations and the
1573  // parameters are read by the ObsNudging class, under erf.obs_nudging
1574  pp.queryAdd("nudging_from_observations", nudging_from_observations);
1575  if (nudging_from_observations && terrain_type == TerrainType::EB) {
1576  amrex::Abort("erf.nudging_from_observations does not support erf.terrain_type = EB; "
1577  "use a terrain-fitted mesh or immersed forcing");
1578  }
1579 
1580  int nudging_u_z1_set = pp.queryAdd("nudging_u_z1", nudging_u_z1);
1581  int nudging_u_z2_set = pp.queryAdd("nudging_u_z2", nudging_u_z2);
1582  pp.queryAdd("nudging_t_z1", nudging_t_z1);
1583  pp.queryAdd("nudging_t_z2", nudging_t_z2);
1584  pp.queryAdd("nudging_q_z1", nudging_q_z1);
1585  pp.queryAdd("nudging_q_z2", nudging_q_z2);
1586 
1588  "nudging_u_z1 must be less than or equal to nudging_u_z2");
1590  "nudging_t_z1 must be less than or equal to nudging_t_z2");
1592  "nudging_q_z1 must be less than or equal to nudging_q_z2");
1593 
1594  pp.queryAdd("nudging_u", nudging_u);
1595  pp.queryAdd("nudging_t", nudging_t);
1596  pp.queryAdd("nudging_q", nudging_q);
1597 
1598  pp.queryAdd("large_scale_forcing", large_scale_forcing);
1599 
1601  if (!nudging_u) {
1602  amrex::Print() << "WARNING: erf.nudging_u = false has no effect when erf.large_scale_forcing "
1603  "= true; momentum nudging is then controlled solely by large_scale_forcing.\n";
1604  }
1605  if (nudging_u_z1_set || nudging_u_z2_set) {
1606  amrex::Print() << "WARNING: erf.nudging_u_z1/erf.nudging_u_z2 are ignored when "
1607  "erf.large_scale_forcing = true; momentum nudging is then applied "
1608  "at all heights.\n";
1609  }
1610  }
1611 
1614  "Should not have both abl_geo_wind_table and custom_geostrophic_profile set.");
1615 
1616  pp.queryAdd("Ave_Plane", ave_plane);
1617 
1618  // Use numerical diffusion?
1619  pp.queryAdd("num_diff_coeff",num_diff_coeff);
1621  "Numerical diffusion coefficient must be between 0 & one");
1622  use_num_diff = (num_diff_coeff > 0);
1623  if (use_num_diff) {
1624  amrex::Print() << "6th-order numerical diffusion turned on with coefficient = "
1625  << num_diff_coeff << std::endl;
1626  num_diff_coeff *= amrex::Math::powi<-6>(two);
1627  }
1628 
1629  advChoice.init_params(pp_prefix);
1630  diffChoice.init_params(pp_prefix);
1631  dampingChoice.init_params(pp_prefix);
1632  spongeChoice.init_params(pp_prefix);
1633  ebChoice.init_params(pp_prefix);
1634 
1635  turbChoice.resize(max_level+1);
1636  for (int lev = 0; lev <= max_level; lev++) {
1637  turbChoice[lev].init_params(lev,max_level,pp_prefix);
1638  }
1639 
1640  if (perturbation_auto) {
1641  // Automatic forcing has a parent and a three-dimensional LES closure.
1642  // A horizontal Smagorinsky closure paired with a PBL scheme is mesoscale.
1643  for (int lev = 0; lev <= max_level; ++lev) {
1644  const auto& tc = turbChoice[lev];
1645  if (lev == 0 || tc.les_type == LESType::None || tc.smag2d ||
1646  tc.pbl_type != PBLType::None) {
1648  }
1649  }
1650  }
1651 
1652  // WRF's Smagorinsky-2D slope limiter divides K_h by the terrain slope factor of the
1653  // mesh, which is 1 everywhere without a terrain-fitted mesh; and the EB closure
1654  // (ComputeTurbulentViscosityLES_EB) applies neither limit.
1655  bool smag2d_requested = false;
1656  bool smag2d_somewhere = false;
1657  for (int lev = 0; lev <= max_level; lev++) {
1658  smag2d_requested = smag2d_requested || turbChoice[lev].smag2d_limits_requested;
1659  smag2d_somewhere = smag2d_somewhere || turbChoice[lev].smag2d;
1660  }
1661  if (smag2d_requested && !smag2d_somewhere) {
1662  amrex::Error("erf.smag2d_slope_limiter and erf.smag2d_kh_cap apply only to "
1663  "erf.les_type = Smagorinsky2D, which no level uses");
1664  }
1665  for (int lev = 0; lev <= max_level; lev++) {
1666  const bool fitted = (terrain_type == TerrainType::StaticFittedMesh ||
1667  terrain_type == TerrainType::MovingFittedMesh);
1668  if (turbChoice[lev].smag2d_slope_limiter && !fitted) {
1669  amrex::Error("erf.smag2d_slope_limiter requires erf.terrain_type = StaticFittedMesh "
1670  "or MovingFittedMesh");
1671  }
1672  if (turbChoice[lev].smag2d_kh_cap > zero && terrain_type == TerrainType::EB) {
1673  amrex::Error("erf.smag2d_kh_cap is not supported with erf.terrain_type = EB");
1674  }
1675  }
1676 
1677  // erf.radiation_model = TwoStream selects the two-stream model; its
1678  // erf.radiation.* sub-options are read only then.
1679  radChoice.init_params(rad_type == RadiationType::TwoStream, pp_prefix);
1680  if (rad_type == RadiationType::RRTMGP) {
1681  rrtmgpSolarChoice.read(pp_prefix);
1682  }
1684  if (topographicChoice.active()) {
1685  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(terrain_type == TerrainType::StaticFittedMesh,
1686  "Topographic radiation requires erf.terrain_type = StaticFittedMesh");
1687  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(rad_type == RadiationType::RRTMGP,
1688  "Topographic radiation currently requires erf.radiation_model = RRTMGP");
1689  }
1690 
1691  // Noah-MP integrates on the downwelling shortwave, downwelling longwave and solar
1692  // zenith angle a radiation model writes into it. Only RRTMGP and TwoStream register
1693  // those outputs with the land model (rad_feeds_lsm, ERF::init_stuff), so under any
1694  // other choice they are never written and Noah-MP runs with no radiative forcing at
1695  // all -- the inputs it reads fall back to zero. That is a legitimate thing to want
1696  // in a test, and rarely what anyone running a land model means, so say it at
1697  // start-up.
1698  if (lsm_type == LandSurfaceType::NOAHMP && !rad_feeds_lsm()) {
1699  amrex::Print() << "WARNING: erf.land_surface_model = NOAHMP with erf.radiation_model = "
1700  << amrex::getEnumNameString(rad_type)
1701  << ": only RRTMGP and TwoStream supply the downwelling shortwave, "
1702  "downwelling longwave and solar zenith angle Noah-MP needs. Noah-MP "
1703  "will run with no radiative forcing (zero SWDOWN, GLW and COSZEN).\n";
1704  }
1705 
1706  vert_implicit_fac.resize(max_level+1);
1707  for (int lev = 0; lev <= max_level; lev++) {
1708  vert_implicit_fac[lev].resize(3);
1709  vert_implicit_fac[lev][0] = one;
1710  vert_implicit_fac[lev][1] = one;
1711  vert_implicit_fac[lev][2] = zero;
1712  }
1713 
1714  // YSU PBL: use consistent coriolis frequency
1715  for (int lev = 0; lev <= max_level; lev++) {
1716  if (turbChoice[lev].pbl_ysu_use_consistent_coriolis) {
1717  if (use_coriolis) {
1718  turbChoice[lev].pbl_ysu_coriolis_freq = coriolis_factor * sinphi;
1719  if (lev == 0) {
1720  amrex::Print() << "YSU PBL using ERF coriolis frequency: " << turbChoice[lev].pbl_ysu_coriolis_freq << std::endl;
1721  }
1722  } else {
1723  amrex::Error("YSU cannot use ERF coriolis frequency if not using coriolis");
1724  }
1725  }
1726  }
1727  // MRF
1728  for (int lev = 0; lev <= max_level; lev++) {
1729  if (turbChoice[lev].pbl_ysu_use_consistent_coriolis) {
1730  if (use_coriolis) {
1731  turbChoice[lev].pbl_ysu_coriolis_freq = coriolis_factor * sinphi;
1732  if (lev == 0) {
1733  amrex::Print() << "MRF PBL using ERF coriolis frequency: " << turbChoice[lev].pbl_ysu_coriolis_freq << std::endl;
1734  }
1735  } else {
1736  amrex::Error("MRF cannot use ERF coriolis frequency if not using coriolis");
1737  }
1738  }
1739  }
1740 
1741  // What's the strength of the bdy nudging?
1742  pp.queryAdd("bdy_nudge_factor",bdy_nudge_factor);
1743 
1744  // Optionally use the dry-air density reconstructed from wrfbdy.
1745  pp.queryAdd("use_wrf_bdy_density", use_wrf_bdy_density);
1746 
1747  // Optionally ingest cloud water and cloud ice from wrfinput/wrfbdy.
1748  pp.queryAdd("use_wrf_bdy_qc_qi", use_wrf_bdy_qc_qi);
1749 
1750  if (!use_real_bcs || init_type != InitType::WRFInput) {
1751  use_wrf_bdy_density = false;
1752  }
1753 
1754  pp.queryAdd("bdy_rho_nudge_factor", bdy_rho_nudge_factor);
1755 
1756  // Which approach to nudging the moist variables in the boundary region?
1757  pp.queryAdd("bdy_moist_nudge_type",bdy_moist_nudge_type);
1758  if (bdy_moist_nudge_type < 0 || bdy_moist_nudge_type > 3) {
1759  amrex::Error("erf.bdy_moist_nudge_type must be one of 0, 1, 2, or 3");
1760  }
1761  if (bdy_moist_nudge_type == 3 && !use_wrf_bdy_qc_qi) {
1762  amrex::Error("erf.bdy_moist_nudge_type = 3 requires erf.use_wrf_bdy_qc_qi = true");
1763  }
1764  if (use_wrf_bdy_qc_qi) {
1766  amrex::Error("erf.use_wrf_bdy_qc_qi requires an active moisture model");
1767  }
1768  if (!use_real_bcs || init_type != InitType::WRFInput) {
1769  amrex::Error("erf.use_wrf_bdy_qc_qi requires WRFInput real boundary conditions");
1770  }
1773  amrex::Error("erf.use_wrf_bdy_qc_qi requires active qv and qc component indices");
1774  }
1775  const int optional_moisture_comps[] = {moisture_indices.qi,
1779  for (const int comp : optional_moisture_comps) {
1780  if (comp != -1 && (comp < RhoQ1_comp || comp > RhoQ11_comp)) {
1781  amrex::Error("erf.use_wrf_bdy_qc_qi found an invalid active moisture component index");
1782  }
1783  }
1784  }
1785 
1786  // Are me transporting the scalar component?
1787  pp.queryAdd("transport_scalar",transport_scalar);
1788 
1789  for (int lev = 0; lev <= max_level; ++lev) {
1790  if (turbChoice[lev].uses_eamxx_shoc()) {
1791  use_eamxx_shoc = true;
1792  }
1793  if (turbChoice[lev].uses_native_shoc()) {
1794  use_native_shoc = true;
1796  }
1797  }
1798 
1799  // Set up the vertical implicit diffusion solve
1800  int n_impfac = pp.countval("vert_implicit_fac");
1801  AMREX_ALWAYS_ASSERT(n_impfac == 0 || n_impfac == 1 || n_impfac==3);
1802  if (n_impfac == 1) {
1803  amrex::Real fac_in;
1804  pp.get("vert_implicit_fac", fac_in);
1805  for (int lev = 0; lev <= max_level; lev++) {
1806  for (int i=0; i<3; ++i) {
1807  vert_implicit_fac[lev][i] = fac_in;
1808  }
1809  }
1810  } else if (n_impfac == 3) {
1811  for (int lev = 0; lev <= max_level; lev++) {
1812  pp.getarr("vert_implicit_fac", vert_implicit_fac[lev]);
1813  }
1814  }
1815 
1816  // Record whether the user explicitly requested these
1817  const bool user_set_imp_thermal = pp.contains("implicit_thermal_diffusion");
1818  const bool user_set_imp_moisture = pp.contains("implicit_moisture_diffusion");
1819  const bool user_set_imp_ke = pp.contains("implicit_ke_diffusion");
1820  const bool user_set_imp_momentum = pp.contains("implicit_momentum_diffusion");
1821 
1822  // If true (default), include implicit contributions to vertical thermal diffusion
1823  pp.queryAdd("implicit_thermal_diffusion", implicit_thermal_diffusion);
1824 
1825  // If true (default), include implicit contributions to vertical moisture diffusion
1826  pp.queryAdd("implicit_moisture_diffusion", implicit_moisture_diffusion);
1827 
1828  // If true (default), include implicit contributions to vertical KE diffusion
1829  pp.queryAdd("implicit_ke_diffusion", implicit_ke_diffusion);
1830 
1831  // If true (default), include implicit contributions in tau13, tau23,
1832  pp.queryAdd("implicit_momentum_diffusion", implicit_momentum_diffusion);
1833 
1834  // If true (default false), also solve the compact terrain-metric part of the vertical
1835  // diffusion, K_h M d2/dz2 (ERF_TerrainImplicitMetric.H), implicitly (terrain-fitted
1836  // meshes only)
1837  pp.queryAdd("implicit_terrain_metric", implicit_terrain_metric);
1838 
1839  // The default is true (i.e. that it happens before the acoustic substepping).
1840  pp.queryAdd("implicit_before_substep", implicit_before_substep);
1841  for (int lev = 0; lev <= max_level; lev++) {
1843  amrex::Print() << "implicit_before_substep cannot be false without substepping; setting to true." << "\n";
1844  implicit_before_substep = true;
1845  }
1846  }
1847 
1848  // Handle shoc case -- SHOC owns whatever vertical diffusion the host does not
1849  if (uses_shoc_family()) {
1850  const bool host_owns_scalars = host_owns_vertical_scalar_diffusion();
1851  const bool host_owns_momentum = host_owns_vertical_momentum_diffusion();
1852  if (!host_owns_scalars &&
1853  ( (user_set_imp_thermal && implicit_thermal_diffusion ) ||
1854  (user_set_imp_moisture && implicit_moisture_diffusion) ||
1855  (user_set_imp_ke && implicit_ke_diffusion ) ) ) {
1856  amrex::Print() << "Ignoring erf.implicit_{thermal,moisture,ke}_diffusion = true; "
1857  << "SHOC owns vertical scalar diffusion." << "\n";
1858  }
1859  if (!host_owns_momentum && user_set_imp_momentum && implicit_momentum_diffusion) {
1860  amrex::Print() << "Ignoring erf.implicit_momentum_diffusion = true; "
1861  << "SHOC owns vertical momentum diffusion." << "\n";
1862  }
1863 
1864  implicit_thermal_diffusion = (implicit_thermal_diffusion && host_owns_scalars);
1866  implicit_ke_diffusion = (implicit_ke_diffusion && host_owns_scalars);
1867  implicit_momentum_diffusion = (implicit_momentum_diffusion && host_owns_momentum);
1868 
1869  // Make the resulting configuration visible in the run log
1870  if (!host_owns_scalars && !host_owns_momentum) {
1871  amrex::Print() << "Turning off vertical implicit solve for all components since SHOC owns diffusion." << "\n";
1872  } else {
1873  amrex::Print() << "SHOC hands vertical diffusion of"
1874  << (host_owns_scalars ? " scalars" : "")
1875  << (host_owns_momentum ? " momentum" : "")
1876  << " to the host; keeping the vertical implicit solve on (theta = "
1878  << ", moisture = " << implicit_moisture_diffusion
1879  << ", tke = " << implicit_ke_diffusion
1880  << ", momenta = " << implicit_momentum_diffusion << ")." << "\n";
1881  }
1882  } // uses_shoc_family
1883 
1884  // Do not allow implicit vertical diff if user turns it off
1885  bool do_vert_implicit = true;
1886  pp.queryAdd("vert_implicit", do_vert_implicit);
1887  if (!do_vert_implicit) {
1888  for (int lev = 0; lev <= max_level; lev++) {
1889  amrex::Print() << "Turning off native vertical implicit solve from vert_implicit flag at level " << lev << std::endl;
1890  vert_implicit_fac[lev][0] = zero;
1891  vert_implicit_fac[lev][1] = zero;
1892  vert_implicit_fac[lev][2] = zero;
1893  }
1894  }
1895 
1896  // The implicit vertical diffusion is only second order in an anelastic run when
1897  // the two stages are the midpoint method and the solve is done in the first stage
1898  // alone: S^* = S^n + (dt/2) F(S^*) and S^{n+1} = S^n + dt F(S^*) give
1899  // S^* = (S^n + S^{n+1})/2, i.e. the implicit midpoint rule. Solving again in the
1900  // second stage would reduce the pair to backward Euler, and with the RK2 (Heun)
1901  // stages there is no stage that plays the role of the midpoint at all.
1902  for (int lev = 0; lev <= max_level; lev++) {
1903  if (anelastic[lev]) {
1904  if (anelastic_type[lev] == AnelasticType::RK2) {
1905  amrex::Print() << "Turning off native vertical implicit solve flag because anelastic at level " << lev
1906  << " with RK2 scheme." << std::endl;
1907  vert_implicit_fac[lev][0] = zero;
1908  vert_implicit_fac[lev][1] = zero;
1909  vert_implicit_fac[lev][2] = zero;
1910  } else if (anelastic_type[lev] == AnelasticType::MidPoint) {
1911  if (do_vert_implicit && vert_implicit_fac[lev][0] != one) {
1912  amrex::Print() << "Forcing implicit factor 1 in first stage of MidPoint to ensure second-order accuracy." << std::endl;
1913  vert_implicit_fac[lev][0] = one;
1914  }
1915  if (vert_implicit_fac[lev][1] > zero) {
1916  amrex::Print() << "Turning off the second-stage vertical implicit solve at level " << lev
1917  << " because anelastic with MidPoint solves in the first stage only."
1918  << std::endl;
1919  }
1920  // The anelastic integrator only takes two stages, so [2] is never used
1921  vert_implicit_fac[lev][1] = zero;
1922  vert_implicit_fac[lev][2] = zero;
1923  }
1924  }
1925  }
1926 
1927  // Do not allow implicit vertical diff with EB
1928  if (terrain_type == TerrainType::EB) {
1929  for (int lev = 0; lev <= max_level; lev++) {
1930  if (do_vert_implicit) {
1931  amrex::Print() << "Implicit diffusion is not supported with EB; turning off at level " << lev << "\n";
1932  vert_implicit_fac[lev][0] = zero;
1933  vert_implicit_fac[lev][1] = zero;
1934  vert_implicit_fac[lev][2] = zero;
1935  }
1936  }
1937  }
1938 
1939  // The EB diffusion path adds no buoyancy, shear or dissipation source for
1940  // a prognostic TKE closure
1941  if (terrain_type == TerrainType::EB) {
1942  for (int lev = 0; lev <= max_level; lev++) {
1943  if (turbChoice[lev].use_keqn) {
1944  amrex::Error("erf.terrain_type = EB cannot be used with erf.les_type = Deardorff "
1945  "or erf.rans_type = kEqn: the EB diffusion path has no TKE sources");
1946  }
1947  }
1948  }
1949 
1950  // Do not allow implicit vertical diff when all the components are false
1955  amrex::Print() << "Thermal, moisture, KE, and momentum diffusion are all turned off; turning off vertical implicit solve." << std::endl;
1956  for (int lev = 0; lev <= max_level; lev++) {
1957  vert_implicit_fac[lev][0] = zero;
1958  vert_implicit_fac[lev][1] = zero;
1959  vert_implicit_fac[lev][2] = zero;
1960  }
1961  }
1962 
1963  // Which type of multilevel coupling
1964  coupling_type = CouplingType::TwoWay; // Default
1965  pp.query_enum_case_insensitive("coupling_type",coupling_type);
1966 
1967  // Test for hybrid (compressible + anelastic) -- in this case we must use one-way coupling
1968  if (any_anelastic && any_compress) {
1969  coupling_type = CouplingType::OneWay;
1970  }
1971 
1972  // Which type of windfarm model
1973  windfarm_type = WindFarmType::None; // Default
1974  pp.query_enum_case_insensitive("windfarm_type",windfarm_type);
1975 
1977  pp.query_enum_case_insensitive("windfarm_loc_type",windfarm_loc_type);
1978 
1979  pp.queryAdd("windfarm_loc_table", windfarm_loc_table);
1980  pp.queryAdd("windfarm_spec_table", windfarm_spec_table);
1981  pp.queryAdd("windfarm_blade_table", windfarm_blade_table);
1982  pp.queryAdd("windfarm_airfoil_tables", windfarm_airfoil_tables);
1983  pp.queryAdd("windfarm_spec_table_extra", windfarm_spec_table_extra);
1984 
1985  // Sampling distance upstream of the turbine to find the
1986  // incoming free stream velocity as a factor of the diameter of the
1987  // turbine. ie. the sampling distance will be this number multiplied
1988  // by the diameter of the turbine
1989  pp.queryAdd("sampling_distance_by_D", sampling_distance_by_D);
1990  pp.queryAdd("turb_disk_angle_from_x", turb_disk_angle);
1991 
1992  pp.queryAdd("windfarm_x_shift",windfarm_x_shift);
1993  pp.queryAdd("windfarm_y_shift",windfarm_y_shift);
1994  // Test if time averaged data is to be output
1995  pp.queryAdd("time_avg_vel",time_avg_vel);
1996 
1997  // Interval means and resolved turbulent moments for plotfile output
1998  pp.queryAdd("compute_mean_vars", compute_mean_vars);
1999  pp.queryAdd("mean_vars_reset_mode", mean_vars_reset_mode);
2000  pp.queryAdd("mean_vars_reset_time", mean_vars_reset_time);
2001 
2002  if (compute_mean_vars &&
2003  mean_vars_reset_mode != "plotfile" && mean_vars_reset_mode != "time") {
2004  amrex::Error("erf.mean_vars_reset_mode must be either 'plotfile' or 'time'");
2005  }
2006  if (compute_mean_vars && mean_vars_reset_mode == "time" &&
2008  amrex::Error("erf.mean_vars_reset_time must be non-negative when "
2009  "erf.mean_vars_reset_mode = 'time'");
2010  }
2011 
2012  pp.queryAdd("hindcast_lateral_forcing", hindcast_lateral_forcing);
2013 
2015  pp.queryAdd("hindcast_boundary_data_dir", hindcast_boundary_data_dir);
2016 
2017  if(hindcast_boundary_data_dir.empty()) {
2018  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_boundary_data_dir' for boundary data for lateral forcing");
2019  }
2020  pp.queryAdd("hindcast_data_interval_in_hrs", hindcast_data_interval_in_hrs);
2022  amrex::Error("ERROR: Input parameter 'erf.hindcast_data_interval_in_hrs' which is the time interval between the "
2023  "data files is either missing or set to less than zero");
2024  }
2025  pp.queryAdd("hindcast_lateral_sponge_strength", hindcast_lateral_sponge_strength);
2026  pp.queryAdd("hindcast_lateral_sponge_length", hindcast_lateral_sponge_length);
2027 
2028  pp.queryAdd("hindcast_zhi_sponge_length", hindcast_zhi_sponge_length);
2029  pp.queryAdd("hindcast_zhi_sponge_strength", hindcast_zhi_sponge_strength);
2030 
2031  pp.queryAdd("hindcast_zhi_sponge_damping", hindcast_zhi_sponge_damping);
2032 
2034  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_lateral_sponge_strength' or it is specified to be less than zero");
2035  }
2036 
2038  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_lateral_sponge_length' or it is specified to be less than zero");
2039  }
2040 
2042  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_zhi_sponge_length' or it is specified to be less than zero");
2043  }
2044 
2046  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_zhi_sponge_strength' or it is specified to be less than zero");
2047  }
2048  }
2049 
2050  pp.queryAdd("hindcast_surface_bcs", hindcast_surface_bcs);
2051  if(hindcast_surface_bcs) {
2052  pp.queryAdd("hindcast_surface_data_dir", hindcast_surface_data_dir);
2053  }
2054 
2055  pp.queryAdd("io_hurricane_eye_tracker", io_hurricane_eye_tracker);
2057  pp.queryAdd("hurricane_eye_latitude", hurricane_eye_latitude);
2058  pp.queryAdd("hurricane_eye_longitude", hurricane_eye_longitude);
2060  amrex::Error("ERROR: You are using 'erf.io_hurricane_eye_tracker' to write out the files that track the eye of the hurricane"
2061  " but have not provided the initial location of the eye of the hurricane to be tracked. There has to be two"
2062  " options in the inputs - erf.hurricane_eye_latitude and erf.hurricane_eye_longitude that gives an approximate"
2063  " location of the eye in the initial condition");
2064  }
2065  }
2066 
2067  pp.queryAdd("is_init_for_ensemble", is_init_for_ensemble);
2068  if(is_init_for_ensemble) {
2069  amrex::ParmParse pp_ens("ensemble");
2070  pp_ens.queryAdd("n_members", n_ensemble);
2071  if(n_ensemble < 2) {
2072  amrex::Abort("You are using an ensemble run. There needs to be at least 2 ensemble members. "
2073  "erf.n_ensemble must be >=2.");
2074  }
2075  pp_ens.queryAdd("coarse_bckgnd_data_file", coarse_bckgnd_data_file);
2076  if (coarse_bckgnd_data_file.empty()) {
2077  amrex::Abort("coarse_bckgnd_data_file is empty! For ensmeble simulations, there needs to be a coarse background file which "
2078  "contains the data which will be interpolated onto the fine mesh. There has to a entry ensemble.coarse_bckgnd_data_file "
2079  "which contains the filename in the inputs.");
2080  }
2081  pp_ens.queryAdd("ens_pert_amplitude", ens_pert_amplitude);
2082  if(ens_pert_amplitude <= 0.0) {
2083  amrex::Error("You are using initialization for ensemble simulations using the inputs option "
2084  "ensemble.is_init_for_ensemble=true. In this case, there has to be an option "
2085  "ensemble.ens_pert_amplitude which is the value of the amplitude of the perturbation "
2086  "to be added to the background state and has to be greater than 0.0");
2087  }
2088  pp_ens.queryAdd("ens_pert_correlated_radius", ens_pert_correlated_radius);
2089  if(ens_pert_correlated_radius <= 0.0) {
2090  amrex::Error("You are using initialization with spatially correlated perturbations using the inputs option "
2091  "ensemble.is_init_for_ensemble=true. In this case, there has to be an option "
2092  "ensemble.ens_pert_correlated_radius which is the value of the the spatial correlation radius, "
2093  "and has to be greater than 0.0");
2094  }
2095  }
2096  }
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:72
constexpr amrex::Real R_d
Definition: ERF_Constants.H:49
bool anelastic_superdroplets_configuration_invalid(const MoistureType moisture_type, const bool any_anelastic) noexcept
Whether an anelastic SuperDroplets configuration is unsupported.
Definition: ERF_DataStruct.H:153
#define RhoQ11_comp
Definition: ERF_IndexDefines.H:76
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:66
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:38
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
void read_shoc_transport_modes(ShocTransportMode &transport_mode, ShocMomentumTransport &momentum_transport)
Read the native SHOC transport modes from the erf.shoc input namespace.
Definition: ERF_ShocTransportStruct.H:118
int query_one_or_per_level_enum_case_insensitive(const amrex::ParmParse &pp, const char *query_string, T &query_var, const int lev, const int maxlev)
Query a scalar or per-level enum input value using case-insensitive matching.
Definition: ERF_TurbStruct.H:85
AMREX_ASSERT_WITH_MESSAGE(wbar_cutoff_min > wbar_cutoff_max, "ERROR: wbar_cutoff_min < wbar_cutoff_max")
void init_params(std::string pp_prefix)
Read advection options from the input parameter database.
Definition: ERF_AdvStruct.H:25
void init_params(amrex::ParmParse &pp)
Definition: ERF_CanopyTurbStruct.H:32
void init_params(std::string pp_prefix)
Read damping options from the input parameter database.
Definition: ERF_DampingStruct.H:28
void init_params(std::string pp_prefix)
Read diffusion options from the input parameter database.
Definition: ERF_DiffStruct.H:30
void init_params(std::string pp_prefix)
Read embedded-boundary options from the input parameter database.
Definition: ERF_EBStruct.H:42
int qs
snow
Definition: ERF_DataStruct.H:266
int qr
rain
Definition: ERF_DataStruct.H:265
int qi
cloud ice
Definition: ERF_DataStruct.H:264
int qv
water vapor
Definition: ERF_DataStruct.H:262
int qc
cloud liquid water
Definition: ERF_DataStruct.H:263
int qg
graupel
Definition: ERF_DataStruct.H:267
static MoistureComponentIndices from_moisture_model(const MoistureType moisture_type)
Build the complete index map – conserved-state components and qmoist diagnostic slots – for a moistur...
Definition: ERF_DataStruct.H:357
void read(const std::string &prefix)
Definition: ERF_RadStruct.H:79
void init_params(bool two_stream_selected, std::string pp_prefix)
Definition: ERF_RadStruct.H:904
bool use_coupled_sst
Definition: ERF_DataStruct.H:2980
int sbm_moment_mode
Definition: ERF_DataStruct.H:2944
bool custom_geostrophic_profile
Whether a custom geostrophic wind profile is used.
Definition: ERF_DataStruct.H:2755
int n_ensemble
Number of ensemble members.
Definition: ERF_DataStruct.H:3063
bool implicit_before_substep
Whether implicit diffusion is applied before acoustic substepping.
Definition: ERF_DataStruct.H:2664
std::string hindcast_boundary_data_dir
Directory containing hindcast lateral boundary data.
Definition: ERF_DataStruct.H:3051
amrex::Real if_psi_cap_factor
Cap on psi_m in the immersed momentum wall law as a fraction of ln(z/z0) (1: none).
Definition: ERF_DataStruct.H:2722
amrex::Real ens_pert_correlated_radius
Spatial correlation radius for ensemble perturbations.
Definition: ERF_DataStruct.H:3064
amrex::Real forest_leaf_theta_fixed
Definition: ERF_DataStruct.H:3038
static InitType init_type
Initial-condition source selected for the run.
Definition: ERF_DataStruct.H:2583
bool io_hurricane_eye_tracker
Whether hurricane-eye tracking output is enabled.
Definition: ERF_DataStruct.H:3059
amrex::Real const_massflux_layer_lo
Lower height of the constant-mass-flux forcing layer.
Definition: ERF_DataStruct.H:3046
amrex::Real hindcast_zhi_sponge_length
Length of the upper hindcast sponge layer.
Definition: ERF_DataStruct.H:3056
TopographicShadingChoice topographicChoice
Definition: ERF_DataStruct.H:2624
amrex::Real gravity
Effective gravitational acceleration.
Definition: ERF_DataStruct.H:2736
bool variable_coriolis
Whether spatially varying Coriolis forcing is enabled.
Definition: ERF_DataStruct.H:2988
amrex::Real poisson_abstol
Absolute tolerance for the Poisson solve.
Definition: ERF_DataStruct.H:2676
amrex::Real if_Cd_momentum
Immersed-forcing drag coefficient for momentum.
Definition: ERF_DataStruct.H:2699
bool nudging_t
Definition: ERF_DataStruct.H:2776
amrex::Real if_Olen_in
Input Obukhov length for immersed-forcing MOST [m].
Definition: ERF_DataStruct.H:2710
bool forest_biophysics
Definition: ERF_DataStruct.H:3036
void build_coriolis_forcings_const_lat(std::string pp_prefix)
Build constant-latitude Coriolis forcing parameters.
Definition: ERF_DataStruct.H:2508
bool use_pert_pres_gradient
Whether momentum equations use perturbational pressure gradients.
Definition: ERF_DataStruct.H:2685
bool sbm_test_native_qc_write_fault
Definition: ERF_DataStruct.H:2946
amrex::Vector< int > project_initial_velocity
Per-level flag for projecting the initial velocity.
Definition: ERF_DataStruct.H:2632
int ave_plane
Averaging plane index used by diagnostics.
Definition: ERF_DataStruct.H:2990
bool nudging_q
Definition: ERF_DataStruct.H:2777
int ncorr
Number of projection correction iterations.
Definition: ERF_DataStruct.H:2669
amrex::Real if_small_volfrac
Immersed-forcing solid fraction below which a cell or face counts as fluid; read from eb2....
Definition: ERF_DataStruct.H:2723
static bool buildings_fc_factories
Use native face-centered EB factories for immersed buildings on a static fitted mesh.
Definition: ERF_DataStruct.H:2598
bool use_rotate_surface_flux
Whether MOST surface fluxes are rotated with terrain.
Definition: ERF_DataStruct.H:2784
bool moisture_tight_coupling
Whether moisture updates use tight coupling.
Definition: ERF_DataStruct.H:2995
bool compute_mean_vars
Definition: ERF_DataStruct.H:2801
amrex::Real test_mapfactor_amp
Amplitude of the spatially varying test map scale factors on level 0 (0: not used).
Definition: ERF_DataStruct.H:2681
amrex::Real beta_s
Time off-centering coefficient for forward weighting.
Definition: ERF_DataStruct.H:2641
bool interp_atmos_from_coarse
Definition: ERF_DataStruct.H:3030
bool forest_substep
Whether canopy source terms are applied only during substeps.
Definition: ERF_DataStruct.H:2696
bool use_wrf_bdy_density
Definition: ERF_DataStruct.H:3008
bool if_implicit_projection
Definition: ERF_DataStruct.H:2704
std::string mean_vars_reset_mode
Definition: ERF_DataStruct.H:2804
amrex::Real beta_s_max
Upper bound of the spatially varying beta_s.
Definition: ERF_DataStruct.H:2647
amrex::Real num_diff_coeff
Numerical diffusion coefficient after input scaling.
Definition: ERF_DataStruct.H:2939
amrex::Real if_wall_tke_time_factor
1 (the default) pins the wall cell after every stage and in the implicit TKE solve; a larger value re...
Definition: ERF_DataStruct.H:2717
amrex::Real bdy_nudge_factor
Boundary sponge nudging factor.
Definition: ERF_DataStruct.H:3005
int sbm_cloud_rain_split
Definition: ERF_DataStruct.H:2945
amrex::Real rdOcp
Ratio of dry-air gas constant to c_p.
Definition: ERF_DataStruct.H:2738
bool hindcast_lateral_forcing
Whether hindcast lateral forcing is enabled.
Definition: ERF_DataStruct.H:3053
bool do_theta_advection
Whether custom vertical subsidence is applied to rho-theta.
Definition: ERF_DataStruct.H:2753
amrex::Real nudging_q_z2
Definition: ERF_DataStruct.H:2773
static bool use_real_bcs
Whether real-data lateral boundary conditions are used.
Definition: ERF_DataStruct.H:2601
bool spatial_moisture_forcing
Whether spatially varying moisture forcing is enabled.
Definition: ERF_DataStruct.H:2758
RRTMGPSolarChoice rrtmgpSolarChoice
Definition: ERF_DataStruct.H:2623
amrex::Real nudging_u_z2
Definition: ERF_DataStruct.H:2769
static SoundingType sounding_type
Interpretation used for input sounding profiles.
Definition: ERF_DataStruct.H:2586
int bdy_moist_nudge_type
Moist-variable nudging strategy in boundary regions.
Definition: ERF_DataStruct.H:3017
amrex::Real poisson_reltol
Relative tolerance for the Poisson solve.
Definition: ERF_DataStruct.H:2677
UrbanType urban_type
Definition: ERF_DataStruct.H:2954
bool time_avg_vel
Whether time-averaged velocity fields are output.
Definition: ERF_DataStruct.H:2798
bool have_geo_wind_profile
Whether a geostrophic wind profile has been configured.
Definition: ERF_DataStruct.H:2986
RadChoice radChoice
Definition: ERF_DataStruct.H:2622
bool four_stream_radiation
Whether the four-stream radiation approximation is enabled.
Definition: ERF_DataStruct.H:2692
amrex::Real beta_s_min
Lower bound of the spatially varying beta_s.
Definition: ERF_DataStruct.H:2646
amrex::Real if_damp_alpha
Immersed-forcing damping coefficient.
Definition: ERF_DataStruct.H:2720
bool rebalance_wrf_input
Whether to rebalance states from wrfinput and wrfbdy data.
Definition: ERF_DataStruct.H:2733
bool wrfinput_zlevels_from_file
Definition: ERF_DataStruct.H:3027
amrex::Vector< amrex::Real > sbm_edges
Definition: ERF_DataStruct.H:2948
amrex::Real hindcast_data_interval_in_hrs
Time interval between hindcast data files [hr].
Definition: ERF_DataStruct.H:3052
amrex::Real const_massflux_layer_hi
Upper height of the constant-mass-flux forcing layer.
Definition: ERF_DataStruct.H:3047
std::string wall_dist_type
Definition: ERF_DataStruct.H:2670
bool avg_grid_faces_to_nodes
Definition: ERF_DataStruct.H:3020
std::string windfarm_spec_table_extra
Additional wind-farm turbine specification table path.
Definition: ERF_DataStruct.H:2997
amrex::Real if_ws_floor
Wind-speed floor [m/s] in the per-step change limit of the building wall-law forcing.
Definition: ERF_DataStruct.H:2719
bool is_init_for_ensemble
Whether initialization is for an ensemble simulation.
Definition: ERF_DataStruct.H:3062
bool uses_shoc_family() const noexcept
Query whether any SHOC-family PBL scheme is active.
Definition: ERF_DataStruct.H:2864
bool test_mapfactor
Whether to use test map scale factors.
Definition: ERF_DataStruct.H:2680
amrex::Real nudging_u_z1
Definition: ERF_DataStruct.H:2768
bool if_snap_partial_cells
Definition: ERF_DataStruct.H:2712
amrex::Vector< amrex::Real > sbm_pivots
Definition: ERF_DataStruct.H:2949
std::string coarse_bckgnd_data_file
Coarse background data file used for ensemble initialization.
Definition: ERF_DataStruct.H:3066
amrex::Real dz0
Initial vertical grid spacing for stretched-grid setup.
Definition: ERF_DataStruct.H:2742
amrex::Real ens_pert_amplitude
Amplitude of ensemble initialization perturbations.
Definition: ERF_DataStruct.H:3065
std::string windfarm_airfoil_tables
Wind-farm airfoil table paths.
Definition: ERF_DataStruct.H:2998
amrex::Real bdy_rho_nudge_factor
Definition: ERF_DataStruct.H:3014
amrex::Real nudging_q_z1
Definition: ERF_DataStruct.H:2772
bool transport_scalar
Whether the passive scalar component is transported.
Definition: ERF_DataStruct.H:2795
TerrainPoissonSolver terrain_poisson_solver
Projection solver on a terrain-fitted mesh: gmres_fft (default), mlmg or gmres_mlmg.
Definition: ERF_DataStruct.H:2671
bool hindcast_zhi_sponge_damping
Whether upper-boundary hindcast sponge damping is enabled.
Definition: ERF_DataStruct.H:3057
amrex::Real hurricane_eye_longitude
Initial hurricane-eye longitude.
Definition: ERF_DataStruct.H:3060
bool nudging_from_observations
Whether solution fields are nudged toward observations at stations.
Definition: ERF_DataStruct.H:2766
LandSurfaceType lsm_type
Land-surface model.
Definition: ERF_DataStruct.H:2953
bool large_scale_forcing
Definition: ERF_DataStruct.H:2779
bool substepping_diag
Whether to emit extra CFL diagnostics for compressible substepping.
Definition: ERF_DataStruct.H:2637
amrex::Real mean_vars_reset_time
Definition: ERF_DataStruct.H:2805
std::string windfarm_blade_table
Wind-farm blade table path.
Definition: ERF_DataStruct.H:2998
CanopyTurbulence canopyTurb
Definition: ERF_DataStruct.H:3040
amrex::Vector< int > is_land
Per-level land/water selector.
Definition: ERF_DataStruct.H:2634
amrex::Real hindcast_lateral_sponge_strength
Strength of the hindcast lateral sponge layer.
Definition: ERF_DataStruct.H:3055
bool forest_biophysics_heat
Definition: ERF_DataStruct.H:3037
ShocTransportMode shoc_transport_mode
Definition: ERF_DataStruct.H:2791
amrex::Real hurricane_eye_latitude
Initial hurricane-eye latitude.
Definition: ERF_DataStruct.H:3060
amrex::Real if_Cd_scalar
Immersed-forcing drag coefficient for scalars.
Definition: ERF_DataStruct.H:2700
amrex::Real if_cf_mismatch_warning
Spread of the fine solid fractions under a coarse cell along a lateral coarse/fine face at or above w...
Definition: ERF_DataStruct.H:2725
std::string windfarm_loc_table
Wind-farm location table path.
Definition: ERF_DataStruct.H:2997
std::string hindcast_surface_data_dir
Directory containing hindcast surface boundary data.
Definition: ERF_DataStruct.H:3051
bool custom_rhotheta_forcing
Whether custom rho-theta forcing is enabled.
Definition: ERF_DataStruct.H:2750
amrex::Real beta_d
Divergence damping coefficient used in the acoustic substepping.
Definition: ERF_DataStruct.H:2651
bool sbm_test_donor_cfl_fault
Definition: ERF_DataStruct.H:2947
amrex::Real if_init_surf_temp
Initial immersed-forcing surface temperature [K].
Definition: ERF_DataStruct.H:2708
amrex::Real nudging_t_z2
Definition: ERF_DataStruct.H:2771
std::string windfarm_spec_table
Wind-farm turbine specification table path.
Definition: ERF_DataStruct.H:2997
bool read_int_string(int max_level, const char *string_to_read, amrex::Vector< int > &vec_to_fill, int default_int)
Read one integer value or one value per AMR level.
Definition: ERF_DataStruct.H:2559
amrex::Real if_surf_temp_flux
Immersed-forcing surface temperature flux [K m/s].
Definition: ERF_DataStruct.H:2707
bool spatial_rhotheta_forcing
Whether spatially varying rho-theta forcing is enabled.
Definition: ERF_DataStruct.H:2757
amrex::Vector< int > urban_enabled_lev
Definition: ERF_DataStruct.H:2955
bool use_variable_beta_s
Whether beta_s varies on the w-faces with the terrain slope.
Definition: ERF_DataStruct.H:2645
bool custom_w_subsidence
Whether custom vertical subsidence is enabled.
Definition: ERF_DataStruct.H:2752
bool rad_feeds_lsm() const
True when the radiation model's outputs feed the land model (downwelling shortwave,...
Definition: ERF_DataStruct.H:2974
bool custom_moisture_forcing
Whether custom moisture forcing is enabled.
Definition: ERF_DataStruct.H:2751
amrex::Real if_surf_heating_rate
Immersed-forcing surface heating rate [K/hr].
Definition: ERF_DataStruct.H:2709
int sbm_nbins
Definition: ERF_DataStruct.H:2943
MoistureComponentIndices moisture_indices
Index map of the moisture data carried by the active scheme: conserved-state components for the speci...
Definition: ERF_DataStruct.H:2993
amrex::Real grid_stretching_ratio
Vertical grid stretching ratio.
Definition: ERF_DataStruct.H:2741
bool hindcast_surface_bcs
Whether hindcast surface boundary conditions are enabled.
Definition: ERF_DataStruct.H:3054
bool host_owns_vertical_scalar_diffusion() const noexcept
Test whether the host owns scalar diffusion.
Definition: ERF_DataStruct.H:2884
bool immersed_forcing_substep
Whether immersed-forcing source terms are applied only during substeps.
Definition: ERF_DataStruct.H:2695
bool if_use_most
Whether immersed-forcing MOST is enabled.
Definition: ERF_DataStruct.H:2711
amrex::Real const_massflux_tau
Relaxation time scale for constant-mass-flux forcing.
Definition: ERF_DataStruct.H:3045
amrex::Real hindcast_lateral_sponge_length
Length of the hindcast lateral sponge layer.
Definition: ERF_DataStruct.H:3055
bool host_owns_vertical_momentum_diffusion() const noexcept
Test whether the host owns momentum diffusion.
Definition: ERF_DataStruct.H:2873
amrex::Real hindcast_zhi_sponge_strength
Strength of the upper hindcast sponge layer.
Definition: ERF_DataStruct.H:3056
int force_stage1_single_substep
Flag forcing a single substep in the first RK stage.
Definition: ERF_DataStruct.H:2626
amrex::Real c_p
Specific heat at constant pressure for dry air [J/(kg-K)].
Definition: ERF_DataStruct.H:2737
bool if_implicit_drag
Definition: ERF_DataStruct.H:2703
bool do_mom_advection
Whether custom vertical subsidence is applied to momentum.
Definition: ERF_DataStruct.H:2754
bool if_stability_correction
Whether immersed-forcing stability corrections are enabled.
Definition: ERF_DataStruct.H:2713
amrex::Real nudging_t_z1
Definition: ERF_DataStruct.H:2770
amrex::Vector< amrex::Real > sbm_fixture_initial_state
Definition: ERF_DataStruct.H:2950
bool custom_forcing_prim_vars
Whether custom forcing operates on primitive variables.
Definition: ERF_DataStruct.H:2756
amrex::Real if_stability_wind_floor
Wind-speed floor [m/s] behind the friction velocity of the wall law's stability estimate (0: none).
Definition: ERF_DataStruct.H:2721
bool nudging_u
Definition: ERF_DataStruct.H:2775
bool nudging_from_input_sounding
Whether solution fields are nudged toward input sounding data.
Definition: ERF_DataStruct.H:2762
bool use_num_diff
Whether sixth-order numerical diffusion is enabled.
Definition: ERF_DataStruct.H:2938
bool use_wrf_bdy_qc_qi
Whether WRF cloud water and active cloud ice are ingested at real boundaries.
Definition: ERF_DataStruct.H:3011
void init_params(std::string pp_prefix)
Read sponge-layer options from the input parameter database.
Definition: ERF_SpongeStruct.H:28
void read(const std::string &prefix, const RRTMGPSolarChoice &solar)
Definition: ERF_TopographicShading.cpp:39
bool active() const
Definition: ERF_RadStruct.H:113
Here is the call graph for this function:

◆ pbl_suppresses_microphysics_condensation()

bool SolverChoice::pbl_suppresses_microphysics_condensation ( ) const
inlinenoexcept

Query whether the active PBL scheme suppresses microphysics condensation.

Returns
True when the active PBL scheme owns condensation handling.
2896  {
2897  return uses_shoc_family();
2898  }
Here is the call graph for this function:

◆ perturbation_pblh_level()

int SolverChoice::perturbation_pblh_level ( int  lev) const
inline
2920  {
2921  for (int source = lev-1; source >= 0; --source) {
2922  if (turbChoice[source].pbl_type != PBLType::None) { return source; }
2923  }
2924  for (int source = lev-1; source >= 0; --source) {
2925  const auto& tc = turbChoice[source];
2926  if (tc.les_type != LESType::None && !tc.smag2d) { return source; }
2927  }
2928  return -1;
2929  }

◆ rad_feeds_lsm()

bool SolverChoice::rad_feeds_lsm ( ) const
inline

True when the radiation model's outputs feed the land model (downwelling shortwave, downwelling longwave, solar zenith angle). RRTMGP writes them for any land model through lsm_output_ptrs; the two-stream model writes the broadband three for Noah-MP only (TwoStreamRadiation::write_land_forcing), since SLM wants the visible / near-infrared direct / diffuse split it does not compute. Both register the outputs in ERF::init_stuff and write them in ERF::advance_radiation; every site that encodes that rule must use this predicate so wiring another model in (e.g. Simple, which already runs through the interface) is one edit.

2974  {
2975  return (rad_type == RadiationType::RRTMGP) ||
2976  (rad_type == RadiationType::TwoStream && lsm_type == LandSurfaceType::NOAHMP);
2977  }

Referenced by NOAHMP::Define(), and init_params().

Here is the caller graph for this function:

◆ rad_uses_interface()

bool SolverChoice::rad_uses_interface ( ) const
inline

True for the models that run through the IRadiation interface (RRTMGP, Simple); the two-stream model has its own class.

2960  {
2961  return (rad_type == RadiationType::RRTMGP) || (rad_type == RadiationType::Simple);
2962  }

◆ read_int_string()

bool SolverChoice::read_int_string ( int  max_level,
const char *  string_to_read,
amrex::Vector< int > &  vec_to_fill,
int  default_int 
)
inline

Read one integer value or one value per AMR level.

Parameters
max_levelMaximum AMR level configured for the run.
string_to_readParmParse key to read.
vec_to_fillDestination vector with one entry per level.
default_intDefault value used when the key is absent.
Returns
True if the key was present in the inputs.
2561  {
2562  amrex::ParmParse pp("erf");
2563  int nvals = pp.countval(string_to_read);
2564  AMREX_ALWAYS_ASSERT(nvals == 0 || nvals == 1 || nvals >= max_level+1);
2565  amrex::Vector<int> temp; temp.resize(nvals);
2566  pp.queryarr(string_to_read,temp);
2567 
2568  if (vec_to_fill.size() < max_level+1) {
2569  vec_to_fill.resize(max_level+1);
2570  }
2571 
2572  if (nvals == 0) {
2573  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = default_int;
2574  } else if (nvals == 1) {
2575  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = temp[0];
2576  } else {
2577  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = temp[i];
2578  }
2579  return (nvals > 0);
2580  }

Referenced by init_params().

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

◆ set_mesh_type()

static void SolverChoice::set_mesh_type ( MeshType  new_mesh_type)
inlinestatic

Override the globally selected mesh type.

Parameters
new_mesh_typeMesh type to store.
2612  {
2613  mesh_type = new_mesh_type;
2614  }

Referenced by ERF::check_mesh_type(), and ProblemBase::init_custom_terrain().

Here is the caller graph for this function:

◆ use_building_immersed_forcing()

bool SolverChoice::use_building_immersed_forcing ( const amrex::Geometry &  geom) const
inlinenoexcept
2809  {
2810  return buildings_type == BuildingsType::ImmersedForcing &&
2811  std::sqrt(geom.CellSize(0) * geom.CellSize(1)) <=
2812  amrex::Real(50.0) * (one + amrex::Real(1.e-6));
2813  }

Referenced by ERF::immersed_forcing_active(), make_mom_sources(), and make_sources().

Here is the caller graph for this function:

◆ use_direct_perturbation()

bool SolverChoice::use_direct_perturbation ( int  lev) const
inline

Query whether direct turbulent perturbations are enabled on a level.

Parameters
levAMR level index.
Returns
True if direct, CPM, or CPM_W perturbations are enabled.
2834  {
2835  return pert_type[lev] == PerturbationType::Direct ||
2836  pert_type[lev] == PerturbationType::CPM ||
2837  pert_type[lev] == PerturbationType::CPM_W;
2838  }

◆ use_perturbation()

bool SolverChoice::use_perturbation ( int  lev) const
inline

Query whether any turbulent perturbation mode is enabled on a level.

Parameters
levAMR level index.
Returns
True if source, direct, CPM, or CPM_W perturbations are enabled.
2821  {
2822  return pert_type[lev] == PerturbationType::Source ||
2823  pert_type[lev] == PerturbationType::Direct ||
2824  pert_type[lev] == PerturbationType::CPM ||
2825  pert_type[lev] == PerturbationType::CPM_W;
2826  }

◆ use_source_perturbation()

bool SolverChoice::use_source_perturbation ( int  lev) const
inline

Query whether source-term turbulent perturbations are enabled on a level.

Parameters
levAMR level index.
Returns
True if source perturbations are enabled.
2846  {
2847  return pert_type[lev] == PerturbationType::Source;
2848  }

Referenced by make_sources().

Here is the caller graph for this function:

◆ use_wvel_perturbation()

bool SolverChoice::use_wvel_perturbation ( int  lev) const
inline

Query whether vertical-velocity CPM perturbations are enabled on a level.

Parameters
levAMR level index.
Returns
True if CPM_W perturbations are enabled.
2856  {
2857  return pert_type[lev] == PerturbationType::CPM_W;
2858  }

◆ uses_shoc_family()

bool SolverChoice::uses_shoc_family ( ) const
inlinenoexcept

Query whether any SHOC-family PBL scheme is active.

Returns
True if native or EAMxx SHOC is active.
2865  {
2866  return (use_eamxx_shoc || use_native_shoc);
2867  }

Referenced by Kessler::Define(), Morrison::Define(), SAM::Define(), SatAdj::Define(), WDM6::Define(), WSM6::Define(), init_params(), and pbl_suppresses_microphysics_condensation().

Here is the caller graph for this function:

Member Data Documentation

◆ abl_driver_type

SolverChoice::abl_driver_type

Atmospheric boundary-layer driver type.

Referenced by build_coriolis_forcings_const_lat(), display(), and init_params().

◆ abl_geo_forcing

SolverChoice::abl_geo_forcing

Applied geostrophic-wind forcing vector.

Referenced by build_coriolis_forcings_const_lat(), display(), init_params(), and make_mom_sources().

◆ abl_geo_wind_table

SolverChoice::abl_geo_wind_table

Path to a time-varying geostrophic wind table.

Referenced by build_coriolis_forcings_const_lat(), and init_params().

◆ abl_pressure_grad

SolverChoice::abl_pressure_grad

Applied ABL pressure-gradient forcing vector.

Referenced by display(), erf_slow_rhs_pre(), and init_params().

◆ advChoice

SolverChoice::advChoice

Advection-related options.

Referenced by ERF::ComputeGhostCells(), display(), erf_slow_rhs_post(), erf_slow_rhs_pre(), and init_params().

◆ anelastic

SolverChoice::anelastic

◆ anelastic_type

SolverChoice::anelastic_type

Per-level two-stage scheme used by the anelastic integrator.

Referenced by display(), erf_slow_rhs_post(), erf_slow_rhs_pre(), init_params(), and StageFluxWeight().

◆ ave_plane

SolverChoice::ave_plane {2}

Averaging plane index used by diagnostics.

Referenced by SAM::Define(), WDM6::Define(), WSM6::Define(), init_params(), make_mom_sources(), and make_sources().

◆ avg_grid_faces_to_nodes

bool SolverChoice::avg_grid_faces_to_nodes {false}

Referenced by init_params().

◆ bdy_moist_nudge_type

SolverChoice::bdy_moist_nudge_type = 1

Moist-variable nudging strategy in boundary regions.

Referenced by init_params().

◆ bdy_nudge_factor

SolverChoice::bdy_nudge_factor = amrex::Real(10.0)

Boundary sponge nudging factor.

Referenced by init_params().

◆ bdy_rho_nudge_factor

amrex::Real SolverChoice::bdy_rho_nudge_factor = amrex::Real(-1.0)

Referenced by init_params().

◆ beta_d

SolverChoice::beta_d = amrex::Real(0.1)

Divergence damping coefficient used in the acoustic substepping.

Referenced by init_params().

◆ beta_s

SolverChoice::beta_s = amrex::Real(0.1)

Time off-centering coefficient for forward weighting.

Referenced by init_params().

◆ beta_s_max

SolverChoice::beta_s_max = amrex::Real(0.8)

Upper bound of the spatially varying beta_s.

Referenced by init_params().

◆ beta_s_min

SolverChoice::beta_s_min = amrex::Real(0.1)

Lower bound of the spatially varying beta_s.

Referenced by init_params().

◆ buildings_fc_factories

SolverChoice::buildings_fc_factories = false
inlinestatic

Use native face-centered EB factories for immersed buildings on a static fitted mesh.

Referenced by init_params(), and ERF::use_native_fc_factories().

◆ buildings_type

SolverChoice::buildings_type = BuildingsType::None
inlinestatic

◆ buoyancy_type

SolverChoice::buoyancy_type

Per-level buoyancy formulation selector.

Referenced by check_params(), display(), init_params(), and make_buoyancy().

◆ c_p

SolverChoice::c_p = Cp_d

Specific heat at constant pressure for dry air [J/(kg-K)].

Referenced by Kessler::Define(), SAM::Define(), SatAdj::Define(), and init_params().

◆ canopyTurb

CanopyTurbulence SolverChoice::canopyTurb

◆ cf_loglaw_fill

SolverChoice::cf_loglaw_fill = false

Share the flux of the first coarse face above a wall among its fine sub-faces at the lateral coarse/fine faces by ln(1 + z/z0) at their heights above the wall, instead of the linear interpolation; the immersed surface or a surface-layer bottom, constant dz.

Referenced by check_params(), and init_params().

◆ cf_loglaw_z0

SolverChoice::cf_loglaw_z0 = amrex::Real(-1.0)

Roughness length [m] of that share; by default erf.if_z0 with immersed forcing, else the inputs' erf.most.z0 or erf.zlo.most.z0 (0.1 m when neither is given).

Referenced by check_params(), and init_params().

◆ coarse_bckgnd_data_file

SolverChoice::coarse_bckgnd_data_file

Coarse background data file used for ensemble initialization.

Referenced by init_params().

◆ compute_mean_vars

bool SolverChoice::compute_mean_vars = false

Referenced by init_params().

◆ const_massflux_layer_hi

SolverChoice::const_massflux_layer_hi = amrex::Real( bogus_large_value)

Upper height of the constant-mass-flux forcing layer.

Referenced by ERF::ERF_shared(), and init_params().

◆ const_massflux_layer_lo

SolverChoice::const_massflux_layer_lo = amrex::Real(-bogus_large_value)

Lower height of the constant-mass-flux forcing layer.

Referenced by ERF::ERF_shared(), and init_params().

◆ const_massflux_tau

SolverChoice::const_massflux_tau = one

Relaxation time scale for constant-mass-flux forcing.

Referenced by init_params(), and make_mom_sources().

◆ const_massflux_u

SolverChoice::const_massflux_u = zero

Target constant mass flux in the x direction.

Referenced by check_params(), ERF::ERF_shared(), init_params(), and make_mom_sources().

◆ const_massflux_v

SolverChoice::const_massflux_v = zero

Target constant mass flux in the y direction.

Referenced by check_params(), ERF::ERF_shared(), init_params(), and make_mom_sources().

◆ coriolis_3d

SolverChoice::coriolis_3d = true

Whether the three-dimensional Coriolis terms are included.

Referenced by build_coriolis_forcings_const_lat().

◆ coriolis_factor

SolverChoice::coriolis_factor = zero

Twice the planetary rotation rate used for Coriolis forcing.

Referenced by build_coriolis_forcings_const_lat(), init_params(), and make_mom_sources().

◆ cosphi

SolverChoice::cosphi = zero

Cosine of the latitude used for Coriolis forcing.

Referenced by build_coriolis_forcings_const_lat(), and make_mom_sources().

◆ coupling_type

SolverChoice::coupling_type

Multilevel coupling strategy.

Referenced by check_params(), display(), init_params(), and RefluxStageWeight().

◆ custom_forcing_prim_vars

SolverChoice::custom_forcing_prim_vars = false

Whether custom forcing operates on primitive variables.

Referenced by init_params(), and make_sources().

◆ custom_geostrophic_profile

SolverChoice::custom_geostrophic_profile = false

Whether a custom geostrophic wind profile is used.

Referenced by init_params().

◆ custom_moisture_forcing

SolverChoice::custom_moisture_forcing = false

Whether custom moisture forcing is enabled.

Referenced by init_params(), and make_sources().

◆ custom_rhotheta_forcing

SolverChoice::custom_rhotheta_forcing = false

Whether custom rho-theta forcing is enabled.

Referenced by init_params(), and make_sources().

◆ custom_w_subsidence

SolverChoice::custom_w_subsidence = false

Whether custom vertical subsidence is enabled.

Referenced by init_params(), make_mom_sources(), and make_sources().

◆ dampingChoice

SolverChoice::dampingChoice

Damping-related options.

Referenced by display(), init_params(), make_mom_sources(), and make_sources().

◆ diffChoice

◆ do_forest_drag

SolverChoice::do_forest_drag {false}

Whether forest canopy drag is enabled.

Referenced by make_mom_sources().

◆ do_mom_advection

SolverChoice::do_mom_advection = true

Whether custom vertical subsidence is applied to momentum.

Referenced by init_params(), and make_mom_sources().

◆ do_theta_advection

SolverChoice::do_theta_advection = true

Whether custom vertical subsidence is applied to rho-theta.

Referenced by init_params(), and make_sources().

◆ dz0

SolverChoice::dz0 = zero

Initial vertical grid spacing for stretched-grid setup.

Referenced by ERF::ERF_shared(), and init_params().

◆ ebChoice

SolverChoice::ebChoice

◆ ens_pert_amplitude

SolverChoice::ens_pert_amplitude = -1.0

Amplitude of ensemble initialization perturbations.

Referenced by init_params().

◆ ens_pert_correlated_radius

SolverChoice::ens_pert_correlated_radius = -1.0

Spatial correlation radius for ensemble perturbations.

Referenced by init_params().

◆ fixed_density

SolverChoice::fixed_density

Per-level flag selecting fixed-density treatment; always 1 at an anelastic level.

Referenced by display(), erf_slow_rhs_pre(), and init_params().

◆ flat_terrain

SolverChoice::flat_terrain = false
inlinestatic

Permit fixed-index planar averages after validating a flat fitted mesh.

Referenced by display(), init_params(), and make_mom_sources().

◆ force_stage1_single_substep

SolverChoice::force_stage1_single_substep = 1

Flag forcing a single substep in the first RK stage.

Referenced by init_params().

◆ forest_biophysics

bool SolverChoice::forest_biophysics {false}

Referenced by init_params().

◆ forest_biophysics_heat

bool SolverChoice::forest_biophysics_heat {false}

◆ forest_leaf_theta_fixed

amrex::Real SolverChoice::forest_leaf_theta_fixed {-one}

◆ forest_substep

SolverChoice::forest_substep = false

Whether canopy source terms are applied only during substeps.

Referenced by init_params(), and make_mom_sources().

◆ four_stream_radiation

SolverChoice::four_stream_radiation = false

Whether the four-stream radiation approximation is enabled.

Referenced by init_params(), and make_sources().

◆ gradp_type

SolverChoice::gradp_type = 0

Terrain-fitted horizontal pressure-gradient formulation.

Referenced by display(), init_params(), and make_gradp_pert().

◆ gravity

SolverChoice::gravity

Effective gravitational acceleration.

Referenced by ComputeTurbulentViscosity(), erf_slow_rhs_post(), init_params(), and make_buoyancy().

◆ grid_stretching_ratio

SolverChoice::grid_stretching_ratio = 0

Vertical grid stretching ratio.

Referenced by ERF::ERF_shared(), and init_params().

◆ have_geo_wind_profile

SolverChoice::have_geo_wind_profile {false}

Whether a geostrophic wind profile has been configured.

Referenced by init_params(), and make_mom_sources().

◆ hindcast_boundary_data_dir

SolverChoice::hindcast_boundary_data_dir

Directory containing hindcast lateral boundary data.

Referenced by init_params().

◆ hindcast_data_interval_in_hrs

SolverChoice::hindcast_data_interval_in_hrs = -one

Time interval between hindcast data files [hr].

Referenced by init_params().

◆ hindcast_lateral_forcing

SolverChoice::hindcast_lateral_forcing = false

Whether hindcast lateral forcing is enabled.

Referenced by init_params(), and make_mom_sources().

◆ hindcast_lateral_sponge_length

SolverChoice::hindcast_lateral_sponge_length = -one

Length of the hindcast lateral sponge layer.

Referenced by ApplyBndryForcing_Forecast(), and init_params().

◆ hindcast_lateral_sponge_strength

SolverChoice::hindcast_lateral_sponge_strength = -one

Strength of the hindcast lateral sponge layer.

Referenced by ApplyBndryForcing_Forecast(), and init_params().

◆ hindcast_surface_bcs

SolverChoice::hindcast_surface_bcs = false

Whether hindcast surface boundary conditions are enabled.

Referenced by init_params().

◆ hindcast_surface_data_dir

SolverChoice::hindcast_surface_data_dir

Directory containing hindcast surface boundary data.

Referenced by init_params().

◆ hindcast_zhi_sponge_damping

SolverChoice::hindcast_zhi_sponge_damping = false

Whether upper-boundary hindcast sponge damping is enabled.

Referenced by ApplyBndryForcing_Forecast(), and init_params().

◆ hindcast_zhi_sponge_length

SolverChoice::hindcast_zhi_sponge_length = -one

Length of the upper hindcast sponge layer.

Referenced by ApplyBndryForcing_Forecast(), and init_params().

◆ hindcast_zhi_sponge_strength

SolverChoice::hindcast_zhi_sponge_strength = -one

Strength of the upper hindcast sponge layer.

Referenced by ApplyBndryForcing_Forecast(), and init_params().

◆ hurricane_eye_latitude

SolverChoice::hurricane_eye_latitude = -1e10

Initial hurricane-eye latitude.

Referenced by ERF::HurricaneEyeTracker(), and init_params().

◆ hurricane_eye_longitude

SolverChoice::hurricane_eye_longitude = -1e10

Initial hurricane-eye longitude.

Referenced by ERF::HurricaneEyeTracker(), and init_params().

◆ if_average_down

SolverChoice::if_average_down = "plain"

Cell average down over immersed-forcing levels: "plain" (the default, the plain cell average) or "fluid_mass" (the fine cells weighted by their fluid mass, coarse cells solid on their own level kept; see if_average_down in ERF_Utils.H).

Referenced by check_params(), and init_params().

◆ if_Cd_momentum

◆ if_Cd_scalar

SolverChoice::if_Cd_scalar = amrex::Real(10.0)

◆ if_cf_mismatch_warning

SolverChoice::if_cf_mismatch_warning = amrex::Real(0.75)

Spread of the fine solid fractions under a coarse cell along a lateral coarse/fine face at or above which the start-up warning counts the cell (the levels describe the surface differently there); 0 turns the check off.

Referenced by init_params().

◆ if_damp_alpha

SolverChoice::if_damp_alpha = 0.5

◆ if_flat_wall_dissipation

SolverChoice::if_flat_wall_dissipation = false

Partial fraction-stress wall cells dissipate TKE with the length scale of flat ground's first cell; on by default with the fraction-stress law.

Referenced by check_params(), ComputeTurbulentViscosity(), and init_params().

◆ if_fraction_stress

SolverChoice::if_fraction_stress = false

erf.if_wall_form = fraction_stress: the wall stress of ERF_ImmersedWallCell.H in the wall cell of each column, with the wall face closed to diffusion; false is the legacy MOST relaxation at fixed 0.5/1.5 dz (the default, unchanged).

Referenced by check_params(), ComputeTurbulentViscosity(), init_params(), make_mom_sources(), and make_sources().

◆ if_implicit_drag

◆ if_implicit_projection

◆ if_init_surf_temp

SolverChoice::if_init_surf_temp = zero

Initial immersed-forcing surface temperature [K].

Referenced by ImmersedForcingBuildings_Scalar(), ImmersedForcingTerrain_Scalar(), init_params(), and make_wall_cond().

◆ if_Olen_in

◆ if_psi_cap_factor

SolverChoice::if_psi_cap_factor = amrex::Real(1.0)

Cap on psi_m in the immersed momentum wall law as a fraction of ln(z/z0) (1: none).

Referenced by ImmersedForcingBuildings_Xmom(), ImmersedForcingBuildings_Ymom(), ImmersedForcingBuildings_Zmom(), ImmersedForcingTerrain_Xmom(), ImmersedForcingTerrain_Ymom(), and init_params().

◆ if_small_volfrac

SolverChoice::if_small_volfrac = amrex::Real(0.005)

◆ if_snap_partial_cells

SolverChoice::if_snap_partial_cells = false

When true, the immersed forcing reads the blanking snapped to solid (1) or fluid (0) at half, so a building from a height map becomes the same staircase of whole cells an exact box is: the wall law (and the thermal conditions) sit on the boundary solid cells, roofs included, the drag on the interior cells, and nothing on the sliver cells of the reader's one-cell ramp (1-20 percent solid at the corners), on which the raw fractions make the wall law and the drag disagree and grow a vertical checkerboard over hours. The staircase puts full-strength forcing on every wall face, so the switch also selects the point-implicit drag form (if_implicit_drag), without which the explicit rate at rims and corners drives the density negative within seconds. The momentum kernels take the blanking of a face from the two cells it joins (solid if either is), so the staircase is the same with and without the face-centred blanking of the build; a face between a solid and a fluid cell is wall-normal and gets the interior drag toward zero (no penetration) whichever row it lies in, and a face between two solid cells the roof or wall law of its row (with the full log-law target; the partial-cell weight of the target is not applied) or the interior drag. Buildings only (erf.buildings_type = ImmersedForcing): the terrain kernels keep the raw fractions, whose wall law is weighted by the fluid fraction of the face. Default false, the raw fractions, for backward compatibility (on an exact box a boundary cell then carries the wall law and the interior drag together, and the roof only the drag); set it for height-map buildings.

Referenced by ImmersedForcingBuildings_Scalar(), ImmersedForcingBuildings_Xmom(), ImmersedForcingBuildings_Ymom(), ImmersedForcingBuildings_Zmom(), and init_params().

◆ if_stability_correction

SolverChoice::if_stability_correction = false

◆ if_stability_wind_floor

SolverChoice::if_stability_wind_floor = amrex::Real(0.0)

◆ if_surf_heating_rate

SolverChoice::if_surf_heating_rate = zero

Immersed-forcing surface heating rate [K/hr].

Referenced by ImmersedForcingBuildings_Scalar(), ImmersedForcingTerrain_Scalar(), init_params(), and make_wall_cond().

◆ if_surf_temp_flux

◆ if_use_most

◆ if_wall_face_spacing

SolverChoice::if_wall_face_spacing = 2

Spacing the face above the fraction-stress wall cell differences over: 0 the cell height, 1 the centroid spacing, 2 (default) the log spacing (ib_wall::face_above_factor).

Referenced by check_params(), and init_params().

◆ if_wall_tke

SolverChoice::if_wall_tke = false

Hold the k-eqn TKE of the fraction-stress wall cell at its flat-ground wall value (ib_wall::wall_tke), as erf.dirichlet_k does over flat ground.

Referenced by check_params(), init_params(), and make_sources().

◆ if_wall_tke_time_factor

SolverChoice::if_wall_tke_time_factor = amrex::Real(1.0)

1 (the default) pins the wall cell after every stage and in the implicit TKE solve; a larger value relaxes toward the wall value as a source over that many steps.

Referenced by erf_slow_rhs_post(), ImmersedForcingTerrain_Scalar_FractionStress(), and init_params().

◆ if_ws_floor

SolverChoice::if_ws_floor = 0.001

Wind-speed floor [m/s] in the per-step change limit of the building wall-law forcing.

Referenced by ImmersedForcingBuildings_Xmom(), ImmersedForcingBuildings_Ymom(), ImmersedForcingBuildings_Zmom(), and init_params().

◆ if_z0

◆ immersed_forcing_substep

SolverChoice::immersed_forcing_substep = false

Whether immersed-forcing source terms are applied only during substeps.

Referenced by ImmersedForcingBuildings_Xmom(), ImmersedForcingBuildings_Ymom(), ImmersedForcingBuildings_Zmom(), init_params(), make_mom_sources(), and make_sources().

◆ implicit_before_substep

SolverChoice::implicit_before_substep = true

Whether implicit diffusion is applied before acoustic substepping.

Referenced by init_params().

◆ implicit_ke_diffusion

SolverChoice::implicit_ke_diffusion = true

Whether implicit vertical TKE diffusion is included.

Referenced by display(), erf_slow_rhs_post(), and init_params().

◆ implicit_moisture_diffusion

SolverChoice::implicit_moisture_diffusion = true

Whether implicit vertical moisture diffusion is included.

Referenced by check_params(), display(), erf_slow_rhs_post(), and init_params().

◆ implicit_momentum_diffusion

SolverChoice::implicit_momentum_diffusion = true

Whether implicit vertical momentum diffusion is included.

Referenced by check_params(), display(), erf_make_tau_terms(), and init_params().

◆ implicit_terrain_metric

SolverChoice::implicit_terrain_metric = false

Whether the compact terrain-metric part of the vertical diffusion is solved implicitly.

Referenced by check_params(), DiffusionSrcForState_T(), display(), erf_make_tau_terms(), and init_params().

◆ implicit_thermal_diffusion

SolverChoice::implicit_thermal_diffusion = true

Whether implicit vertical thermal diffusion is included.

Referenced by check_params(), display(), erf_slow_rhs_pre(), and init_params().

◆ init_type

SolverChoice::init_type = InitType::None
inlinestatic

◆ interp_atmos_from_coarse

bool SolverChoice::interp_atmos_from_coarse {false}

Referenced by init_params().

◆ io_hurricane_eye_tracker

SolverChoice::io_hurricane_eye_tracker = false

Whether hurricane-eye tracking output is enabled.

Referenced by init_params().

◆ is_init_for_ensemble

SolverChoice::is_init_for_ensemble = false

Whether initialization is for an ensemble simulation.

Referenced by init_params().

◆ is_land

SolverChoice::is_land

Per-level land/water selector.

Referenced by init_params().

◆ large_scale_forcing

bool SolverChoice::large_scale_forcing = false

Referenced by init_params(), and make_mom_sources().

◆ lsf_file

std::string SolverChoice::lsf_file = ""

◆ lsf_timescale

amrex::Real SolverChoice::lsf_timescale = zero

◆ lsm_type

SolverChoice::lsm_type

Land-surface model.

Referenced by init_params(), rad_feeds_lsm(), and Radiation::Radiation().

◆ massflux_khi

SolverChoice::massflux_khi {0}

Upper vertical index for constant-mass-flux forcing.

Referenced by ERF::ERF_shared(), and make_mom_sources().

◆ massflux_klo

SolverChoice::massflux_klo {0}

Lower vertical index for constant-mass-flux forcing.

Referenced by ERF::ERF_shared(), and make_mom_sources().

◆ mean_vars_reset_mode

std::string SolverChoice::mean_vars_reset_mode = "plotfile"

Referenced by init_params().

◆ mean_vars_reset_time

amrex::Real SolverChoice::mean_vars_reset_time = -one

Referenced by init_params().

◆ mesh_type

◆ moisture_indices

◆ moisture_tight_coupling

SolverChoice::moisture_tight_coupling {false}

Whether moisture updates use tight coupling.

Referenced by init_params().

◆ moisture_type

◆ n_ensemble

SolverChoice::n_ensemble = -1

Number of ensemble members.

Referenced by init_params().

◆ ncorr

SolverChoice::ncorr = 1

Number of projection correction iterations.

Referenced by init_params().

◆ nudging_from_input_sounding

SolverChoice::nudging_from_input_sounding = false

Whether solution fields are nudged toward input sounding data.

Referenced by init_params(), and make_mom_sources().

◆ nudging_from_observations

SolverChoice::nudging_from_observations = false

Whether solution fields are nudged toward observations at stations.

Referenced by init_params().

◆ nudging_q

bool SolverChoice::nudging_q = true

Referenced by init_params().

◆ nudging_q_z1

amrex::Real SolverChoice::nudging_q_z1 = zero

Referenced by init_params().

◆ nudging_q_z2

amrex::Real SolverChoice::nudging_q_z2 = amrex::Real(10000.0)

Referenced by init_params().

◆ nudging_t

bool SolverChoice::nudging_t = true

Referenced by init_params().

◆ nudging_t_z1

amrex::Real SolverChoice::nudging_t_z1 = zero

Referenced by init_params().

◆ nudging_t_z2

amrex::Real SolverChoice::nudging_t_z2 = amrex::Real(10000.0)

Referenced by init_params().

◆ nudging_u

bool SolverChoice::nudging_u = true

Referenced by init_params(), and make_mom_sources().

◆ nudging_u_z1

amrex::Real SolverChoice::nudging_u_z1 = amrex::Real(-1.0e36)

Referenced by init_params(), and make_mom_sources().

◆ nudging_u_z2

amrex::Real SolverChoice::nudging_u_z2 = amrex::Real(1.0e36)

Referenced by init_params(), and make_mom_sources().

◆ num_diff_coeff

SolverChoice::num_diff_coeff {zero}

Numerical diffusion coefficient after input scaling.

Referenced by init_params(), make_mom_sources(), and make_sources().

◆ pert_type

SolverChoice::pert_type

◆ perturbation_auto

SolverChoice::perturbation_auto {false}

Select LES nests, using parent winds and a PBL ancestor's height, or the nearest LES ancestor's diagnostic when no PBL scheme is present. Defaults to true for WRFInput and Metgrid initialization, false otherwise.

Referenced by check_params(), display(), and init_params().

◆ perturbation_auto_pbl_fraction

SolverChoice::perturbation_auto_pbl_fraction {amrex::Real(0.9)}

Fraction of the selected ancestor's PBL height occupied by perturbations.

Referenced by display(), and init_params().

◆ perturbation_auto_period

SolverChoice::perturbation_auto_period {amrex::Real(600.0)}

Seconds between automatic parent-wind and PBL-height updates.

Referenced by display(), and init_params().

◆ poisson_abstol

SolverChoice::poisson_abstol = amrex::Real(1e-8)

Absolute tolerance for the Poisson solve.

Referenced by init_params().

◆ poisson_reltol

SolverChoice::poisson_reltol = amrex::Real(1e-8)

Relative tolerance for the Poisson solve.

Referenced by init_params().

◆ project_initial_velocity

SolverChoice::project_initial_velocity

Per-level flag for projecting the initial velocity.

Referenced by init_params().

◆ rad_type

◆ radChoice

RadChoice SolverChoice::radChoice

Referenced by init_params().

◆ rdOcp

◆ rebalance_wrf_input

SolverChoice::rebalance_wrf_input = true

Whether to rebalance states from wrfinput and wrfbdy data.

Referenced by init_params().

◆ rrtmgpSolarChoice

RRTMGPSolarChoice SolverChoice::rrtmgpSolarChoice

◆ sampling_distance_by_D

SolverChoice::sampling_distance_by_D = -one

Turbine inflow sampling distance normalized by rotor diameter.

Referenced by check_params(), and init_params().

◆ sbm_cloud_rain_split

int SolverChoice::sbm_cloud_rain_split {-1}

Referenced by init_params().

◆ sbm_edges

amrex::Vector<amrex::Real> SolverChoice::sbm_edges

Referenced by init_params().

◆ sbm_fixture_initial_state

amrex::Vector<amrex::Real> SolverChoice::sbm_fixture_initial_state

Referenced by ERF::ERF_shared(), and init_params().

◆ sbm_moment_mode

int SolverChoice::sbm_moment_mode {1}

Referenced by init_params().

◆ sbm_nbins

int SolverChoice::sbm_nbins {4}

Referenced by init_params().

◆ sbm_pivots

amrex::Vector<amrex::Real> SolverChoice::sbm_pivots

Referenced by init_params().

◆ sbm_test_donor_cfl_fault

bool SolverChoice::sbm_test_donor_cfl_fault {false}

Referenced by erf_slow_rhs_post(), and init_params().

◆ sbm_test_native_qc_write_fault

bool SolverChoice::sbm_test_native_qc_write_fault {false}

Referenced by erf_slow_rhs_post(), and init_params().

◆ shoc_momentum_transport

◆ shoc_transport_mode

ShocTransportMode SolverChoice::shoc_transport_mode = ShocTransportMode::StateUpdate

◆ sinphi

SolverChoice::sinphi = zero

Sine of the latitude used for Coriolis forcing.

Referenced by build_coriolis_forcings_const_lat(), init_params(), and make_mom_sources().

◆ sounding_type

SolverChoice::sounding_type = SoundingType::Ideal
inlinestatic

Interpretation used for input sounding profiles.

Referenced by init_params().

◆ spatial_moisture_forcing

SolverChoice::spatial_moisture_forcing = false

Whether spatially varying moisture forcing is enabled.

Referenced by init_params(), and make_sources().

◆ spatial_rhotheta_forcing

SolverChoice::spatial_rhotheta_forcing = false

Whether spatially varying rho-theta forcing is enabled.

Referenced by init_params(), and make_sources().

◆ spongeChoice

SolverChoice::spongeChoice

Sponge-layer options.

Referenced by display(), init_params(), make_mom_sources(), and make_sources().

◆ substepping_diag

SolverChoice::substepping_diag = false

Whether to emit extra CFL diagnostics for compressible substepping.

Referenced by init_params().

◆ substepping_type

SolverChoice::substepping_type

Acoustic substepping type for each AMR level.

Referenced by display(), and init_params().

◆ terrain_poisson_solver

SolverChoice::terrain_poisson_solver = TerrainPoissonSolver::gmres_fft

Projection solver on a terrain-fitted mesh: gmres_fft (default), mlmg or gmres_mlmg.

Referenced by init_params().

◆ terrain_type

◆ test_mapfactor

SolverChoice::test_mapfactor = false

Whether to use test map scale factors.

Referenced by init_params().

◆ test_mapfactor_amp

SolverChoice::test_mapfactor_amp = amrex::Real(0)

Amplitude of the spatially varying test map scale factors on level 0 (0: not used).

Referenced by init_params().

◆ time_avg_vel

SolverChoice::time_avg_vel = false

Whether time-averaged velocity fields are output.

Referenced by init_params().

◆ topographicChoice

TopographicShadingChoice SolverChoice::topographicChoice

◆ transport_scalar

SolverChoice::transport_scalar = true

Whether the passive scalar component is transported.

Referenced by erf_slow_rhs_post(), and init_params().

◆ turb_disk_angle

SolverChoice::turb_disk_angle = -one

Turbine disk angle from the x axis [deg].

Referenced by check_params(), and init_params().

◆ turbChoice

◆ urban_enabled_lev

amrex::Vector<int> SolverChoice::urban_enabled_lev

Referenced by init_params().

◆ urban_type

UrbanType SolverChoice::urban_type

Referenced by init_params().

◆ use_coriolis

SolverChoice::use_coriolis = false

Whether Coriolis forcing is enabled.

Referenced by display(), init_params(), and make_mom_sources().

◆ use_coupled_sst

bool SolverChoice::use_coupled_sst = false

◆ use_eamxx_shoc

SolverChoice::use_eamxx_shoc = false

Whether any level uses the EAMxx SHOC PBL scheme.

Referenced by host_owns_vertical_momentum_diffusion(), host_owns_vertical_scalar_diffusion(), init_params(), and uses_shoc_family().

◆ use_gravity

SolverChoice::use_gravity = false

Whether gravitational forcing is enabled.

Referenced by display(), and init_params().

◆ use_lagged_delta_rt

SolverChoice::use_lagged_delta_rt = true

Whether to use lagged delta terms for moving terrain.

Referenced by check_params(), and init_params().

◆ use_native_shoc

SolverChoice::use_native_shoc = false

Whether any level uses the native SHOC PBL scheme.

Referenced by host_owns_vertical_momentum_diffusion(), host_owns_vertical_scalar_diffusion(), init_params(), and uses_shoc_family().

◆ use_num_diff

SolverChoice::use_num_diff {false}

Whether sixth-order numerical diffusion is enabled.

Referenced by ERF::ComputeGhostCells(), init_params(), and make_sources().

◆ use_pert_pres_gradient

SolverChoice::use_pert_pres_gradient = true

Whether momentum equations use perturbational pressure gradients.

Referenced by init_params(), and make_gradp_pert().

◆ use_real_bcs

SolverChoice::use_real_bcs = false
inlinestatic

Whether real-data lateral boundary conditions are used.

Referenced by init_params().

◆ use_rotate_surface_flux

SolverChoice::use_rotate_surface_flux = false

Whether MOST surface fluxes are rotated with terrain.

Referenced by erf_slow_rhs_post(), erf_slow_rhs_pre(), and init_params().

◆ use_variable_beta_s

SolverChoice::use_variable_beta_s = false

Whether beta_s varies on the w-faces with the terrain slope.

Referenced by init_params().

◆ use_wrf_bdy_density

bool SolverChoice::use_wrf_bdy_density = true

Referenced by init_params().

◆ use_wrf_bdy_qc_qi

SolverChoice::use_wrf_bdy_qc_qi = false

Whether WRF cloud water and active cloud ice are ingested at real boundaries.

Referenced by init_params().

◆ variable_coriolis

SolverChoice::variable_coriolis {false}

Whether spatially varying Coriolis forcing is enabled.

Referenced by init_params(), and make_mom_sources().

◆ vert_implicit_fac

SolverChoice::vert_implicit_fac

Per-level, per-stage implicit vertical diffusion factors.

Referenced by check_params(), display(), erf_make_tau_terms(), erf_slow_rhs_post(), erf_slow_rhs_pre(), and init_params().

◆ wall_dist_type

std::string SolverChoice::wall_dist_type = "poisson"

Referenced by init_params().

◆ windfarm_airfoil_tables

SolverChoice::windfarm_airfoil_tables

Wind-farm airfoil table paths.

Referenced by init_params().

◆ windfarm_blade_table

SolverChoice::windfarm_blade_table

Wind-farm blade table path.

Referenced by init_params().

◆ windfarm_loc_table

SolverChoice::windfarm_loc_table

Wind-farm location table path.

Referenced by init_params().

◆ windfarm_loc_type

SolverChoice::windfarm_loc_type

Coordinate system for wind-farm turbine locations.

Referenced by check_params(), and init_params().

◆ windfarm_spec_table

SolverChoice::windfarm_spec_table

Wind-farm turbine specification table path.

Referenced by init_params().

◆ windfarm_spec_table_extra

SolverChoice::windfarm_spec_table_extra

Additional wind-farm turbine specification table path.

Referenced by init_params().

◆ windfarm_type

SolverChoice::windfarm_type

Wind-farm model.

Referenced by check_params(), and init_params().

◆ windfarm_x_shift

SolverChoice::windfarm_x_shift = -one

Wind-farm x-coordinate shift.

Referenced by check_params(), and init_params().

◆ windfarm_y_shift

SolverChoice::windfarm_y_shift = -one

Wind-farm y-coordinate shift.

Referenced by check_params(), and init_params().

◆ wrfinput_zlevels_from_file

bool SolverChoice::wrfinput_zlevels_from_file {true}

Referenced by init_params().


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