ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_IBSEBParams.H
Go to the documentation of this file.
1 #ifndef ERF_IBSEB_PARAMS_H
2 #define ERF_IBSEB_PARAMS_H
3 
4 #include <AMReX_ParmParse.H>
5 #include <AMReX_REAL.H>
6 #include <AMReX.H>
7 #include <string>
8 #include <vector>
9 
10 /**
11  * \file ERF_IBSEBParams.H
12  * \brief Inputs of the immersed-boundary surface energy balance (``erf.ibseb.*``).
13  *
14  * The balance runs on the faces of buildings represented by immersed forcing
15  * (``erf.buildings_type = ImmersedForcing``). Every input lives under the
16  * ``erf.ibseb`` prefix and everything is off unless ``erf.ibseb.enable`` is set,
17  * in which case ERF::init_ibseb() builds one IBFaceSet per level.
18  *
19  * The parameters are parsed once, in ERF::ReadParameters(), and copied into
20  * each IBFaceSet, so a face set never reads ParmParse itself. Every input of
21  * the balance lives here with its default, so that the whole input surface
22  * is in one place; the inputs are documented in Docs/sphinx_doc/Inputs.rst.
23  */
25 {
26  bool enable = false; ///< Master switch
27  int n_slab_layers = 4; ///< Conduction layers per face
28  amrex::Real T_skin_init = 300.0; ///< Initial skin temperature [K]
29  amrex::Real T_interior = 293.0; ///< Interior (deep) temperature [K]
30  std::string csv_file = "ibseb_buildings.csv"; ///< Per-building report
31  int csv_int = 100; ///< Steps between report rows; <= 0 disables
32  bool debug = false; ///< [IBSEB DEBUG] prints: set description at build, per-step summary, per-building rows
33  std::string dump_faces_file; ///< Per-rank face dump at report time (empty = off)
34  bool dump_faces_tag_step = false; ///< Name each dump by its step (keeps every one) instead of overwriting
35 
36  // ---- Radiation provider ------------------------------------------------
37  // Where the downwelling shortwave and longwave come from.
38  // "prescribed" is built in: clear-sky formulas with a fixed or computed
39  // sun. "two_stream" is reserved for the column fluxes of the TwoStream
40  // radiation model (erf.radiation_model = TwoStream), not wired yet.
41  std::string radiation = "prescribed";
42  // "fixed": the sun stays at sun_zenith_deg / sun_azimuth_deg with the
43  // direct-normal and diffuse irradiances given below (analytic tests).
44  // "solar": sun from the site and time; irradiances from the clear-sky
45  // formulas.
46  std::string sun_mode = "fixed";
47  amrex::Real sun_zenith_deg = 45.0; ///< fixed: zenith angle [deg]
48  amrex::Real sun_azimuth_deg = 180.0; ///< fixed: azimuth clockwise from north [deg]; 180 = sun in the south
49  amrex::Real sw_direct_normal = 800.0; ///< fixed: direct-normal irradiance [W/m2]
50  amrex::Real sw_diffuse = 100.0; ///< fixed: diffuse irradiance on a horizontal surface [W/m2]
51  amrex::Real latitude_deg = 40.0; ///< solar: site latitude, north positive
52  amrex::Real longitude_deg = -105.0; ///< solar: site longitude, east positive
53  amrex::Real day_of_year = 172.0; ///< solar: day of year
54  amrex::Real time_zero_utc_s = 12.0 * 3600.0; ///< solar: seconds after 00:00 UTC at simulation time zero (the sun follows UTC and the longitude)
55  amrex::Real solar_constant = 1361.0; ///< solar: [W/m2]
56  amrex::Real sw_transmission = 0.7; ///< solar: bulk clear-sky transmission (Bird)
57  amrex::Real sw_diffuse_coeff = 0.5; ///< solar: share of the attenuated beam that arrives as diffuse light
58  // Optical properties, uniform unless the material library below overrides them.
59  amrex::Real albedo = 0.3; ///< Face shortwave albedo
60  amrex::Real albedo_ground = 0.2; ///< Ground albedo for the reflected diffuse term
61  amrex::Real emissivity = 0.9; ///< Face longwave emissivity
62  amrex::Real emissivity_ground = 0.95; ///< Ground emissivity for the ground term
63 
64  // ---- View fractions and longwave ----------------------------------------
65  // Rays per face of the cosine-weighted hemisphere sampled once at
66  // initialisation: n_az azimuths x n_el elevations.
67  int view_n_az = 16;
68  int view_n_el = 8;
69  // Downwelling longwave from the sky: "fixed" uses lw_down as given,
70  // "gray" uses sky_emissivity x sigma x T_air^4 with the air temperature
71  // of the face's fluid cell.
72  std::string lw_mode = "gray";
73  amrex::Real lw_down = 300.0; ///< fixed: sky longwave [W/m2]
74  amrex::Real sky_emissivity = 0.83; ///< gray: effective clear-sky emissivity
75  amrex::Real T_ground = 300.0; ///< Ground temperature for the ground term [K]
76 
77  // ---- Sensible and latent heat -------------------------------------------
78  // Wall function between the face skin temperature and the adjacent fluid
79  // cell: u* from the tangential wind at half a cell from the wall with the
80  // roughness length z0_wall, theta* from the skin-to-air difference with
81  // z0h_wall; H = rho c_p u* theta* (positive out of the face). Neutral on
82  // every face unless stability_correction is set, which applies the
83  // surface layer's similarity functions on roofs. couple_heat = false
84  // diagnoses H without adding it to the temperature equation.
85  amrex::Real z0_wall = 0.01; ///< Momentum roughness of the faces [m]
86  amrex::Real z0h_wall = 0.001; ///< Heat roughness of the faces [m]
87  bool stability_correction = false;
88  bool couple_heat = true; ///< Add the face flux to the temperature equation
89 
90  // ---- Ground heat flux and materials -------------------------------------
91  // Every face carries a slab of n_slab_layers layers between the skin and
92  // the building interior at T_interior; the conduction into it is G. The
93  // slab's conductivity, heat capacity and thickness, and the face's albedo
94  // and emissivity, come from the material library (SLUCM schema) when
95  // material_file is given: material_default for every building, or one
96  // id per building in material_by_building (indexed by building id from
97  // 1). Without a file the uniform values below apply to every face.
98  std::string material_file;
100  std::vector<int> material_by_building;
101  amrex::Real k_therm = 1.0; ///< Uniform conductivity [W/m/K]
102  amrex::Real rho_cp = 1.6e6; ///< Uniform volumetric heat capacity [J/m3/K]
103  amrex::Real thickness = 0.3; ///< Uniform slab thickness [m]
104 
105  // ---- Prognostic balance -------------------------------------------------
106  // With prognostic on, every step solves the massless-skin balance
107  // SW_abs + eps Q_ext + LW_net - H - LE - G = 0 for the skin temperature
108  // of every face by Newton's method (ERF_IBSEBBalance.H), consistent with
109  // the implicit slab step, and stores the fluxes at the solution. Off, the
110  // skin stays at T_skin_init (or the restart value) and the terms are
111  // diagnosed around it, which is what the term-by-term regression tests
112  // use to check each term on its own.
113  bool prognostic = true;
114  amrex::Real T_skin_min = 260.0; ///< Lower bound of the skin temperature [K]
115  amrex::Real T_skin_max = 380.0; ///< Upper bound [K]; raise it for faces under a fire
116  int newton_max_iter = 20; ///< Newton iteration cap per face and step
117  amrex::Real newton_tol_K = 1.0e-3; ///< Newton stops when a step changes T_skin by less than this [K]
118  amrex::Real newton_max_step_K = 20.0; ///< Largest Newton step [K]
119  amrex::Real Q_ext_uniform = 0.0; ///< Uniform external incident flux on every face [W/m2] (test hook)
120 
121  // ---- Wall function beyond neutral ----------------------------------------
122  // stability_correction (above) applies the surface layer's similarity
123  // functions on roofs with the face's own Obukhov length, seeded from the
124  // ground surface layer's 2D Obukhov field at the face's column when
125  // obukhov_seed = "ground" (or from neutral). convective_velocity =
126  // "deardorff" adds a convective velocity scale to the wind the wall
127  // function sees, U_eff^2 = U_tan^2 + (beta w*)^2 with
128  // w* = (g/theta H/(rho c_p) depth)^(1/3) from the previous step's H when it
129  // is out of the face, so u* does not collapse when the wind dies. The
130  // depth is the mixed layer above a roof (z_i - z_face, floored at the
131  // building height; z_i from the bulk Richardson diagnostic on the
132  // horizontal-mean profile, from ERF's surface-layer pblh, or fixed) and
133  // the building height for a wall. All off by default.
134  std::string obukhov_seed = "ground"; ///< "ground" or "neutral"
135  std::string convective_velocity = "none"; ///< "none" or "deardorff"
136  amrex::Real beta_conv = 1.2; ///< Gustiness factor on w*
137  std::string z_i_mode = "bulk_ri"; ///< "bulk_ri", "pblh" or "fixed"
138  amrex::Real z_i = 1000.0; ///< Fixed mixed-layer depth [m] (z_i_mode = fixed, and the fallback)
139  amrex::Real ri_crit = 0.25; ///< Critical bulk Richardson number of the diagnostic
140  amrex::Real obukhov_relax = 0.5; ///< Under-relaxation of the roof's u*, theta* iteration (1 = none), as erf-model #3486
141 
142  /**
143  * Read the ``erf.ibseb.*`` inputs and validate them.
144  *
145  * Only queried, never required: a deck without any ``erf.ibseb`` key gets
146  * the defaults above with the balance off. Validation is skipped when the
147  * balance is off so an unrelated deck cannot abort on an unused key.
148  */
149  void init_params ()
150  {
151  amrex::ParmParse pp("erf.ibseb");
152  pp.query("enable", enable);
153  pp.query("n_slab_layers", n_slab_layers);
154  pp.query("T_skin_init", T_skin_init);
155  pp.query("T_interior", T_interior);
156  pp.query("csv_file", csv_file);
157  pp.query("csv_int", csv_int);
158  pp.query("debug", debug);
159  pp.query("dump_faces_file", dump_faces_file);
160  pp.query("dump_faces_tag_step", dump_faces_tag_step);
161  pp.query("radiation", radiation);
162  pp.query("sun_mode", sun_mode);
163  pp.query("sun_zenith_deg", sun_zenith_deg);
164  pp.query("sun_azimuth_deg", sun_azimuth_deg);
165  pp.query("sw_direct_normal", sw_direct_normal);
166  pp.query("sw_diffuse", sw_diffuse);
167  pp.query("latitude_deg", latitude_deg);
168  pp.query("longitude_deg", longitude_deg);
169  pp.query("day_of_year", day_of_year);
170  pp.query("time_zero_utc_s", time_zero_utc_s);
171  pp.query("solar_constant", solar_constant);
172  pp.query("sw_transmission", sw_transmission);
173  pp.query("sw_diffuse_coeff", sw_diffuse_coeff);
174  pp.query("albedo", albedo);
175  pp.query("albedo_ground", albedo_ground);
176  pp.query("emissivity", emissivity);
177  pp.query("emissivity_ground", emissivity_ground);
178  pp.query("view_n_az", view_n_az);
179  pp.query("view_n_el", view_n_el);
180  pp.query("lw_mode", lw_mode);
181  pp.query("lw_down", lw_down);
182  pp.query("sky_emissivity", sky_emissivity);
183  pp.query("T_ground", T_ground);
184  pp.query("z0_wall", z0_wall);
185  pp.query("z0h_wall", z0h_wall);
186  pp.query("stability_correction", stability_correction);
187  pp.query("couple_heat", couple_heat);
188  pp.query("material_file", material_file);
189  pp.query("material_default", material_default);
190  pp.queryarr("material_by_building", material_by_building);
191  pp.query("k_therm", k_therm);
192  pp.query("rho_cp", rho_cp);
193  pp.query("thickness", thickness);
194  pp.query("prognostic", prognostic);
195  pp.query("T_skin_min", T_skin_min);
196  pp.query("T_skin_max", T_skin_max);
197  pp.query("newton_max_iter", newton_max_iter);
198  pp.query("newton_tol_K", newton_tol_K);
199  pp.query("newton_max_step_K", newton_max_step_K);
200  pp.query("Q_ext_uniform", Q_ext_uniform);
201  pp.query("obukhov_seed", obukhov_seed);
202  pp.query("convective_velocity", convective_velocity);
203  pp.query("beta_conv", beta_conv);
204  pp.query("z_i_mode", z_i_mode);
205  pp.query("z_i", z_i);
206  pp.query("ri_crit", ri_crit);
207  pp.query("obukhov_relax", obukhov_relax);
208  if (enable) {
209  if (radiation != "prescribed") {
210  amrex::Abort("erf.ibseb.radiation: only \"prescribed\" is available in this build");
211  }
212  if (sun_mode != "fixed" && sun_mode != "solar") {
213  amrex::Abort("erf.ibseb.sun_mode must be \"fixed\" or \"solar\"");
214  }
215  if (sun_zenith_deg < 0.0 || sun_zenith_deg > 180.0) { amrex::Abort("erf.ibseb.sun_zenith_deg must be in [0, 180]"); }
216  if (latitude_deg < -90.0 || latitude_deg > 90.0) { amrex::Abort("erf.ibseb.latitude_deg must be in [-90, 90]"); }
217  if (longitude_deg < -180.0 || longitude_deg > 180.0) { amrex::Abort("erf.ibseb.longitude_deg must be in [-180, 180]"); }
218  if (day_of_year < 1.0 || day_of_year > 366.0) { amrex::Abort("erf.ibseb.day_of_year must be in [1, 366]"); }
219  // The sun is computed from UTC (time_zero_utc_s) and the longitude; a
220  // time-zone offset has no place in that and used to cancel silently.
221  if (pp.contains("utc_offset_hours")) {
222  amrex::Abort("erf.ibseb.utc_offset_hours is not an input: the sun follows time_zero_utc_s (UTC) and longitude_deg; remove it");
223  }
224  if (sw_direct_normal < 0.0 || sw_diffuse < 0.0) { amrex::Abort("erf.ibseb.sw_direct_normal and sw_diffuse must be >= 0"); }
225  if (sw_transmission <= 0.0 || sw_transmission > 1.0) { amrex::Abort("erf.ibseb.sw_transmission must be in (0, 1]"); }
226  if (albedo < 0.0 || albedo > 1.0 || albedo_ground < 0.0 || albedo_ground > 1.0) {
227  amrex::Abort("erf.ibseb.albedo and albedo_ground must be in [0, 1]");
228  }
229  if (emissivity <= 0.0 || emissivity > 1.0 || emissivity_ground <= 0.0 || emissivity_ground > 1.0 ||
230  sky_emissivity <= 0.0 || sky_emissivity > 1.0) {
231  amrex::Abort("erf.ibseb emissivities must be in (0, 1]");
232  }
233  if (view_n_az < 1 || view_n_el < 1) { amrex::Abort("erf.ibseb.view_n_az and view_n_el must be >= 1"); }
234  if (lw_mode != "fixed" && lw_mode != "gray") { amrex::Abort("erf.ibseb.lw_mode must be \"fixed\" or \"gray\""); }
235  if (lw_down < 0.0 || T_ground <= 0.0) { amrex::Abort("erf.ibseb.lw_down must be >= 0 and T_ground > 0"); }
236  if (z0_wall <= 0.0 || z0h_wall <= 0.0) { amrex::Abort("erf.ibseb.z0_wall and z0h_wall must be positive [m]"); }
237  if (k_therm <= 0.0 || rho_cp <= 0.0 || thickness <= 0.0) { amrex::Abort("erf.ibseb.k_therm, rho_cp and thickness must be positive"); }
238  if (n_slab_layers > 32) { amrex::Abort("erf.ibseb.n_slab_layers must be <= 32 (the slab kernels keep their layers on the stack)"); }
239  if (n_slab_layers < 1) { amrex::Abort("erf.ibseb.n_slab_layers must be >= 1"); }
240  if (T_skin_init <= 0.0 || T_interior <= 0.0) {
241  amrex::Abort("erf.ibseb.T_skin_init and T_interior must be positive [K]");
242  }
243  if (T_skin_min <= 0.0 || T_skin_max <= T_skin_min) {
244  amrex::Abort("erf.ibseb.T_skin_min must be positive and below T_skin_max");
245  }
246  if (prognostic && (T_skin_init < T_skin_min || T_skin_init > T_skin_max)) {
247  amrex::Abort("erf.ibseb.T_skin_init must lie within [T_skin_min, T_skin_max]");
248  }
249  if (newton_max_iter < 1 || newton_tol_K <= 0.0 || newton_max_step_K <= 0.0) {
250  amrex::Abort("erf.ibseb.newton_max_iter must be >= 1, newton_tol_K and newton_max_step_K positive");
251  }
252  if (Q_ext_uniform < 0.0) { amrex::Abort("erf.ibseb.Q_ext_uniform must be >= 0"); }
253  if (obukhov_seed != "ground" && obukhov_seed != "neutral") { amrex::Abort("erf.ibseb.obukhov_seed must be \"ground\" or \"neutral\""); }
254  if (convective_velocity != "none" && convective_velocity != "deardorff") {
255  amrex::Abort("erf.ibseb.convective_velocity must be \"none\" or \"deardorff\"");
256  }
257  if (z_i_mode != "bulk_ri" && z_i_mode != "pblh" && z_i_mode != "fixed") {
258  amrex::Abort("erf.ibseb.z_i_mode must be \"bulk_ri\", \"pblh\" or \"fixed\"");
259  }
260  if (beta_conv <= 0.0 || z_i <= 0.0 || ri_crit <= 0.0) { amrex::Abort("erf.ibseb.beta_conv, z_i and ri_crit must be positive"); }
261  if (obukhov_relax <= 0.0 || obukhov_relax > 1.0) { amrex::Abort("erf.ibseb.obukhov_relax must be in (0, 1]"); }
262  }
263  }
264 };
265 
266 #endif
ParmParse pp("prob")
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_IBSEBParams.H:25
amrex::Real newton_max_step_K
Largest Newton step [K].
Definition: ERF_IBSEBParams.H:118
std::string csv_file
Per-building report.
Definition: ERF_IBSEBParams.H:30
amrex::Real T_interior
Interior (deep) temperature [K].
Definition: ERF_IBSEBParams.H:29
std::string sun_mode
Definition: ERF_IBSEBParams.H:46
std::string convective_velocity
"none" or "deardorff"
Definition: ERF_IBSEBParams.H:135
amrex::Real T_ground
Ground temperature for the ground term [K].
Definition: ERF_IBSEBParams.H:75
amrex::Real Q_ext_uniform
Uniform external incident flux on every face [W/m2] (test hook)
Definition: ERF_IBSEBParams.H:119
amrex::Real day_of_year
solar: day of year
Definition: ERF_IBSEBParams.H:53
bool prognostic
Definition: ERF_IBSEBParams.H:113
int material_default
Definition: ERF_IBSEBParams.H:99
amrex::Real newton_tol_K
Newton stops when a step changes T_skin by less than this [K].
Definition: ERF_IBSEBParams.H:117
amrex::Real obukhov_relax
Under-relaxation of the roof's u*, theta* iteration (1 = none), as erf-model #3486.
Definition: ERF_IBSEBParams.H:140
amrex::Real z0_wall
Momentum roughness of the faces [m].
Definition: ERF_IBSEBParams.H:85
amrex::Real k_therm
Uniform conductivity [W/m/K].
Definition: ERF_IBSEBParams.H:101
amrex::Real sw_transmission
solar: bulk clear-sky transmission (Bird)
Definition: ERF_IBSEBParams.H:56
bool enable
Master switch.
Definition: ERF_IBSEBParams.H:26
int n_slab_layers
Conduction layers per face.
Definition: ERF_IBSEBParams.H:27
amrex::Real rho_cp
Uniform volumetric heat capacity [J/m3/K].
Definition: ERF_IBSEBParams.H:102
std::string z_i_mode
"bulk_ri", "pblh" or "fixed"
Definition: ERF_IBSEBParams.H:137
amrex::Real thickness
Uniform slab thickness [m].
Definition: ERF_IBSEBParams.H:103
std::string material_file
Definition: ERF_IBSEBParams.H:98
int view_n_az
Definition: ERF_IBSEBParams.H:67
amrex::Real sky_emissivity
gray: effective clear-sky emissivity
Definition: ERF_IBSEBParams.H:74
bool couple_heat
Add the face flux to the temperature equation.
Definition: ERF_IBSEBParams.H:88
amrex::Real ri_crit
Critical bulk Richardson number of the diagnostic.
Definition: ERF_IBSEBParams.H:139
amrex::Real longitude_deg
solar: site longitude, east positive
Definition: ERF_IBSEBParams.H:52
int view_n_el
Definition: ERF_IBSEBParams.H:68
std::vector< int > material_by_building
Definition: ERF_IBSEBParams.H:100
std::string lw_mode
Definition: ERF_IBSEBParams.H:72
amrex::Real albedo_ground
Ground albedo for the reflected diffuse term.
Definition: ERF_IBSEBParams.H:60
bool dump_faces_tag_step
Name each dump by its step (keeps every one) instead of overwriting.
Definition: ERF_IBSEBParams.H:34
amrex::Real emissivity_ground
Ground emissivity for the ground term.
Definition: ERF_IBSEBParams.H:62
void init_params()
Definition: ERF_IBSEBParams.H:149
std::string radiation
Definition: ERF_IBSEBParams.H:41
int csv_int
Steps between report rows; <= 0 disables.
Definition: ERF_IBSEBParams.H:31
amrex::Real beta_conv
Gustiness factor on w*.
Definition: ERF_IBSEBParams.H:136
bool debug
[IBSEB DEBUG] prints: set description at build, per-step summary, per-building rows
Definition: ERF_IBSEBParams.H:32
amrex::Real solar_constant
solar: [W/m2]
Definition: ERF_IBSEBParams.H:55
amrex::Real sw_direct_normal
fixed: direct-normal irradiance [W/m2]
Definition: ERF_IBSEBParams.H:49
std::string dump_faces_file
Per-rank face dump at report time (empty = off)
Definition: ERF_IBSEBParams.H:33
amrex::Real albedo
Face shortwave albedo.
Definition: ERF_IBSEBParams.H:59
amrex::Real T_skin_min
Lower bound of the skin temperature [K].
Definition: ERF_IBSEBParams.H:114
amrex::Real time_zero_utc_s
solar: seconds after 00:00 UTC at simulation time zero (the sun follows UTC and the longitude)
Definition: ERF_IBSEBParams.H:54
amrex::Real sun_zenith_deg
fixed: zenith angle [deg]
Definition: ERF_IBSEBParams.H:47
amrex::Real lw_down
fixed: sky longwave [W/m2]
Definition: ERF_IBSEBParams.H:73
amrex::Real z_i
Fixed mixed-layer depth [m] (z_i_mode = fixed, and the fallback)
Definition: ERF_IBSEBParams.H:138
amrex::Real z0h_wall
Heat roughness of the faces [m].
Definition: ERF_IBSEBParams.H:86
amrex::Real sw_diffuse
fixed: diffuse irradiance on a horizontal surface [W/m2]
Definition: ERF_IBSEBParams.H:50
amrex::Real sun_azimuth_deg
fixed: azimuth clockwise from north [deg]; 180 = sun in the south
Definition: ERF_IBSEBParams.H:48
bool stability_correction
Definition: ERF_IBSEBParams.H:87
amrex::Real T_skin_init
Initial skin temperature [K].
Definition: ERF_IBSEBParams.H:28
amrex::Real latitude_deg
solar: site latitude, north positive
Definition: ERF_IBSEBParams.H:51
std::string obukhov_seed
"ground" or "neutral"
Definition: ERF_IBSEBParams.H:134
amrex::Real sw_diffuse_coeff
solar: share of the attenuated beam that arrives as diffuse light
Definition: ERF_IBSEBParams.H:57
amrex::Real T_skin_max
Upper bound [K]; raise it for faces under a fire.
Definition: ERF_IBSEBParams.H:115
amrex::Real emissivity
Face longwave emissivity.
Definition: ERF_IBSEBParams.H:61
int newton_max_iter
Newton iteration cap per face and step.
Definition: ERF_IBSEBParams.H:116