ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_DataStruct.H
Go to the documentation of this file.
1 #ifndef ERF_DATA_STRUCT_H_
2 #define ERF_DATA_STRUCT_H_
3 
4 #include <string>
5 #include <iostream>
6 
7 #include <AMReX_ParmParse.H>
8 #include <AMReX_Print.H>
9 #include <AMReX_Gpu.H>
10 #include <AMReX_Geometry.H>
11 
12 #include <ERF_Constants.H>
13 #include <ERF_IndexDefines.H>
14 #include <ERF_AdvStruct.H>
15 #include <ERF_DampingStruct.H>
16 #include <ERF_DiffStruct.H>
17 #include <ERF_EBStruct.H>
18 #include <ERF_SpongeStruct.H>
19 #include <ERF_TurbStruct.H>
20 #include <ERF_TurbPertStruct.H>
21 
22 /**
23  * @brief Indices for map scale factors on mass and face grids.
24  */
25 enum MapFacType {
26 // This version assumes isotropic
27  m_x, u_x, v_x, num,
28  m_y = 0, u_y = 1, v_y = 2
29 // This version allows for non-isotropic
30 // m_x, u_x, v_x,
31 // m_y, u_y, v_y, num
32 };
33 
34 /**
35  * @brief Stress tensor component indices.
36  */
37 enum TauType {
39 };
40 
41 /**
42  * @brief Initial-condition source used to populate the ERF state.
43  */
44 AMREX_ENUM(InitType,
45  None, Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, ConstantDensity, ConstantDensityLinearTheta,
46  Isentropic, MoistBaseState, HindCast
47 );
48 
49 /**
50  * @brief Interpretation of input sounding profiles.
51  */
52 AMREX_ENUM(SoundingType,
53  ConstantDensity, Ideal, Isentropic, DryIsentropic
54 );
55 
56 /**
57  * @brief Large-scale atmospheric boundary-layer driver type.
58  */
59 AMREX_ENUM(ABLDriverType,
60  None, PressureGradient, GeostrophicWind
61 );
62 
63 /**
64  * @brief Multilevel coupling strategy.
65  */
66 AMREX_ENUM(CouplingType,
67  OneWay, TwoWay
68 );
69 
70 /**
71  * @brief Acoustic substepping strategy.
72  */
73 AMREX_ENUM(SubsteppingType,
74  None, Implicit
75 );
76 
77 /**
78  * @brief Vertical mesh representation.
79  */
80 AMREX_ENUM(MeshType,
81  ConstantDz, StretchedDz, VariableDz
82 );
83 
84 /**
85  * @brief Terrain and immersed-boundary representation.
86  */
87 AMREX_ENUM(TerrainType,
88  None, StaticFittedMesh, MovingFittedMesh, EB, ImmersedForcing
89 );
90 
91 /**
92  * @brief Building representation.
93  */
94 AMREX_ENUM(BuildingsType,
95  None, ImmersedForcing
96 );
97 
98 /**
99  * @brief Moisture transport representation.
100  */
101 AMREX_ENUM(MoistureModelType,
102  Eulerian, Lagrangian, Undefined
103 );
104 
105 /**
106  * @brief Moisture and microphysics model.
107  */
108 AMREX_ENUM(MoistureType,
109  SAM, SAM_NoIce, SAM_NoPrecip_NoIce, Kessler, Kessler_NoRain, SatAdj, Morrison, Morrison_NoIce, WSM6, SuperDroplets, MoistNoCondensation, None
110 );
111 
112 /**
113  * @brief Wind-farm model.
114  */
115 AMREX_ENUM(WindFarmType,
116  Fitch, EWP, SimpleAD, GeneralAD, None
117 );
118 
119 /**
120  * @brief Coordinate system used for wind-farm locations.
121  */
122 AMREX_ENUM(WindFarmLocType,
123  lat_lon, x_y, None
124 );
125 
126 /**
127  * @brief Land-surface model.
128  */
129 AMREX_ENUM(LandSurfaceType,
130  SLM, NOAHMP, OceanSurf, None
131 );
132 
133 /**
134  * @brief Radiation model.
135  */
136 AMREX_ENUM(RadiationType,
137  None, RRTMGP
138 );
139 
140 /**
141  * @brief Coordinate-axis selector.
142  */
143 enum struct Coord {
144  x, y, z
145 };
146 
147 // These are used as integers so must be enum not enum struct
148 /**
149  * @brief Rayleigh damping profile component indices.
150  */
151 enum Rayleigh {
153 };
154 
155 // These are used as integers so must be enum not enum struct
156 /**
157  * @brief Sponge reference-state component indices.
158  */
159 enum Sponge {
161 };
162 
163 /**
164  * @brief Component indices for moisture species in the conserved state.
165  */
167  int qv = -1; // Water vapor
168  int qc = -1; // Cloud liquid water
169  int qi = -1; // Cloud ice
170  int qr = -1; // Rain
171  int qs = -1; // Snow
172  int qg = -1; // Graupel
173  int nc = -1; // number concentration for cloud liquid water
174  int ni = -1; // number concentration for cloud ice
175  int nr = -1; // number concentration for rain
176  int ns = -1; // number concentration for snow
177  int ng = -1; // number concentration for graupel
178 
179  /**
180  * @brief Construct moisture component indices from conserved-state component numbers.
181  * @param qv_comp Water vapor component index.
182  * @param qc_comp Cloud liquid water component index.
183  * @param qi_comp Cloud ice component index.
184  * @param qr_comp Rain component index.
185  * @param qs_comp Snow component index.
186  * @param qg_comp Graupel component index.
187  * @param nc_comp Cloud liquid water number concentration component index.
188  * @param ni_comp Cloud ice number concentration component index.
189  * @param nr_comp Rain number concentration component index.
190  * @param ns_comp Snow number concentration component index.
191  * @param ng_comp Graupel number concentration component index.
192  */
193  MoistureComponentIndices (int qv_comp, int qc_comp,
194  int qi_comp=-1,
195  int qr_comp=-1,
196  int qs_comp=-1,
197  int qg_comp=-1,
198  int nc_comp=-1,
199  int ni_comp=-1,
200  int nr_comp=-1,
201  int ns_comp=-1,
202  int ng_comp=-1)
203  : qv(qv_comp), qc(qc_comp), qi(qi_comp), qr(qr_comp), qs(qs_comp), qg(qg_comp),
204  nc(nc_comp), ni(ni_comp), nr(nr_comp), ns(ns_comp), ng(ng_comp) {}
205 
206  /**
207  * @brief Construct an empty set of moisture component indices.
208  */
210 };
211 
212 /**
213  * @var MoistureComponentIndices::qv
214  * @brief Water vapor component index.
215  * @var MoistureComponentIndices::qc
216  * @brief Cloud liquid water component index.
217  * @var MoistureComponentIndices::qi
218  * @brief Cloud ice component index.
219  * @var MoistureComponentIndices::qr
220  * @brief Rain component index.
221  * @var MoistureComponentIndices::qs
222  * @brief Snow component index.
223  * @var MoistureComponentIndices::qg
224  * @brief Graupel component index.
225  * @var MoistureComponentIndices::nc
226  * @brief Cloud liquid water number concentration component index.
227  * @var MoistureComponentIndices::ni
228  * @brief Cloud ice number concentration component index.
229  * @var MoistureComponentIndices::nr
230  * @brief Rain number concentration component index.
231  * @var MoistureComponentIndices::ns
232  * @brief Snow number concentration component index.
233  * @var MoistureComponentIndices::ng
234  * @brief Graupel number concentration component index.
235  */
236 
237 /**
238  * Container holding many of the algorithmic options and parameters
239  */
240 
241 struct SolverChoice {
242  public:
243  /**
244  * @brief Read solver-wide algorithmic options from the input parameter database.
245  * @param max_level Maximum AMR level configured for the run.
246  * @param pp_prefix ParmParse prefix for the ERF input namespace.
247  */
248  void init_params (int max_level, std::string pp_prefix)
249  {
250  amrex::ParmParse pp(pp_prefix);
251 
252  bool bogus_bool;
253  if (pp.query("use_terrain",bogus_bool) > 0) {
254  amrex::Error("The input use_terrain is deprecated. Set terrain_type instead.");
255  }
256 
257  if (pp.query("use_moist_background",bogus_bool) > 0) {
258  amrex::Error("The input use_moist_background is deprecated. Set init_type = MoistBaseState instead.");
259  }
260 
261  // Do we set map scale factors to myhalf instead of 1 for testing?
262  pp.query("test_mapfactor", test_mapfactor);
263 
264  // Which horizontal pressure gradient formulation to use with terrain fitted coords?
265  // 0: dp/dx with dp/dz correction (default)
266  // 1: gradient of vertically interpolated p, see Klemp 2011
267  pp.query("gradp_type", gradp_type);
269 
270  // For the lateral pressure gradient to be used in the momentum equation, should we
271  // take the x- and y-derivatives of the perturbational pressure or the full pressure?
272  pp.query("use_pert_pres_gradient", use_pert_pres_gradient);
273 
274  // What type of moisture model to use?
275  moisture_type = MoistureType::None; // Default
276  if (pp.query("moisture_type",moisture_type) > 0) {
277  amrex::Error("The input moisture_type is deprecated. Set moisture_model instead.");
278  }
279 
280  pp.query_enum_case_insensitive("moisture_model",moisture_type);
281  if (moisture_type == MoistureType::Morrison) {
283  RhoQ1_comp, // water vapor
284  RhoQ2_comp, // cloud water
285  RhoQ3_comp, // cloud ice
286  RhoQ4_comp, // rain
287  RhoQ5_comp, // snow
288  RhoQ6_comp, // graupel
289  RhoQ7_comp, // number concentration of cloud water
290  RhoQ8_comp, // number concentration of cloud ice
291  RhoQ9_comp, // number concentration of rain
292  RhoQ10_comp, // number concentration of snow
293  RhoQ11_comp // number concentration of graupel
294  );
295  } else if ( (moisture_type == MoistureType::WSM6) ||
296  (moisture_type == MoistureType::SAM) ) {
298  RhoQ1_comp, // water vapor
299  RhoQ2_comp, // cloud water
300  RhoQ3_comp, // cloud ice
301  RhoQ4_comp, // rain
302  RhoQ5_comp, // snow
303  RhoQ6_comp // graupel
304  );
305  } else if ( (moisture_type == MoistureType::Morrison_NoIce) ||
306  (moisture_type == MoistureType::SAM_NoIce) ) {
308  RhoQ1_comp, // water vapor
309  RhoQ2_comp, // cloud water
310  -1, // cloud ice
311  RhoQ4_comp // rain
312  );
313  } else if ( (moisture_type == MoistureType::SAM_NoPrecip_NoIce) ||
314  (moisture_type == MoistureType::Kessler_NoRain) ||
315  (moisture_type == MoistureType::SatAdj) ||
316  (moisture_type == MoistureType::MoistNoCondensation) ) {
318  RhoQ1_comp, // water vapor
319  RhoQ2_comp // cloud water
320  );
321  } else if (moisture_type == MoistureType::Kessler) {
323  RhoQ1_comp, // water vapor
324  RhoQ2_comp, // cloud water
325  -1, // cloud ice
326  RhoQ3_comp // rain
327  );
328  } else if (moisture_type == MoistureType::SuperDroplets) {
330  RhoQ1_comp, // water vapor
331  RhoQ2_comp, // cloud water
332  -1, // cloud ice
333  RhoQ3_comp // rain
334  );
335  }
336 
337  // Set a default for dry
338  buoyancy_type.resize(max_level+1);
339  for (int i = 0; i <= max_level; ++i) {
340  buoyancy_type[i] = 1; // uses Rhoprime
341  }
342 
343  // Set a default for moist
344  if (moisture_type != MoistureType::None) {
345  if ( !(moisture_type == MoistureType::Kessler_NoRain ||
346  moisture_type == MoistureType::SAM ||
347  moisture_type == MoistureType::SAM_NoIce ||
348  moisture_type == MoistureType::SAM_NoPrecip_NoIce ||
349  moisture_type == MoistureType::Morrison ||
350  moisture_type == MoistureType::Morrison_NoIce ||
351  moisture_type == MoistureType::WSM6 ||
352  moisture_type == MoistureType::SatAdj) )
353  {
354  for (int i = 0; i <= max_level; ++i) {
355  buoyancy_type[i] = 2; // uses Tprime
356  }
357  }
358 
359  pp.query("moisture_tight_coupling",moisture_tight_coupling);
360  }
361 
362  // Which expression (1,2/3 or 4) to use for buoyancy
363  int default_buoyancy_type = buoyancy_type[0];
364  read_int_string(max_level, "buoyancy_type", buoyancy_type, default_buoyancy_type);
365 
366  // What type of land surface model to use
367  lsm_type = LandSurfaceType::None; // Default
368  pp.query_enum_case_insensitive("land_surface_model",lsm_type);
369 
370  read_int_string(max_level, "is_land", is_land, 1);
371  for (int lev = 0; lev <= max_level; ++lev) {
372  if (is_land[lev] == 1) {
373  amrex::Print() << "Level " << lev << " is land" << std::endl;
374  } else if (is_land[lev] == 0) {
375  amrex::Print() << "Level " << lev << " is water" << std::endl;
376  } else {
377  amrex::Error("is_land should be 0 or 1");
378  }
379  }
380 
381  // What type of radiation model to use
382  rad_type = RadiationType::None; // Default
383  pp.query_enum_case_insensitive("radiation_model", rad_type);
384 
385  // Verify that radiation model cannot be RRTMGP if ERF was not compiled with RRTMGP
386 #ifndef ERF_USE_RRTMGP
387  if (rad_type == RadiationType::RRTMGP)
388  {
389  amrex::Error("ERF was not compiled with RRTMGP enabled!");
390  }
391 #endif
392 
393  // Is the terrain none, static or moving?
394  std::string terrain_type_temp = "";
395  pp.query("terrain_type", terrain_type_temp);
396  if (terrain_type_temp == "Moving") {
397  amrex::Warning("erf.terrain_type = Moving is deprecated; please replace Moving by MovingFittedMesh");
398  terrain_type = TerrainType::MovingFittedMesh;
399  } else if (terrain_type_temp == "Static") {
400  amrex::Warning("erf.terrain_type = Static is deprecated; please replace Static by StaticFittedMesh");
401  terrain_type = TerrainType::StaticFittedMesh;
402  } else {
403  pp.query_enum_case_insensitive("terrain_type",terrain_type);
404  }
405 
406  // Get buildings type
407  std::string buildings_type_temp = "";
408  pp.query("buildings_type", buildings_type_temp);
409  if (buildings_type_temp == "ImmersedForcing") {
410  buildings_type = BuildingsType::ImmersedForcing;
411  }
412 
413  //
414  // Read the init_type here to make sure we correctly set the mesh and terrain types
415  //
416  std::string init_type_temp_string;
417 
418  int found = pp.query("init_type",init_type_temp_string);
419 
420  if ( (init_type_temp_string == "Real") || (init_type_temp_string == "real") ) {
421  amrex::Error("erf.init_type = Real is deprecated; please replace Real by WRFInput");
422  } else if ( (init_type_temp_string == "Ideal") || (init_type_temp_string == "ideal") ) {
423  amrex::Error("erf.init_type = Ideal is deprecated; please replace Ideal by WRFInput");
424  } else {
425  pp.query_enum_case_insensitive("init_type",init_type);
426  use_real_bcs = ( (init_type == InitType::WRFInput) || (init_type == InitType::Metgrid) );
427  }
428 
429  if ( (init_type == InitType::WRFInput) || (init_type == InitType::Metgrid) ) {
430  if (terrain_type != TerrainType::StaticFittedMesh) {
431  amrex::Error("Only terrain_type = StaticFittedMesh are allowed with init_type = WRFInput or Metgrid");
432  }
433  }
434 
435  if (init_type == InitType::MoistBaseState) {
436  if (moisture_type == MoistureType::None) {
437  amrex::Error("Makes no sense to have moist base state with no moisture model");
438  }
439  }
440 
441  if (init_type == InitType::WRFInput) {
442  if (moisture_type == MoistureType::None) {
443  amrex::Error("Can't have moisture_type = None with init_type = WRFInput");
444  }
445 
446  // NetCDF wrfbdy lateral boundary file
447  std::string nc_bdy_file_temp_string;
448  bool has_bdy = pp.query("nc_bdy_file", nc_bdy_file_temp_string);
449  if (!has_bdy) use_real_bcs = false;
450 
451  bool use_real_bcs_temp = use_real_bcs;
452  pp.query("use_real_bcs", use_real_bcs_temp);
453  if (use_real_bcs && !use_real_bcs_temp) {
454  use_real_bcs = false;
455  }
456  }
457 
458  if (found == 0 || init_type == InitType::None) {
459  amrex::Print() << "init_type must now be set. The options are " << std::endl;
460  amrex::Print() << " Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, " << std::endl;
461  amrex::Print() << " ConstantDensity, Isentropic, MoistBaseState, or HindCast " << std::endl;
462  amrex::Error("Please add a string for init_type to your inputs file or command line");
463  }
464 
465  // How to interpret input_sounding
466  if (init_type == InitType::Input_Sounding) {
467  pp.query_enum_case_insensitive("sounding_type",sounding_type);
468  }
469 
470  if (terrain_type == TerrainType::StaticFittedMesh ||
471  terrain_type == TerrainType::MovingFittedMesh) {
472  mesh_type = MeshType::VariableDz;
473  }
474 
475  if ( (moisture_type == MoistureType::SAM ||
476  moisture_type == MoistureType::SAM_NoIce ||
477  moisture_type == MoistureType::SAM_NoPrecip_NoIce ) &&
478  (mesh_type == MeshType::VariableDz) )
479  {
480  amrex::Abort("SAM is not correct with variable dz -- choose another moisture model");
481  }
482 
483  pp.query("grid_stretching_ratio", grid_stretching_ratio);
484  if (grid_stretching_ratio != 0) {
486  "The grid stretching ratio must be greater than 1");
487  }
488  if (grid_stretching_ratio >= 1) {
489  if (terrain_type == TerrainType::None) {
490  terrain_type = TerrainType::StaticFittedMesh;
491  }
492  if (mesh_type == MeshType::ConstantDz) {
493  mesh_type = MeshType::StretchedDz;
494  }
495  pp.query("zsurface", zsurf);
496  if (zsurf != zero) {
497  amrex::Print() << "Nominal zsurface height != 0, may result in unexpected behavior"
498  << std::endl;
499  }
500  pp.get("initial_dz", dz0);
501  }
502 
503  int n_zlevels = pp.countval("terrain_z_levels");
504  if (n_zlevels > 0)
505  {
506  if (terrain_type == TerrainType::None) {
507  terrain_type = TerrainType::StaticFittedMesh;
508  }
509  if (mesh_type == MeshType::ConstantDz) {
510  mesh_type = MeshType::StretchedDz;
511  }
512  }
513 
514  // Use lagged_delta_rt in the fast integrator?
515  pp.query("use_lagged_delta_rt", use_lagged_delta_rt);
516 
517  // Keep the default wrf grid or remake our own
518  pp.query("use_wrf_height_grid",use_wrf_height_grid);
519 
520  // Rebalance wrf state?
521  pp.query("rebalance_wrf_input", rebalance_wrf_input);
522 
523  // Must rebalance if not using WRF grid
525  amrex::Print() << "Must rebalance when not using WRF height grid. Setting rebalance_wrf_input to true \n";
526  rebalance_wrf_input = true;
527  }
528 
529  // These default to true but are used for unit testing
530  pp.query("use_gravity", use_gravity);
531 
532  // Initializing from Metgrid or WRFInput without gravity makes no sense
533  if ( !use_gravity && ( (init_type == InitType::WRFInput) || (init_type == InitType::Metgrid) ) ) {
534  amrex::Print() << "Setting use_gravity to true due to init_type = WRFInput / Metgrid " << std::endl;
535  use_gravity = true;
536  }
537 
539 
540  pp.query("c_p", c_p);
541  rdOcp = R_d / c_p;
542 
543  // *******************************************************************************
544  // Read anelastic etc and over-ride if necessary
545  // *******************************************************************************
546 
547  read_int_string(max_level, "anelastic", anelastic, 0);
548  read_int_string(max_level, "fixed_density", fixed_density, 0);
549  read_int_string(max_level, "project_initial_velocity", project_initial_velocity, 0);
550 
551  bool any_anelastic = false;
552  bool any_compress = false;
553  for (int i = 0; i <= max_level; ++i) {
554  if (anelastic[i] == 1) {
556  fixed_density[i] = 1; // We default to true but are allowed to override below
557  buoyancy_type[i] = 3; // (This isn't actually used when anelastic is set)
558  any_anelastic = true;
559  } else {
560  any_compress = true;
561  }
562  }
563 
564  // Want to have different immersed forcing defaults depending on anelastic or fully compressible.
565  // We should have different starting values because the stability of the method is dependent on dt.
566  // dt is coarser for anelastic --> need to loosen stiffness of immersed forcing.
567  if (any_anelastic) {
568  immersed_forcing_substep = false;
569  if_Cd_momentum = amrex::Real(50.0);
570  if_Cd_scalar = amrex::Real(5.0);
571  } else {
573  if_Cd_momentum = amrex::Real(500.0);
574  if_Cd_scalar = amrex::Real(50.0);
575  }
576 
577  // *******************************************************************************
578  // Read substepping_type and allow for different values at each level
579  // *******************************************************************************
580  substepping_type.resize(max_level+1);
581 
582  for (int i = 0; i <= max_level; i++) {
583  substepping_type[i] = SubsteppingType::Implicit;
584  }
585 
586  for (int i = 0; i <= max_level; i++) {
588  pp, "substepping_type", substepping_type[i], i, max_level);
589  }
590 
591  pp.query("substepping_diag", substepping_diag);
592 
593  pp.query("beta_s", beta_s);
594 
595 
596 
597  // *******************************************************************************
598  // Error check on deprecated input
599  // *******************************************************************************
600  int nvals_old = pp.countval("no_substepping");
601  if (nvals_old > 0) {
602  amrex::Error("The no_substepping flag is deprecated -- set substepping_type instead");
603  }
604 
605  // *******************************************************************************
606 
607  pp.query("ncorr", ncorr);
608  pp.query("poisson_abstol", poisson_abstol);
609  pp.query("poisson_reltol", poisson_reltol);
610 #ifdef AMREX_USE_FLOAT
611  poisson_abstol = amrex::max(poisson_abstol,amrex::Real(1e-6));
612  poisson_reltol = amrex::max(poisson_reltol,amrex::Real(1e-6));
613 #endif
614  for (int lev = 0; lev <= max_level; lev++) {
615  if (anelastic[lev] != 0)
616  {
617  substepping_type[lev] = SubsteppingType::None;
618  }
619  }
620 
621  pp.query("force_stage1_single_substep", force_stage1_single_substep);
622 
623  // Include Coriolis forcing?
624  pp.query("use_coriolis", use_coriolis);
625  pp.query("variable_coriolis", variable_coriolis);
626 
627  // Include four stream radiation approximation
628  pp.query("four_stream_radiation", four_stream_radiation);
629 
630  // flags for whether to apply other source terms in substep only
631  pp.query("immersed_forcing_substep", immersed_forcing_substep); // apply immersed forcing source terms in substep only
632  pp.query("forest_substep", forest_substep); // apply canopy-related source terms in substep only
633 
634  // immersed forcing parameters
635  pp.query("if_Cd_momentum", if_Cd_momentum);
636  pp.query("if_Cd_scalar", if_Cd_scalar);
637  pp.query("if_implicit_drag", if_implicit_drag); // flag for implicit vs. explicit drag formulation
638  pp.query("if_z0", if_z0);
639  pp.query("if_surf_temp_flux", if_surf_temp_flux);
640  pp.query("if_init_surf_temp", if_init_surf_temp);
641 
642  pp.query("if_surf_heating_rate", if_surf_heating_rate);
643 
644  // Modify rate to be in units of K / s rather than K / hr
645  if_surf_heating_rate /= amrex::Real(3600.0); // [K/s]
646 
647  pp.query("if_Olen", if_Olen_in);
648  pp.query("if_use_most",if_use_most);
649  pp.query("if_stability_correction",if_stability_correction);
650  pp.query("if_ws_floor",if_ws_floor);
651  pp.query("if_damp_alpha",if_damp_alpha);
652 
653  if ((if_init_surf_temp > zero && if_surf_temp_flux != amrex::Real(1e-8)) ||
654  (if_init_surf_temp > zero && if_Olen_in != amrex::Real(1e-8)) ||
655  (if_Olen_in != amrex::Real(1e-8) && if_surf_temp_flux != amrex::Real(1e-8)))
656  {
657  amrex::Error("Can only specify one of init_surf_temp, surf_temp_flux, or Olen");
658  }
659 
660  // Flag to do MOST rotations with terrain
661  pp.query("use_rotate_surface_flux",use_rotate_surface_flux);
663  AMREX_ASSERT_WITH_MESSAGE(terrain_type != TerrainType::None,"MOST stress rotations are only valid with terrain!");
664  }
665 
666  // Which external forcings?
667  abl_driver_type = ABLDriverType::None; // Default: no ABL driver for simulating classical fluid dynamics problems
668  pp.query_enum_case_insensitive("abl_driver_type",abl_driver_type);
669  pp.query("const_massflux_u", const_massflux_u);
670  pp.query("const_massflux_v", const_massflux_v);
671  pp.query("const_massflux_tau", const_massflux_tau);
672  pp.query("const_massflux_layer_lo", const_massflux_layer_lo);
673  pp.query("const_massflux_layer_hi", const_massflux_layer_hi);
674 
675  // Which type of inflow turbulent generation
676  pert_type.resize(max_level+1);
677  for (int lev = 0; lev <= max_level; ++lev) {
678  pert_type[lev] = PerturbationType::None; // Default
680  pp, "perturbation_type", pert_type[lev], lev, max_level);
681  }
682 
683  amrex::Vector<amrex::Real> abl_pressure_grad_in = {zero, zero, zero};
684  pp.queryarr("abl_pressure_grad",abl_pressure_grad_in);
685  for(int i = 0; i < AMREX_SPACEDIM; ++i) abl_pressure_grad[i] = abl_pressure_grad_in[i];
686 
687  amrex::Vector<amrex::Real> abl_geo_forcing_in = {zero, zero, zero};
688  if(pp.queryarr("abl_geo_forcing",abl_geo_forcing_in)) {
689  amrex::Print() << "Specified abl_geo_forcing: (";
690  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
691  abl_geo_forcing[i] = abl_geo_forcing_in[i];
692  amrex::Print() << abl_geo_forcing[i] << " ";
693  }
694  amrex::Print() << ")" << std::endl;
695  }
696 
697  if (use_coriolis)
698  {
700  }
701 
702  pp.query("add_custom_rhotheta_forcing", custom_rhotheta_forcing);
703  pp.query("add_custom_moisture_forcing", custom_moisture_forcing);
704  pp.query("add_custom_w_subsidence", custom_w_subsidence);
705  pp.query("add_do_theta_advection", do_theta_advection); // If true, apply custom subsidence to (rho*theta) when add_custom_w_subsidence is used
706  pp.query("add_do_mom_advection", do_mom_advection); // If true, apply custom subsidence to momentum when add_custom_w_subsidence is used
707  pp.query("add_custom_geostrophic_profile", custom_geostrophic_profile);
708  pp.query("custom_forcing_uses_primitive_vars", custom_forcing_prim_vars);
709  pp.query("spatial_rhotheta_forcing", spatial_rhotheta_forcing);
710  pp.query("spatial_moisture_forcing", spatial_moisture_forcing);
711 
712  pp.query("nudging_from_input_sounding", nudging_from_input_sounding);
713 
716  "Should not have both abl_geo_wind_table and custom_geostrophic_profile set.");
717 
718  pp.query("Ave_Plane", ave_plane);
719 
720  // Use numerical diffusion?
721  pp.query("num_diff_coeff",num_diff_coeff);
723  "Numerical diffusion coefficient must be between 0 & one");
725  if (use_num_diff) {
726  amrex::Print() << "6th-order numerical diffusion turned on with coefficient = "
727  << num_diff_coeff << std::endl;
728  num_diff_coeff *= amrex::Math::powi<-6>(two);
729  }
730 
731  advChoice.init_params(pp_prefix);
732  diffChoice.init_params(pp_prefix);
733  dampingChoice.init_params(pp_prefix);
734  spongeChoice.init_params(pp_prefix);
735  ebChoice.init_params(pp_prefix);
736 
737  turbChoice.resize(max_level+1);
738  for (int lev = 0; lev <= max_level; lev++) {
739  turbChoice[lev].init_params(lev,max_level,pp_prefix);
740  }
741 
742  vert_implicit_fac.resize(max_level+1);
743  for (int lev = 0; lev <= max_level; lev++) {
744  vert_implicit_fac[lev].resize(3);
745  vert_implicit_fac[lev][0] = one;
746  vert_implicit_fac[lev][1] = one;
747  vert_implicit_fac[lev][2] = zero;
748  }
749 
750  // YSU PBL: use consistent coriolis frequency
751  for (int lev = 0; lev <= max_level; lev++) {
752  if (turbChoice[lev].pbl_ysu_use_consistent_coriolis) {
753  if (use_coriolis) {
754  turbChoice[lev].pbl_ysu_coriolis_freq = coriolis_factor * sinphi;
755  if (lev == 0) {
756  amrex::Print() << "YSU PBL using ERF coriolis frequency: " << turbChoice[lev].pbl_ysu_coriolis_freq << std::endl;
757  }
758  } else {
759  amrex::Error("YSU cannot use ERF coriolis frequency if not using coriolis");
760  }
761  }
762  }
763  // MRF
764  for (int lev = 0; lev <= max_level; lev++) {
765  if (turbChoice[lev].pbl_ysu_use_consistent_coriolis) {
766  if (use_coriolis) {
767  turbChoice[lev].pbl_ysu_coriolis_freq = coriolis_factor * sinphi;
768  if (lev == 0) {
769  amrex::Print() << "MRF PBL using ERF coriolis frequency: " << turbChoice[lev].pbl_ysu_coriolis_freq << std::endl;
770  }
771  } else {
772  amrex::Error("MRF cannot use ERF coriolis frequency if not using coriolis");
773  }
774  }
775  }
776 
777  // What's the strength of the bdy nudging?
778  pp.query("bdy_nudge_factor",bdy_nudge_factor);
779 
780  // Optionally use the dry-air density reconstructed from wrfbdy.
781  pp.query("use_wrf_bdy_density", use_wrf_bdy_density);
782  pp.query("bdy_rho_nudge_factor", bdy_rho_nudge_factor);
783 
784  // Which approach to nudging the moist variables in the boundary region?
785  pp.query("bdy_moist_nudge_type",bdy_moist_nudge_type);
786 
787  // Are me transporting the scalar component?
788  pp.query("transport_scalar",transport_scalar);
789 
790  for (int lev = 0; lev <= max_level; ++lev) {
791  if (turbChoice[lev].uses_eamxx_shoc()) {
792  use_eamxx_shoc = true;
793  }
794  if (turbChoice[lev].uses_native_shoc()) {
795  use_native_shoc = true;
796  }
797  }
798 
799  // Implicit vertical diffusion (not available with SHOC family)
800  if (uses_shoc_family()) {
801  amrex::Print() << "Turning off native vertical implicit solve at all levels with SHOC family PBL scheme." << std::endl;
802  for (int lev = 0; lev <= max_level; lev++) {
803  vert_implicit_fac[lev][0] = zero;
804  vert_implicit_fac[lev][1] = zero;
805  vert_implicit_fac[lev][2] = zero;
806  }
807  } else {
808  // This controls the time-centering of the vertical differences in the diffusive term
809  bool do_vert_implicit = true;
810  pp.query("vert_implicit", do_vert_implicit);
811 
812  if (!do_vert_implicit) {
813  for (int lev = 0; lev <= max_level; lev++) {
814  amrex::Print() << "Turning off native vertical implicit solve from vert_implicit flag at level " << lev << std::endl;
815  vert_implicit_fac[lev][0] = zero;
816  vert_implicit_fac[lev][1] = zero;
817  vert_implicit_fac[lev][2] = zero;
818  }
819  } else {
820 
821  for (int lev = 0; lev <= max_level; lev++) {
822  if (anelastic[lev]) {
823  amrex::Print() << "Turning off native vertical implicit solve flag because anelastic at level " << lev << std::endl;
824  vert_implicit_fac[lev][0] = zero;
825  vert_implicit_fac[lev][1] = zero;
826  vert_implicit_fac[lev][2] = zero;
827  }
828  }
829 
830  // This may be one value for all RK stages or a different value in each stage
831  int n_impfac = pp.countval("vert_implicit_fac");
832  AMREX_ALWAYS_ASSERT(n_impfac == 0 || n_impfac == 1 || n_impfac==3);
833  if (n_impfac > 0 && do_vert_implicit) {
834  amrex::Print() << "Overriding defaults with specified implicit factor(s)" << std::endl;
835  }
836 
837  if (n_impfac == 1) {
838  amrex::Real fac_in;
839  pp.get("vert_implicit_fac", fac_in);
840  for (int lev = 0; lev <= max_level; lev++) {
841  for (int i=0; i<3; ++i) {
842  vert_implicit_fac[lev][i] = fac_in;
843  }
844  }
845  } else if (n_impfac == 3) {
846  for (int lev = 0; lev <= max_level; lev++) {
847  pp.getarr("vert_implicit_fac", vert_implicit_fac[lev]);
848  }
849  }
850 
851  // If true (default), include implicit contributions to vertical
852  // thermal diffusion
853  pp.query("implicit_thermal_diffusion", implicit_thermal_diffusion);
854 
855  // If true (default), include implicit contributions to vertical
856  // moisture diffusion
857  pp.query("implicit_moisture_diffusion", implicit_moisture_diffusion);
858 
859  // If true (default), include implicit contributions to vertical
860  // KE diffusion
861  pp.query("implicit_ke_diffusion", implicit_ke_diffusion);
862 
863  // If true (default), include implicit contributions in tau13, tau23,
864  // (and if ERF_IMPLICIT_W is set, tau33) to correct u, v, (and w).
865  pp.query("implicit_momentum_diffusion", implicit_momentum_diffusion);
866 
867  // This controls when the vertical implicit solve for the diffusive terms will happen relative to
868  // the acoustic substepping (if it happens, i.e. if any of the implicit_fac > zero)
869  // The default is true (i.e. that it happens before the acoustic substepping).
870  pp.query("implicit_before_substep", implicit_before_substep);
871  for (int lev = 0; lev <= max_level; lev++) {
872  if ( (substepping_type[lev] == SubsteppingType::None) && !implicit_before_substep) {
873  amrex::Print() << "implicit_before_substep cannot be false without substepping; setting to true." << "\n";
875  }
876  }
877 
878  // Do not allow implicit vertical diff with EB
879 
880  if (terrain_type == TerrainType::EB) {
881  for (int lev = 0; lev <= max_level; lev++) {
882  if (do_vert_implicit) {
883  amrex::Print() << "Implicit diffusion is not supported with EB; turning off at level " << lev << "\n";
884  vert_implicit_fac[lev][0] = zero;
885  vert_implicit_fac[lev][1] = zero;
886  vert_implicit_fac[lev][2] = zero;
887  }
888  }
889  }
890 
895  amrex::Print() << "Thermal, moisture, KE, and momentum diffusion are all turned off; turning off vertical implicit solve." << std::endl;
896  for (int lev = 0; lev <= max_level; lev++) {
897  vert_implicit_fac[lev][0] = zero;
898  vert_implicit_fac[lev][1] = zero;
899  vert_implicit_fac[lev][2] = zero;
900  }
901  }
902  } // do_vert_implicit
903  } // uses_shoc_family
904 
905  // Which type of multilevel coupling
906  coupling_type = CouplingType::TwoWay; // Default
907  pp.query_enum_case_insensitive("coupling_type",coupling_type);
908 
909  // Test for hybrid (compressible + anelastic) -- in this case we must use one-way coupling
910  if (any_anelastic && any_compress) {
911  coupling_type = CouplingType::OneWay;
912  }
913 
914  // Which type of windfarm model
915  windfarm_type = WindFarmType::None; // Default
916  pp.query_enum_case_insensitive("windfarm_type",windfarm_type);
917 
918  windfarm_loc_type = WindFarmLocType::None;
919  pp.query_enum_case_insensitive("windfarm_loc_type",windfarm_loc_type);
920 
921  pp.query("windfarm_loc_table", windfarm_loc_table);
922  pp.query("windfarm_spec_table", windfarm_spec_table);
923  pp.query("windfarm_blade_table", windfarm_blade_table);
924  pp.query("windfarm_airfoil_tables", windfarm_airfoil_tables);
925  pp.query("windfarm_spec_table_extra", windfarm_spec_table_extra);
926 
927  // Sampling distance upstream of the turbine to find the
928  // incoming free stream velocity as a factor of the diameter of the
929  // turbine. ie. the sampling distance will be this number multiplied
930  // by the diameter of the turbine
931  pp.query("sampling_distance_by_D", sampling_distance_by_D);
932  pp.query("turb_disk_angle_from_x", turb_disk_angle);
933 
934  pp.query("windfarm_x_shift",windfarm_x_shift);
935  pp.query("windfarm_y_shift",windfarm_y_shift);
936  // Test if time averaged data is to be output
937  pp.query("time_avg_vel",time_avg_vel);
938 
939  pp.query("hindcast_lateral_forcing", hindcast_lateral_forcing);
940 
942  pp.query("hindcast_boundary_data_dir", hindcast_boundary_data_dir);
943 
944  if(hindcast_boundary_data_dir.empty()) {
945  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_boundary_data_dir' for boundary data for lateral forcing");
946  }
947  pp.query("hindcast_data_interval_in_hrs", hindcast_data_interval_in_hrs);
949  amrex::Error("ERROR: Input parameter 'erf.hindcast_data_interval_in_hrs' which is the time interval between the "
950  "data files is either missing or set to less than zero");
951  }
952  pp.query("hindcast_lateral_sponge_strength", hindcast_lateral_sponge_strength);
953  pp.query("hindcast_lateral_sponge_length", hindcast_lateral_sponge_length);
954 
955  pp.query("hindcast_zhi_sponge_length", hindcast_zhi_sponge_length);
956  pp.query("hindcast_zhi_sponge_strength", hindcast_zhi_sponge_strength);
957 
958  pp.query("hindcast_zhi_sponge_damping", hindcast_zhi_sponge_damping);
959 
961  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_lateral_sponge_strength' or it is specified to be less than zero");
962  }
963 
965  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_lateral_sponge_length' or it is specified to be less than zero");
966  }
967 
969  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_zhi_sponge_length' or it is specified to be less than zero");
970  }
971 
973  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_zhi_sponge_strength' or it is specified to be less than zero");
974  }
975  }
976 
977  pp.query("hindcast_surface_bcs", hindcast_surface_bcs);
979  pp.query("hindcast_surface_data_dir", hindcast_surface_data_dir);
980  }
981 
982  pp.query("io_hurricane_eye_tracker", io_hurricane_eye_tracker);
984  pp.query("hurricane_eye_latitude", hurricane_eye_latitude);
985  pp.query("hurricane_eye_longitude", hurricane_eye_longitude);
987  amrex::Error("ERROR: You are using 'erf.io_hurricane_eye_tracker' to write out the files that track the eye of the hurricane"
988  " but have not provided the initial location of the eye of the hurricane to be tracked. There has to be two"
989  " options in the inputs - erf.hurricane_eye_latitude and erf.hurricane_eye_longitude that gives an approximate"
990  " location of the eye in the initial condition");
991  }
992  }
993 
994  pp.query("is_init_for_ensemble", is_init_for_ensemble);
996  amrex::ParmParse pp_ens("ensemble");
997  pp_ens.query("n_members", n_ensemble);
998  if(n_ensemble < 2) {
999  amrex::Abort("You are using an ensemble run. There needs to be at least 2 ensemble members. "
1000  "erf.n_ensemble must be >=2.");
1001  }
1002  pp_ens.query("coarse_bckgnd_data_file", coarse_bckgnd_data_file);
1003  if (coarse_bckgnd_data_file.empty()) {
1004  amrex::Abort("coarse_bckgnd_data_file is empty! For ensmeble simulations, there needs to be a coarse background file which "
1005  "contains the data which will be interpolated onto the fine mesh. There has to a entry ensemble.coarse_bckgnd_data_file "
1006  "which contains the filename in the inputs.");
1007  }
1008  pp_ens.query("ens_pert_amplitude", ens_pert_amplitude);
1009  if(ens_pert_amplitude <= 0.0) {
1010  amrex::Error("You are using initialization for ensemble simulations using the inputs option "
1011  "ensemble.is_init_for_ensemble=true. In this case, there has to be an option "
1012  "ensemble.ens_pert_amplitude which is the value of the amplitude of the perturbation "
1013  "to be added to the background state and has to be greater than 0.0");
1014  }
1015  pp_ens.query("ens_pert_correlated_radius", ens_pert_correlated_radius);
1016  if(ens_pert_correlated_radius <= 0.0) {
1017  amrex::Error("You are using initialization with spatially correlated perturbations using the inputs option "
1018  "ensemble.is_init_for_ensemble=true. In this case, there has to be an option "
1019  "ensemble.ens_pert_correlated_radius which is the value of the the spatial correlation radius, "
1020  "and has to be greater than 0.0");
1021  }
1022  }
1023  }
1024 
1025  /**
1026  * @brief Validate solver options after geometry and boundary conditions are known.
1027  * @param max_level Maximum AMR level configured for the run.
1028  * @param geom_vect Geometry for each AMR level.
1029  * @param phys_bc_type Physical boundary-condition types.
1030  */
1031  void check_params (int max_level, const amrex::Vector<amrex::Geometry>& geom_vect, amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2> phys_bc_type)
1032  {
1033 #if 0
1034  // Warn for PBL models and moisture - these may not yet be compatible
1035  for (int lev = 0; lev <= max_level; lev++) {
1036  if ((moisture_type != MoistureType::None) && (turbChoice[lev].pbl_type != PBLType::None)) {
1037  amrex::Warning("\n*** WARNING: Moisture may not yet be compatible with PBL models, \n proceed with caution ***");
1038  }
1039  }
1040 #endif
1041  //
1042  // Buoyancy type check
1043  //
1044  for (int lev = 0; lev <= max_level; lev++) {
1045  if (buoyancy_type[lev] != 1 && buoyancy_type[lev] != 2 && buoyancy_type[lev] != 3 && buoyancy_type[lev] != 4) {
1046  amrex::Error("buoyancy_type must be 1, 2, 3 or 4");
1047  }
1048  }
1049 
1050  if (!use_lagged_delta_rt && !(terrain_type == TerrainType::MovingFittedMesh)) {
1051  amrex::Error("Can't turn off lagged_delta_rt when terrain not moving");
1052  }
1053 
1054  //
1055  // Wind farm checks
1056  //
1057  if (windfarm_type==WindFarmType::SimpleAD and sampling_distance_by_D < zero) {
1058  amrex::Error("To use simplified actuator disks, you need to provide a variable"
1059  " erf.sampling_distance_by_D in the inputs which specifies the upstream"
1060  " distance as a factor of the turbine diameter at which the incoming free stream"
1061  " velocity will be computed at.");
1062  }
1063  if ( (windfarm_type==WindFarmType::SimpleAD ||
1064  windfarm_type==WindFarmType::GeneralAD ) && turb_disk_angle < zero) {
1065  amrex::Error("To use simplified actuator disks, you need to provide a variable"
1066  " erf.turb_disk_angle_from_x in the inputs which is the angle of the face of the"
1067  " turbine disk from the x-axis. A turbine facing an oncoming flow in the x-direction"
1068  " will have turb_disk_angle value of 90 deg.");
1069  }
1070  if (windfarm_loc_type == WindFarmLocType::lat_lon and (windfarm_x_shift < zero or windfarm_y_shift < zero)) {
1071  amrex::Error("You are using windfarms with latitude-logitude option to position the turbines."
1072  " For this you should provide the inputs erf.windfarm_x_shift and"
1073  " erf.windfarm_y_shift which are the values by which the bounding box of the"
1074  " windfarm is shifted from the x and the y axes.");
1075  }
1076 
1077 
1078  if ( (const_massflux_u != 0) && !(geom_vect[0].isPeriodic(0)) ) {
1079  amrex::Error("Constant mass flux (in x) should be used with periodic boundaries");
1080  }
1081 
1082  if ( (const_massflux_v != 0) && !(geom_vect[0].isPeriodic(1)) ) {
1083  amrex::Error("Constant mass flux (in y) should be used with periodic boundaries");
1084  }
1085 
1086  // Mesoscale diffusion -- test if LES appropriate with this dx,dy
1087  for (int lev = 0; lev <= max_level; lev++) {
1088  if ((geom_vect[lev].CellSize(0) > amrex::Real(2000.)) || (geom_vect[lev].CellSize(1) > amrex::Real(2000.)))
1089  {
1090  if ( (turbChoice[lev].les_type == LESType::Smagorinsky) && !turbChoice[lev].smag2d ) {
1091  amrex::Warning("Should use 2-D Smagorinsky for mesoscale resolution");
1092  } else if (turbChoice[lev].les_type == LESType::Deardorff) {
1093  amrex::Warning("Should not use Deardorff LES for mesoscale resolution");
1094  }
1095  }
1096  }
1097 
1098  // Turn off implicit solve if we have no diffusion
1099  bool l_use_kturb = turbChoice[0].use_kturb;
1100  for (int lev = 1; lev <= max_level; lev++) {
1101  l_use_kturb = (l_use_kturb || turbChoice[lev].use_kturb);
1102  }
1103  bool l_use_diff = ( (diffChoice.molec_diff_type != MolecDiffType::None) || l_use_kturb );
1104 
1105  for (int lev = 0; lev <= max_level; lev++) {
1106  bool l_implicit_diff = (vert_implicit_fac[lev][0] > zero ||
1107  vert_implicit_fac[lev][1] > zero ||
1108  vert_implicit_fac[lev][2] > zero);
1109  if (l_implicit_diff && !l_use_diff) {
1110  amrex:: Print() << "No molecular or turbulent diffusion, turning off implicit solve at level " << lev << std::endl;
1111  vert_implicit_fac[lev][0] = zero;
1112  vert_implicit_fac[lev][1] = zero;
1113  vert_implicit_fac[lev][2] = zero;
1114  }
1115  }
1116 
1117  // Countergradient validation: ensure required implicit diffusion is enabled
1118  for (int lev = 0; lev <= max_level; lev++) {
1119  if (turbChoice[lev].enable_mrf_countergradient) {
1121  vert_implicit_fac[lev][0] > zero ||
1122  vert_implicit_fac[lev][1] > zero ||
1123  vert_implicit_fac[lev][2] > zero,
1124  "enable_mrf_countergradient requires vert_implicit_fac > 0");
1127  "enable_mrf_countergradient requires implicit_thermal_diffusion = true");
1128  if (moisture_type != MoistureType::None) {
1131  "enable_mrf_countergradient with moisture requires implicit_moisture_diffusion = true");
1132  }
1133  }
1134  }
1135 
1136  for (int lev = 0; lev <= max_level; lev++) {
1137  turbChoice[lev].check_params(phys_bc_type);
1138  }
1139  }
1140 
1141  /**
1142  * @brief Print the configured solver, physics, and transport options.
1143  * @param max_level Maximum AMR level configured for the run.
1144  * @param pp_prefix ParmParse prefix used to display nested choices.
1145  */
1146  void display (int max_level, std::string pp_prefix)
1147  {
1148  amrex::Print() << "SOLVER CHOICE: " << std::endl;
1149  for (int lev = 0; lev <= max_level; lev++) {
1150  amrex::Print() << "At level " << lev << " : " << std::endl;
1151  if (anelastic[lev]) {
1152  amrex::Print() << " anelastic with no substepping" << std::endl;
1153  } else {
1154  if (substepping_type[lev] == SubsteppingType::None) {
1155  amrex::Print() << " compressible with no substepping" << std::endl;
1156  } else if (substepping_type[lev] == SubsteppingType::Implicit) {
1157  amrex::Print() << " compressible with implicit substepping" << std::endl;
1158  }
1159  }
1160  if (fixed_density[lev]) {
1161  amrex::Print() << " and fixed density" << std::endl;
1162  }
1163  }
1164 
1165  for (int lev = 0; lev <= max_level; lev++) {
1166  amrex::Print() << "vert_implicit_fac at level " << lev << " : "
1167  << vert_implicit_fac[lev][0] << " "
1168  << vert_implicit_fac[lev][1] << " "
1169  << vert_implicit_fac[lev][2];
1170  if (vert_implicit_fac[lev][0] > zero ||
1171  vert_implicit_fac[lev][1] > zero ||
1172  vert_implicit_fac[lev][2] > zero)
1173  {
1174  amrex::Print() << " (theta = " << implicit_thermal_diffusion
1175  << ", moisture = " << implicit_moisture_diffusion
1176  << ", tke = " << implicit_ke_diffusion
1177  << ", momenta = " << implicit_momentum_diffusion;
1178 #ifdef ERF_IMPLICIT_W
1179  amrex::Print() << ", including w";
1180 #endif
1181  amrex::Print() << ")";
1182  }
1183  }
1184  amrex::Print() << std::endl;
1185  amrex::Print() << "use_coriolis : " << use_coriolis << std::endl;
1186  amrex::Print() << "use_gravity : " << use_gravity << std::endl;
1187 
1188  if (moisture_type == MoistureType::SAM) {
1189  amrex::Print() << "Moisture Model: SAM" << std::endl;
1190  } else if (moisture_type == MoistureType::SAM_NoIce) {
1191  amrex::Print() << "Moisture Model: SAM No Ice" << std::endl;
1192  } else if (moisture_type == MoistureType::SAM_NoPrecip_NoIce) {
1193  amrex::Print() << "Moisture Model: SAM No Precip No Ice" << std::endl;
1194  } else if (moisture_type == MoistureType::Morrison) {
1195  amrex::Print() << "Moisture Model: Morrison" << std::endl;
1196  } else if (moisture_type == MoistureType::Morrison_NoIce) {
1197  amrex::Print() << "Moisture Model: Morrison_NoIce" << std::endl;
1198  } else if (moisture_type == MoistureType::WSM6) {
1199  amrex::Print() << "Moisture Model: WSM6" << std::endl;
1200  } else if (moisture_type == MoistureType::Kessler) {
1201  amrex::Print() << "Moisture Model: Kessler" << std::endl;
1202  } else if (moisture_type == MoistureType::Kessler_NoRain) {
1203  amrex::Print() << "Moisture Model: Kessler No Rain" << std::endl;
1204  } else if (moisture_type == MoistureType::SatAdj) {
1205  amrex::Print() << "Moisture Model: Saturation Adjustment" << std::endl;
1206  } else if (moisture_type == MoistureType::MoistNoCondensation) {
1207  amrex::Print() << "Moisture Model: MoistNoCondensation" << std::endl;
1208  } else {
1209  amrex::Print() << "Moisture Model: None" << std::endl;
1210  }
1211 
1212  if (terrain_type == TerrainType::StaticFittedMesh) {
1213  amrex::Print() << "Terrain Type: StaticFittedMesh" << std::endl;
1214  } else if (terrain_type == TerrainType::MovingFittedMesh) {
1215  amrex::Print() << "Terrain Type: MovingFittedMesh" << std::endl;
1216  } else if (terrain_type == TerrainType::EB) {
1217  amrex::Print() << "Terrain Type: EB" << std::endl;
1218  ebChoice.display();
1219  } else if (terrain_type == TerrainType::ImmersedForcing) {
1220  amrex::Print() << "Terrain Type: ImmersedForcing" << std::endl;
1221  } else {
1222  amrex::Print() << "Terrain Type: None" << std::endl;
1223  }
1224 
1225  if (buildings_type == BuildingsType::ImmersedForcing) {
1226  amrex::Print() << "Buildings Type: ImmersedForcing" << std::endl;
1227  } else {
1228  amrex::Print() << "Buildings Type: None" << std::endl;
1229  }
1230 
1231  if (mesh_type == MeshType::ConstantDz) {
1232  amrex::Print() << " Mesh Type: ConstantDz" << std::endl;
1233  } else if (mesh_type == MeshType::StretchedDz) {
1234  amrex::Print() << " Mesh Type: StretchedDz" << std::endl;
1235  } else if (mesh_type == MeshType::VariableDz) {
1236  amrex::Print() << " Mesh Type: VariableDz" << std::endl;
1237  } else {
1238  amrex::Error("No mesh_type set!");
1239  }
1240 
1241  amrex::Print() << "ABL Driver Type: " << std::endl;
1242  if (abl_driver_type == ABLDriverType::None) {
1243  amrex::Print() << " None" << std::endl;
1244  } else if (abl_driver_type == ABLDriverType::PressureGradient) {
1245  amrex::Print() << " Pressure Gradient "
1246  << amrex::RealVect(abl_pressure_grad[0],abl_pressure_grad[1],abl_pressure_grad[2])
1247  << std::endl;
1248  } else if (abl_driver_type == ABLDriverType::GeostrophicWind) {
1249  amrex::Print() << " Geostrophic Wind "
1250  << amrex::RealVect(abl_geo_forcing[0],abl_geo_forcing[1],abl_geo_forcing[2])
1251  << std::endl;
1252  }
1253 
1254  if (max_level > 0) {
1255  amrex::Print() << "Coupling Type: " << std::endl;
1256  if (coupling_type == CouplingType::TwoWay) {
1257  amrex::Print() << " Two-way" << std::endl;
1258  } else if (coupling_type == CouplingType::OneWay) {
1259  amrex::Print() << " One-way" << std::endl;
1260  }
1261  }
1262 
1263  if (rad_type == RadiationType::RRTMGP) {
1264  amrex::Print() << "Radiation Model: RRTMGP" << std::endl;
1265  } else {
1266  amrex::Print() << "Radiation Model: None" << std::endl;
1267  }
1268 
1269  amrex::Print() << "Gradp_type : " << gradp_type << std::endl;
1270 
1271  for (int lev = 0; lev <= max_level; lev++) {
1272  amrex::Print() << "Buoyancy_type at level " << lev << " : " << buoyancy_type[lev] << std::endl;
1273  }
1274 
1275  advChoice.display(pp_prefix);
1276  diffChoice.display();
1279 
1280  for (int lev = 0; lev <= max_level; lev++) {
1281  turbChoice[lev].display(lev);
1282  }
1283  }
1284 
1285  /**
1286  * @brief Build constant-latitude Coriolis forcing parameters.
1287  * @param pp_prefix ParmParse prefix for the ERF input namespace.
1288  */
1289  void build_coriolis_forcings_const_lat (std::string pp_prefix)
1290  {
1291  amrex::ParmParse pp(pp_prefix);
1292 
1293  // Read the rotational time period (in seconds)
1294  double rot_time_period = 86400.0;
1295  pp.query("rotational_time_period", rot_time_period);
1296 
1297  coriolis_factor = static_cast<amrex::Real>(4.0 * PI / rot_time_period);
1298 
1299  pp.query("coriolis_3d", coriolis_3d);
1300 
1301  // Convert to radians
1302  amrex::Real latitude_for_coriolis = amrex::Real(90.0);
1303  pp.query("latitude", latitude_for_coriolis);
1304  latitude_for_coriolis *= (PI/amrex::Real(180.));
1305  sinphi = std::sin(latitude_for_coriolis);
1306 
1307  // Note: cosphi defaults to 0
1308  if (coriolis_3d) {
1309  cosphi = std::cos(latitude_for_coriolis);
1310  }
1311 
1312  amrex::Print() << "Coriolis frequency, f = " << coriolis_factor * sinphi << " 1/s" << std::endl;
1313 
1314  if (abl_driver_type == ABLDriverType::GeostrophicWind) {
1315  // Read in the geostrophic wind -- we only use this to construct
1316  // the forcing term so no need to keep it
1317  amrex::Vector<amrex::Real> abl_geo_wind(3);
1318  pp.queryarr("abl_geo_wind",abl_geo_wind);
1319 
1320  if(!pp.query("abl_geo_wind_table",abl_geo_wind_table)) {
1321  abl_geo_forcing = {
1322  -coriolis_factor * (abl_geo_wind[1]*sinphi - abl_geo_wind[2]*cosphi),
1323  coriolis_factor * abl_geo_wind[0]*sinphi,
1324  -coriolis_factor * abl_geo_wind[0]*cosphi
1325  };
1326  } else {
1327  amrex::Print() << "NOTE: abl_geo_wind_table provided, ignoring input abl_geo_wind" << std::endl;
1328  }
1329  }
1330  }
1331 
1332  /**
1333  * @brief Read one integer value or one value per AMR level.
1334  * @param max_level Maximum AMR level configured for the run.
1335  * @param string_to_read ParmParse key to read.
1336  * @param vec_to_fill Destination vector with one entry per level.
1337  * @param default_int Default value used when the key is absent.
1338  */
1339  void read_int_string (int max_level, const char* string_to_read,
1340  amrex::Vector<int>& vec_to_fill, int default_int)
1341  {
1342  amrex::ParmParse pp("erf");
1343  int nvals = pp.countval(string_to_read);
1344  AMREX_ALWAYS_ASSERT(nvals == 0 || nvals == 1 || nvals >= max_level+1);
1345  amrex::Vector<int> temp; temp.resize(nvals);
1346  pp.queryarr(string_to_read,temp);
1347 
1348  if (vec_to_fill.size() < max_level+1) {
1349  vec_to_fill.resize(max_level+1);
1350  }
1351 
1352  if (nvals == 0) {
1353  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = default_int;
1354  } else if (nvals == 1) {
1355  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = temp[0];
1356  } else {
1357  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = temp[i];
1358  }
1359  }
1360 
1361  inline static
1362  InitType init_type = InitType::None;
1363 
1364  inline static
1365  SoundingType sounding_type = SoundingType::Ideal;
1366 
1367  inline static
1368  TerrainType terrain_type = TerrainType::None;
1369 
1370  inline static
1371  BuildingsType buildings_type = BuildingsType::None;
1372 
1373  inline static
1374  bool use_real_bcs = false;
1375 
1376  inline static
1377  MeshType mesh_type = MeshType::ConstantDz;
1378 
1379  /**
1380  * @brief Override the globally selected mesh type.
1381  * @param new_mesh_type Mesh type to store.
1382  */
1383  static
1384  void set_mesh_type (MeshType new_mesh_type)
1385  {
1386  mesh_type = new_mesh_type;
1387  }
1388 
1393  amrex::Vector<TurbChoice> turbChoice;
1395 
1397 
1398  amrex::Vector<SubsteppingType> substepping_type;
1399  amrex::Vector<int> anelastic;
1400  amrex::Vector<int> fixed_density;
1401  amrex::Vector<int> project_initial_velocity;
1402  amrex::Vector<int> buoyancy_type;
1403  amrex::Vector<int> is_land;
1404 
1405  // do some extra CFL diagnostics for compressible with substepping
1406  bool substepping_diag = false;
1407 
1408  // time off-centering coefficient, > 0 for forward weighting (i.e., bias
1409  // towards the future time step)
1411 
1412  // This controls the time-centering of the *vertical* differences in the diffusive term for
1413  // theta, u, v (and w if ERF_IMPLICIT_W is set)
1414  // 0: fully explicit
1415  // 1: fully implicit
1416  amrex::Vector<amrex::Vector<amrex::Real>> vert_implicit_fac; // one value per RK stage
1417 
1418  // if any vert_implicit_fac > 0, then the following apply:
1424 
1425  int ncorr = 1;
1426 #ifdef AMREX_USE_FLOAT
1429 #else
1432 #endif
1433 
1434  bool test_mapfactor = false;
1435 
1436  int gradp_type = 0;
1437 
1439 
1440  // Specify what additional physics/forcing modules we use
1441  bool use_gravity = false;
1442  bool use_coriolis = false;
1443  bool coriolis_3d = true;
1444 
1446 
1447  // Specify whether to apply other various source terms on substep only
1449  bool forest_substep = false;
1450 
1451  // immersed forcing parameters
1454  // Use a point-implicit (linearly-implicit) formulation of the immersed-forcing
1455  // drag. Defaults to false (explicit forward-Euler source).
1456  bool if_implicit_drag = false;
1457  // immersed forcing MOST parameters.
1463  bool if_use_most = false;
1465  amrex::Real if_ws_floor = 0.001; // [m/s]
1467 
1468  // This defaults to true but can be set to false for moving terrain cases only
1469  bool use_lagged_delta_rt = true;
1470 
1471  // Flag to rebalance states from wrfinput and wrfbdy
1472  bool rebalance_wrf_input = true;
1473 
1474  // Constants
1476  amrex::Real c_p = Cp_d; // specific heat at constant pressure for dry air [J/(kg-K)]
1478 
1479  // Staggered z levels for vertical grid stretching
1483 
1484  // Coriolis forcing
1488 
1489  // User-specified forcings in problem definition
1492  bool custom_w_subsidence = false;
1493  bool do_theta_advection = true; // Apply custom vertical subsidence to (rho*theta) equation when using custom w subsidence
1494  bool do_mom_advection = true; // Apply custom vertical subsidence to momentum equations when using custom w subsidence
1499 
1500  // Do we use source terms to nudge the solution towards
1501  // the time-varying data provided in input sounding files?
1503 
1504  // MOST stress rotations
1506 
1507  // Should we use SHOC?
1508  bool use_eamxx_shoc = false;
1509  bool use_native_shoc = false;
1510 
1511  // Transport the passive scalar?
1512  bool transport_scalar = true;
1513 
1514  // User wishes to output time averaged velocity fields
1515  bool time_avg_vel = false;
1516 
1517  /**
1518  * @brief Query whether any turbulent perturbation mode is enabled on a level.
1519  * @param lev AMR level index.
1520  * @return True if source, direct, CPM, or CPM_W perturbations are enabled.
1521  */
1522  bool use_perturbation (int lev) const
1523  {
1524  return pert_type[lev] == PerturbationType::Source ||
1525  pert_type[lev] == PerturbationType::Direct ||
1526  pert_type[lev] == PerturbationType::CPM ||
1527  pert_type[lev] == PerturbationType::CPM_W;
1528  }
1529 
1530  /**
1531  * @brief Query whether direct turbulent perturbations are enabled on a level.
1532  * @param lev AMR level index.
1533  * @return True if direct, CPM, or CPM_W perturbations are enabled.
1534  */
1535  bool use_direct_perturbation (int lev) const
1536  {
1537  return pert_type[lev] == PerturbationType::Direct ||
1538  pert_type[lev] == PerturbationType::CPM ||
1539  pert_type[lev] == PerturbationType::CPM_W;
1540  }
1541 
1542  /**
1543  * @brief Query whether source-term turbulent perturbations are enabled on a level.
1544  * @param lev AMR level index.
1545  * @return True if source perturbations are enabled.
1546  */
1547  bool use_source_perturbation (int lev) const
1548  {
1549  return pert_type[lev] == PerturbationType::Source;
1550  }
1551 
1552  /**
1553  * @brief Query whether vertical-velocity CPM perturbations are enabled on a level.
1554  * @param lev AMR level index.
1555  * @return True if CPM_W perturbations are enabled.
1556  */
1557  bool use_wvel_perturbation (int lev) const
1558  {
1559  return pert_type[lev] == PerturbationType::CPM_W;
1560  }
1561 
1562  /**
1563  * @brief Query whether any SHOC-family PBL scheme is active.
1564  * @return True if native or EAMxx SHOC is active.
1565  */
1566  bool uses_shoc_family () const noexcept
1567  {
1568  return use_eamxx_shoc || use_native_shoc;
1569  }
1570 
1571  /**
1572  * @brief Query whether the active PBL scheme suppresses microphysics condensation.
1573  * @return True when the active PBL scheme owns condensation handling.
1574  */
1576  {
1577  return uses_shoc_family();
1578  }
1579 
1580  /**
1581  * @brief Query whether any level uses a turbulent perturbation mode.
1582  * @return True if at least one configured level has source, direct, or CPM perturbations.
1583  */
1584  bool any_perturbation () const
1585  {
1586  for (const auto& type : pert_type) {
1587  if (type == PerturbationType::Source ||
1588  type == PerturbationType::Direct ||
1589  type == PerturbationType::CPM) {
1590  return true;
1591  }
1592  }
1593  return false;
1594  }
1595 
1596  // Type of perturbation
1597  amrex::Vector<PerturbationType> pert_type;
1598 
1599  // Numerical diffusion
1600  bool use_num_diff{false};
1602 
1603  CouplingType coupling_type;
1604  MoistureType moisture_type;
1605  WindFarmType windfarm_type;
1606  WindFarmLocType windfarm_loc_type;
1607  LandSurfaceType lsm_type;
1608  RadiationType rad_type;
1609 
1610  ABLDriverType abl_driver_type;
1611  amrex::GpuArray<amrex::Real, AMREX_SPACEDIM> abl_pressure_grad;
1612  amrex::GpuArray<amrex::Real, AMREX_SPACEDIM> abl_geo_forcing;
1613  std::string abl_geo_wind_table;
1615 
1616  bool variable_coriolis{false};
1617 
1618  int ave_plane {2};
1619 
1620  // Microphysics params
1622 
1624 
1631 
1632  // Nudging factor for bdy sponging : F1 = 1/(nudge_factor * dt)
1634 
1635  // Use density reconstructed from standard WRF lateral boundary data.
1636  bool use_wrf_bdy_density = false;
1637  // Density-specific Davies factor; non-positive means use bdy_nudge_factor.
1639 
1640  // Which approach to nudging the moist variables in the boundary region?
1642 
1643  // Keep the WRF grid or remake our own?
1644  bool use_wrf_height_grid {true};
1645 
1646  // Use forest canopy model?
1647  bool do_forest_drag {false};
1648 
1649  // Enforce constant mass flux?
1655  int massflux_klo {0}; // these are updated in ERF.cpp
1656  int massflux_khi {0};
1657 
1661  bool hindcast_surface_bcs = false;
1665 
1668 
1669  bool is_init_for_ensemble = false;
1670  int n_ensemble = -1;
1674 };
1675 
1676 /**
1677  * @var SolverChoice::init_type
1678  * @brief Initial-condition source selected for the run.
1679  * @var SolverChoice::sounding_type
1680  * @brief Interpretation used for input sounding profiles.
1681  * @var SolverChoice::terrain_type
1682  * @brief Terrain or immersed-boundary representation.
1683  * @var SolverChoice::buildings_type
1684  * @brief Building representation.
1685  * @var SolverChoice::use_real_bcs
1686  * @brief Whether real-data lateral boundary conditions are used.
1687  * @var SolverChoice::mesh_type
1688  * @brief Vertical mesh representation.
1689  * @var SolverChoice::advChoice
1690  * @brief Advection-related options.
1691  * @var SolverChoice::diffChoice
1692  * @brief Diffusion-related options.
1693  * @var SolverChoice::dampingChoice
1694  * @brief Damping-related options.
1695  * @var SolverChoice::spongeChoice
1696  * @brief Sponge-layer options.
1697  * @var SolverChoice::turbChoice
1698  * @brief Turbulence options for each AMR level.
1699  * @var SolverChoice::ebChoice
1700  * @brief Embedded-boundary options.
1701  * @var SolverChoice::force_stage1_single_substep
1702  * @brief Flag forcing a single substep in the first RK stage.
1703  * @var SolverChoice::substepping_type
1704  * @brief Acoustic substepping type for each AMR level.
1705  * @var SolverChoice::anelastic
1706  * @brief Per-level flag selecting anelastic dynamics.
1707  * @var SolverChoice::fixed_density
1708  * @brief Per-level flag selecting fixed-density treatment.
1709  * @var SolverChoice::project_initial_velocity
1710  * @brief Per-level flag for projecting the initial velocity.
1711  * @var SolverChoice::buoyancy_type
1712  * @brief Per-level buoyancy formulation selector.
1713  * @var SolverChoice::is_land
1714  * @brief Per-level land/water selector.
1715  * @var SolverChoice::substepping_diag
1716  * @brief Whether to emit extra CFL diagnostics for compressible substepping.
1717  * @var SolverChoice::beta_s
1718  * @brief Time off-centering coefficient for forward weighting.
1719  * @var SolverChoice::vert_implicit_fac
1720  * @brief Per-level, per-stage implicit vertical diffusion factors.
1721  * @var SolverChoice::implicit_thermal_diffusion
1722  * @brief Whether implicit vertical thermal diffusion is included.
1723  * @var SolverChoice::implicit_moisture_diffusion
1724  * @brief Whether implicit vertical moisture diffusion is included.
1725  * @var SolverChoice::implicit_ke_diffusion
1726  * @brief Whether implicit vertical TKE diffusion is included.
1727  * @var SolverChoice::implicit_momentum_diffusion
1728  * @brief Whether implicit vertical momentum diffusion is included.
1729  * @var SolverChoice::implicit_before_substep
1730  * @brief Whether implicit diffusion is applied before acoustic substepping.
1731  * @var SolverChoice::ncorr
1732  * @brief Number of projection correction iterations.
1733  * @var SolverChoice::poisson_abstol
1734  * @brief Absolute tolerance for the Poisson solve.
1735  * @var SolverChoice::poisson_reltol
1736  * @brief Relative tolerance for the Poisson solve.
1737  * @var SolverChoice::test_mapfactor
1738  * @brief Whether to use test map scale factors.
1739  * @var SolverChoice::gradp_type
1740  * @brief Terrain-fitted horizontal pressure-gradient formulation.
1741  * @var SolverChoice::use_pert_pres_gradient
1742  * @brief Whether momentum equations use perturbational pressure gradients.
1743  * @var SolverChoice::use_gravity
1744  * @brief Whether gravitational forcing is enabled.
1745  * @var SolverChoice::use_coriolis
1746  * @brief Whether Coriolis forcing is enabled.
1747  * @var SolverChoice::coriolis_3d
1748  * @brief Whether the three-dimensional Coriolis terms are included.
1749  * @var SolverChoice::four_stream_radiation
1750  * @brief Whether the four-stream radiation approximation is enabled.
1751  * @var SolverChoice::immersed_forcing_substep
1752  * @brief Whether immersed-forcing source terms are applied only during substeps.
1753  * @var SolverChoice::forest_substep
1754  * @brief Whether canopy source terms are applied only during substeps.
1755  * @var SolverChoice::if_Cd_momentum
1756  * @brief Immersed-forcing drag coefficient for momentum.
1757  * @var SolverChoice::if_Cd_scalar
1758  * @brief Immersed-forcing drag coefficient for scalars.
1759  * @var SolverChoice::if_z0
1760  * @brief Immersed-forcing roughness length [m].
1761  * @var SolverChoice::if_surf_temp_flux
1762  * @brief Immersed-forcing surface temperature flux [K m/s].
1763  * @var SolverChoice::if_init_surf_temp
1764  * @brief Initial immersed-forcing surface temperature [K].
1765  * @var SolverChoice::if_surf_heating_rate
1766  * @brief Immersed-forcing surface heating rate [K/hr].
1767  * @var SolverChoice::if_Olen_in
1768  * @brief Input Obukhov length for immersed-forcing MOST [m].
1769  * @var SolverChoice::if_use_most
1770  * @brief Whether immersed-forcing MOST is enabled.
1771  * @var SolverChoice::if_stability_correction
1772  * @brief Whether immersed-forcing stability corrections are enabled.
1773  * @var SolverChoice::if_ws_floor
1774  * @brief Wind-speed floor for immersed-forcing MOST [m/s].
1775  * @var SolverChoice::if_damp_alpha
1776  * @brief Immersed-forcing damping coefficient.
1777  * @var SolverChoice::use_lagged_delta_rt
1778  * @brief Whether to use lagged delta terms for moving terrain.
1779  * @var SolverChoice::rebalance_wrf_input
1780  * @brief Whether to rebalance states from wrfinput and wrfbdy data.
1781  * @var SolverChoice::gravity
1782  * @brief Effective gravitational acceleration.
1783  * @var SolverChoice::c_p
1784  * @brief Specific heat at constant pressure for dry air [J/(kg-K)].
1785  * @var SolverChoice::rdOcp
1786  * @brief Ratio of dry-air gas constant to c_p.
1787  * @var SolverChoice::grid_stretching_ratio
1788  * @brief Vertical grid stretching ratio.
1789  * @var SolverChoice::zsurf
1790  * @brief Nominal surface height for stretched-grid setup.
1791  * @var SolverChoice::dz0
1792  * @brief Initial vertical grid spacing for stretched-grid setup.
1793  * @var SolverChoice::coriolis_factor
1794  * @brief Twice the planetary rotation rate used for Coriolis forcing.
1795  * @var SolverChoice::cosphi
1796  * @brief Cosine of the latitude used for Coriolis forcing.
1797  * @var SolverChoice::sinphi
1798  * @brief Sine of the latitude used for Coriolis forcing.
1799  * @var SolverChoice::custom_rhotheta_forcing
1800  * @brief Whether custom rho-theta forcing is enabled.
1801  * @var SolverChoice::custom_moisture_forcing
1802  * @brief Whether custom moisture forcing is enabled.
1803  * @var SolverChoice::custom_w_subsidence
1804  * @brief Whether custom vertical subsidence is enabled.
1805  * @var SolverChoice::do_theta_advection
1806  * @brief Whether custom vertical subsidence is applied to rho-theta.
1807  * @var SolverChoice::do_mom_advection
1808  * @brief Whether custom vertical subsidence is applied to momentum.
1809  * @var SolverChoice::custom_geostrophic_profile
1810  * @brief Whether a custom geostrophic wind profile is used.
1811  * @var SolverChoice::custom_forcing_prim_vars
1812  * @brief Whether custom forcing operates on primitive variables.
1813  * @var SolverChoice::spatial_rhotheta_forcing
1814  * @brief Whether spatially varying rho-theta forcing is enabled.
1815  * @var SolverChoice::spatial_moisture_forcing
1816  * @brief Whether spatially varying moisture forcing is enabled.
1817  * @var SolverChoice::nudging_from_input_sounding
1818  * @brief Whether solution fields are nudged toward input sounding data.
1819  * @var SolverChoice::use_rotate_surface_flux
1820  * @brief Whether MOST surface fluxes are rotated with terrain.
1821  * @var SolverChoice::use_eamxx_shoc
1822  * @brief Whether any level uses the EAMxx SHOC PBL scheme.
1823  * @var SolverChoice::use_native_shoc
1824  * @brief Whether any level uses the native SHOC PBL scheme.
1825  * @var SolverChoice::transport_scalar
1826  * @brief Whether the passive scalar component is transported.
1827  * @var SolverChoice::time_avg_vel
1828  * @brief Whether time-averaged velocity fields are output.
1829  * @var SolverChoice::pert_type
1830  * @brief Turbulent perturbation type for each AMR level.
1831  * @var SolverChoice::use_num_diff
1832  * @brief Whether sixth-order numerical diffusion is enabled.
1833  * @var SolverChoice::num_diff_coeff
1834  * @brief Numerical diffusion coefficient after input scaling.
1835  * @var SolverChoice::coupling_type
1836  * @brief Multilevel coupling strategy.
1837  * @var SolverChoice::moisture_type
1838  * @brief Moisture or microphysics model.
1839  * @var SolverChoice::windfarm_type
1840  * @brief Wind-farm model.
1841  * @var SolverChoice::windfarm_loc_type
1842  * @brief Coordinate system for wind-farm turbine locations.
1843  * @var SolverChoice::lsm_type
1844  * @brief Land-surface model.
1845  * @var SolverChoice::rad_type
1846  * @brief Radiation model.
1847  * @var SolverChoice::abl_driver_type
1848  * @brief Atmospheric boundary-layer driver type.
1849  * @var SolverChoice::abl_pressure_grad
1850  * @brief Applied ABL pressure-gradient forcing vector.
1851  * @var SolverChoice::abl_geo_forcing
1852  * @brief Applied geostrophic-wind forcing vector.
1853  * @var SolverChoice::abl_geo_wind_table
1854  * @brief Path to a time-varying geostrophic wind table.
1855  * @var SolverChoice::have_geo_wind_profile
1856  * @brief Whether a geostrophic wind profile has been configured.
1857  * @var SolverChoice::variable_coriolis
1858  * @brief Whether spatially varying Coriolis forcing is enabled.
1859  * @var SolverChoice::ave_plane
1860  * @brief Averaging plane index used by diagnostics.
1861  * @var SolverChoice::moisture_indices
1862  * @brief Conserved-state component indices for active moisture species.
1863  * @var SolverChoice::moisture_tight_coupling
1864  * @brief Whether moisture updates use tight coupling.
1865  * @var SolverChoice::windfarm_loc_table
1866  * @brief Wind-farm location table path.
1867  * @var SolverChoice::windfarm_spec_table
1868  * @brief Wind-farm turbine specification table path.
1869  * @var SolverChoice::windfarm_spec_table_extra
1870  * @brief Additional wind-farm turbine specification table path.
1871  * @var SolverChoice::windfarm_blade_table
1872  * @brief Wind-farm blade table path.
1873  * @var SolverChoice::windfarm_airfoil_tables
1874  * @brief Wind-farm airfoil table paths.
1875  * @var SolverChoice::sampling_distance_by_D
1876  * @brief Turbine inflow sampling distance normalized by rotor diameter.
1877  * @var SolverChoice::turb_disk_angle
1878  * @brief Turbine disk angle from the x axis [deg].
1879  * @var SolverChoice::windfarm_x_shift
1880  * @brief Wind-farm x-coordinate shift.
1881  * @var SolverChoice::windfarm_y_shift
1882  * @brief Wind-farm y-coordinate shift.
1883  * @var SolverChoice::bdy_nudge_factor
1884  * @brief Boundary sponge nudging factor.
1885  * @var SolverChoice::bdy_moist_nudge_type
1886  * @brief Moist-variable nudging strategy in boundary regions.
1887  * @var SolverChoice::do_forest_drag
1888  * @brief Whether forest canopy drag is enabled.
1889  * @var SolverChoice::const_massflux_u
1890  * @brief Target constant mass flux in the x direction.
1891  * @var SolverChoice::const_massflux_v
1892  * @brief Target constant mass flux in the y direction.
1893  * @var SolverChoice::const_massflux_tau
1894  * @brief Relaxation time scale for constant-mass-flux forcing.
1895  * @var SolverChoice::const_massflux_layer_lo
1896  * @brief Lower height of the constant-mass-flux forcing layer.
1897  * @var SolverChoice::const_massflux_layer_hi
1898  * @brief Upper height of the constant-mass-flux forcing layer.
1899  * @var SolverChoice::massflux_klo
1900  * @brief Lower vertical index for constant-mass-flux forcing.
1901  * @var SolverChoice::massflux_khi
1902  * @brief Upper vertical index for constant-mass-flux forcing.
1903  * @var SolverChoice::hindcast_boundary_data_dir
1904  * @brief Directory containing hindcast lateral boundary data.
1905  * @var SolverChoice::hindcast_surface_data_dir
1906  * @brief Directory containing hindcast surface boundary data.
1907  * @var SolverChoice::hindcast_data_interval_in_hrs
1908  * @brief Time interval between hindcast data files [hr].
1909  * @var SolverChoice::hindcast_lateral_forcing
1910  * @brief Whether hindcast lateral forcing is enabled.
1911  * @var SolverChoice::hindcast_surface_bcs
1912  * @brief Whether hindcast surface boundary conditions are enabled.
1913  * @var SolverChoice::hindcast_lateral_sponge_strength
1914  * @brief Strength of the hindcast lateral sponge layer.
1915  * @var SolverChoice::hindcast_lateral_sponge_length
1916  * @brief Length of the hindcast lateral sponge layer.
1917  * @var SolverChoice::hindcast_zhi_sponge_strength
1918  * @brief Strength of the upper hindcast sponge layer.
1919  * @var SolverChoice::hindcast_zhi_sponge_length
1920  * @brief Length of the upper hindcast sponge layer.
1921  * @var SolverChoice::hindcast_zhi_sponge_damping
1922  * @brief Whether upper-boundary hindcast sponge damping is enabled.
1923  * @var SolverChoice::io_hurricane_eye_tracker
1924  * @brief Whether hurricane-eye tracking output is enabled.
1925  * @var SolverChoice::hurricane_eye_latitude
1926  * @brief Initial hurricane-eye latitude.
1927  * @var SolverChoice::hurricane_eye_longitude
1928  * @brief Initial hurricane-eye longitude.
1929  * @var SolverChoice::is_init_for_ensemble
1930  * @brief Whether initialization is for an ensemble simulation.
1931  * @var SolverChoice::n_ensemble
1932  * @brief Number of ensemble members.
1933  * @var SolverChoice::ens_pert_correlated_radius
1934  * @brief Spatial correlation radius for ensemble perturbations.
1935  * @var SolverChoice::ens_pert_amplitude
1936  * @brief Amplitude of ensemble initialization perturbations.
1937  * @var SolverChoice::coarse_bckgnd_data_file
1938  * @brief Coarse background data file used for ensemble initialization.
1939  */
1940 #endif
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:49
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real bogus_large_value
Definition: ERF_Constants.H:26
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real PI
Definition: ERF_Constants.H:42
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:64
constexpr amrex::Real R_d
Definition: ERF_Constants.H:47
TauType
Stress tensor component indices.
Definition: ERF_DataStruct.H:37
@ tau12
Definition: ERF_DataStruct.H:38
@ tau23
Definition: ERF_DataStruct.H:38
@ tau33
Definition: ERF_DataStruct.H:38
@ tau22
Definition: ERF_DataStruct.H:38
@ tau11
Definition: ERF_DataStruct.H:38
@ tau32
Definition: ERF_DataStruct.H:38
@ tau31
Definition: ERF_DataStruct.H:38
@ tau21
Definition: ERF_DataStruct.H:38
@ tau13
Definition: ERF_DataStruct.H:38
AMREX_ENUM(InitType, None, Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, ConstantDensity, ConstantDensityLinearTheta, Isentropic, MoistBaseState, HindCast)
Initial-condition source used to populate the ERF state.
Rayleigh
Rayleigh damping profile component indices.
Definition: ERF_DataStruct.H:151
@ ubar
Definition: ERF_DataStruct.H:152
@ wbar
Definition: ERF_DataStruct.H:152
@ nvars
Definition: ERF_DataStruct.H:152
@ vbar
Definition: ERF_DataStruct.H:152
@ thetabar
Definition: ERF_DataStruct.H:152
Sponge
Sponge reference-state component indices.
Definition: ERF_DataStruct.H:159
@ nvars_sponge
Definition: ERF_DataStruct.H:160
@ vbar_sponge
Definition: ERF_DataStruct.H:160
@ ubar_sponge
Definition: ERF_DataStruct.H:160
MapFacType
Indices for map scale factors on mass and face grids.
Definition: ERF_DataStruct.H:25
@ v_x
Definition: ERF_DataStruct.H:27
@ num
Definition: ERF_DataStruct.H:27
@ u_y
Definition: ERF_DataStruct.H:28
@ v_y
Definition: ERF_DataStruct.H:28
@ m_y
Definition: ERF_DataStruct.H:28
@ u_x
Definition: ERF_DataStruct.H:27
@ m_x
Definition: ERF_DataStruct.H:27
Coord
Coordinate-axis selector.
Definition: ERF_DataStruct.H:143
#define RhoQ4_comp
Definition: ERF_IndexDefines.H:45
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:43
#define RhoQ3_comp
Definition: ERF_IndexDefines.H:44
#define RhoQ11_comp
Definition: ERF_IndexDefines.H:52
#define RhoQ9_comp
Definition: ERF_IndexDefines.H:50
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42
#define RhoQ6_comp
Definition: ERF_IndexDefines.H:47
#define RhoQ8_comp
Definition: ERF_IndexDefines.H:49
#define RhoQ5_comp
Definition: ERF_IndexDefines.H:46
#define RhoQ7_comp
Definition: ERF_IndexDefines.H:48
#define RhoQ10_comp
Definition: ERF_IndexDefines.H:51
ParmParse pp("prob")
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
amrex::Real Real
Definition: ERF_ShocInterface.H:19
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:80
AMREX_ASSERT_WITH_MESSAGE(wbar_cutoff_min > wbar_cutoff_max, "ERROR: wbar_cutoff_min < wbar_cutoff_max")
Definition: ERF_EWP.H:9
Definition: ERF_Fitch.H:9
Definition: ERF_GeneralAD.H:8
Definition: ERF_Kessler.H:40
Definition: ERF_MoistNoCondensation.H:13
Definition: ERF_Morrison.H:59
Definition: ERF_NOAHMP.H:57
Definition: ERF_OceanSurf.H:19
Definition: ERF_SAM.H:55
Definition: ERF_SLM.H:26
Definition: ERF_SatAdj.H:45
Definition: ERF_SimpleAD.H:8
Definition: ERF_WSM6.H:38
Definition: ERF_AdvStruct.H:19
void display(std::string &pp_prefix)
Print the configured advection choices.
Definition: ERF_AdvStruct.H:243
void init_params(std::string pp_prefix)
Read advection options from the input parameter database.
Definition: ERF_AdvStruct.H:25
Definition: ERF_DampingStruct.H:22
void init_params(std::string pp_prefix)
Read damping options from the input parameter database.
Definition: ERF_DampingStruct.H:28
void display()
Print the configured damping options.
Definition: ERF_DampingStruct.H:71
Definition: ERF_DiffStruct.H:22
MolecDiffType molec_diff_type
Selected molecular transport model.
Definition: ERF_DiffStruct.H:94
void init_params(std::string pp_prefix)
Read diffusion options from the input parameter database.
Definition: ERF_DiffStruct.H:28
void display()
Print the configured diffusion options.
Definition: ERF_DiffStruct.H:77
Definition: ERF_EBStruct.H:36
void init_params(std::string pp_prefix)
Read embedded-boundary options from the input parameter database.
Definition: ERF_EBStruct.H:42
void display()
Print the configured embedded-boundary options.
Definition: ERF_EBStruct.H:63
Component indices for moisture species in the conserved state.
Definition: ERF_DataStruct.H:166
int ns
Snow number concentration component index.
Definition: ERF_DataStruct.H:176
int qi
Cloud ice component index.
Definition: ERF_DataStruct.H:169
MoistureComponentIndices()=default
Construct an empty set of moisture component indices.
int qv
Water vapor component index.
Definition: ERF_DataStruct.H:167
MoistureComponentIndices(int qv_comp, int qc_comp, int qi_comp=-1, int qr_comp=-1, int qs_comp=-1, int qg_comp=-1, int nc_comp=-1, int ni_comp=-1, int nr_comp=-1, int ns_comp=-1, int ng_comp=-1)
Construct moisture component indices from conserved-state component numbers.
Definition: ERF_DataStruct.H:193
int qs
Snow component index.
Definition: ERF_DataStruct.H:171
int qr
Rain component index.
Definition: ERF_DataStruct.H:170
int qc
Cloud liquid water component index.
Definition: ERF_DataStruct.H:168
int ng
Graupel number concentration component index.
Definition: ERF_DataStruct.H:177
int qg
Graupel component index.
Definition: ERF_DataStruct.H:172
int ni
Cloud ice number concentration component index.
Definition: ERF_DataStruct.H:174
int nr
Rain number concentration component index.
Definition: ERF_DataStruct.H:175
int nc
Cloud liquid water number concentration component index.
Definition: ERF_DataStruct.H:173
Definition: ERF_DataStruct.H:241
bool custom_geostrophic_profile
Whether a custom geostrophic wind profile is used.
Definition: ERF_DataStruct.H:1495
int n_ensemble
Number of ensemble members.
Definition: ERF_DataStruct.H:1670
WindFarmLocType windfarm_loc_type
Coordinate system for wind-farm turbine locations.
Definition: ERF_DataStruct.H:1606
bool implicit_before_substep
Whether implicit diffusion is applied before acoustic substepping.
Definition: ERF_DataStruct.H:1423
amrex::Real const_massflux_v
Target constant mass flux in the y direction.
Definition: ERF_DataStruct.H:1651
std::string hindcast_boundary_data_dir
Directory containing hindcast lateral boundary data.
Definition: ERF_DataStruct.H:1658
amrex::Real ens_pert_correlated_radius
Spatial correlation radius for ensemble perturbations.
Definition: ERF_DataStruct.H:1671
static InitType init_type
Initial-condition source selected for the run.
Definition: ERF_DataStruct.H:1362
amrex::Real coriolis_factor
Twice the planetary rotation rate used for Coriolis forcing.
Definition: ERF_DataStruct.H:1485
bool io_hurricane_eye_tracker
Whether hurricane-eye tracking output is enabled.
Definition: ERF_DataStruct.H:1666
std::string abl_geo_wind_table
Path to a time-varying geostrophic wind table.
Definition: ERF_DataStruct.H:1613
amrex::Vector< int > fixed_density
Per-level flag selecting fixed-density treatment.
Definition: ERF_DataStruct.H:1400
amrex::Vector< TurbChoice > turbChoice
Turbulence options for each AMR level.
Definition: ERF_DataStruct.H:1393
amrex::Real const_massflux_layer_lo
Lower height of the constant-mass-flux forcing layer.
Definition: ERF_DataStruct.H:1653
amrex::Real hindcast_zhi_sponge_length
Length of the upper hindcast sponge layer.
Definition: ERF_DataStruct.H:1663
amrex::Real gravity
Effective gravitational acceleration.
Definition: ERF_DataStruct.H:1475
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.
Definition: ERF_DataStruct.H:1031
bool pbl_suppresses_microphysics_condensation() const noexcept
Query whether the active PBL scheme suppresses microphysics condensation.
Definition: ERF_DataStruct.H:1575
bool variable_coriolis
Whether spatially varying Coriolis forcing is enabled.
Definition: ERF_DataStruct.H:1616
bool implicit_moisture_diffusion
Whether implicit vertical moisture diffusion is included.
Definition: ERF_DataStruct.H:1420
MoistureType moisture_type
Moisture or microphysics model.
Definition: ERF_DataStruct.H:1604
void display(int max_level, std::string pp_prefix)
Print the configured solver, physics, and transport options.
Definition: ERF_DataStruct.H:1146
amrex::Real poisson_abstol
Absolute tolerance for the Poisson solve.
Definition: ERF_DataStruct.H:1430
amrex::Real if_Cd_momentum
Immersed-forcing drag coefficient for momentum.
Definition: ERF_DataStruct.H:1452
amrex::Real if_Olen_in
Input Obukhov length for immersed-forcing MOST [m].
Definition: ERF_DataStruct.H:1462
amrex::Vector< int > buoyancy_type
Per-level buoyancy formulation selector.
Definition: ERF_DataStruct.H:1402
void build_coriolis_forcings_const_lat(std::string pp_prefix)
Build constant-latitude Coriolis forcing parameters.
Definition: ERF_DataStruct.H:1289
CouplingType coupling_type
Multilevel coupling strategy.
Definition: ERF_DataStruct.H:1603
bool use_pert_pres_gradient
Whether momentum equations use perturbational pressure gradients.
Definition: ERF_DataStruct.H:1438
amrex::Vector< int > project_initial_velocity
Per-level flag for projecting the initial velocity.
Definition: ERF_DataStruct.H:1401
int ave_plane
Averaging plane index used by diagnostics.
Definition: ERF_DataStruct.H:1618
amrex::Real const_massflux_u
Target constant mass flux in the x direction.
Definition: ERF_DataStruct.H:1650
void 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:1339
int ncorr
Number of projection correction iterations.
Definition: ERF_DataStruct.H:1425
amrex::Real sampling_distance_by_D
Turbine inflow sampling distance normalized by rotor diameter.
Definition: ERF_DataStruct.H:1627
amrex::Real windfarm_y_shift
Wind-farm y-coordinate shift.
Definition: ERF_DataStruct.H:1630
bool use_rotate_surface_flux
Whether MOST surface fluxes are rotated with terrain.
Definition: ERF_DataStruct.H:1505
bool moisture_tight_coupling
Whether moisture updates use tight coupling.
Definition: ERF_DataStruct.H:1623
EBChoice ebChoice
Embedded-boundary options.
Definition: ERF_DataStruct.H:1394
amrex::Real beta_s
Time off-centering coefficient for forward weighting.
Definition: ERF_DataStruct.H:1410
bool implicit_ke_diffusion
Whether implicit vertical TKE diffusion is included.
Definition: ERF_DataStruct.H:1421
bool any_perturbation() const
Query whether any level uses a turbulent perturbation mode.
Definition: ERF_DataStruct.H:1584
amrex::Real if_z0
Immersed-forcing roughness length [m].
Definition: ERF_DataStruct.H:1458
bool forest_substep
Whether canopy source terms are applied only during substeps.
Definition: ERF_DataStruct.H:1449
bool use_wrf_bdy_density
Definition: ERF_DataStruct.H:1636
bool implicit_thermal_diffusion
Whether implicit vertical thermal diffusion is included.
Definition: ERF_DataStruct.H:1419
bool use_gravity
Whether gravitational forcing is enabled.
Definition: ERF_DataStruct.H:1441
amrex::Real num_diff_coeff
Numerical diffusion coefficient after input scaling.
Definition: ERF_DataStruct.H:1601
amrex::Real bdy_nudge_factor
Boundary sponge nudging factor.
Definition: ERF_DataStruct.H:1633
amrex::Real rdOcp
Ratio of dry-air gas constant to c_p.
Definition: ERF_DataStruct.H:1477
bool use_wvel_perturbation(int lev) const
Query whether vertical-velocity CPM perturbations are enabled on a level.
Definition: ERF_DataStruct.H:1557
bool hindcast_lateral_forcing
Whether hindcast lateral forcing is enabled.
Definition: ERF_DataStruct.H:1660
bool do_theta_advection
Whether custom vertical subsidence is applied to rho-theta.
Definition: ERF_DataStruct.H:1493
bool use_native_shoc
Whether any level uses the native SHOC PBL scheme.
Definition: ERF_DataStruct.H:1509
static bool use_real_bcs
Whether real-data lateral boundary conditions are used.
Definition: ERF_DataStruct.H:1374
bool spatial_moisture_forcing
Whether spatially varying moisture forcing is enabled.
Definition: ERF_DataStruct.H:1498
amrex::Vector< SubsteppingType > substepping_type
Acoustic substepping type for each AMR level.
Definition: ERF_DataStruct.H:1398
bool use_perturbation(int lev) const
Query whether any turbulent perturbation mode is enabled on a level.
Definition: ERF_DataStruct.H:1522
static SoundingType sounding_type
Interpretation used for input sounding profiles.
Definition: ERF_DataStruct.H:1365
int bdy_moist_nudge_type
Moist-variable nudging strategy in boundary regions.
Definition: ERF_DataStruct.H:1641
amrex::Real poisson_reltol
Relative tolerance for the Poisson solve.
Definition: ERF_DataStruct.H:1431
bool use_coriolis
Whether Coriolis forcing is enabled.
Definition: ERF_DataStruct.H:1442
amrex::Vector< PerturbationType > pert_type
Turbulent perturbation type for each AMR level.
Definition: ERF_DataStruct.H:1597
static MeshType mesh_type
Vertical mesh representation.
Definition: ERF_DataStruct.H:1377
bool use_wrf_height_grid
Definition: ERF_DataStruct.H:1644
AdvChoice advChoice
Advection-related options.
Definition: ERF_DataStruct.H:1389
SpongeChoice spongeChoice
Sponge-layer options.
Definition: ERF_DataStruct.H:1392
void init_params(int max_level, std::string pp_prefix)
Read solver-wide algorithmic options from the input parameter database.
Definition: ERF_DataStruct.H:248
bool time_avg_vel
Whether time-averaged velocity fields are output.
Definition: ERF_DataStruct.H:1515
bool use_direct_perturbation(int lev) const
Query whether direct turbulent perturbations are enabled on a level.
Definition: ERF_DataStruct.H:1535
bool have_geo_wind_profile
Whether a geostrophic wind profile has been configured.
Definition: ERF_DataStruct.H:1614
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_pressure_grad
Applied ABL pressure-gradient forcing vector.
Definition: ERF_DataStruct.H:1611
amrex::Vector< int > anelastic
Per-level flag selecting anelastic dynamics.
Definition: ERF_DataStruct.H:1399
bool four_stream_radiation
Whether the four-stream radiation approximation is enabled.
Definition: ERF_DataStruct.H:1445
int gradp_type
Terrain-fitted horizontal pressure-gradient formulation.
Definition: ERF_DataStruct.H:1436
DampingChoice dampingChoice
Damping-related options.
Definition: ERF_DataStruct.H:1391
amrex::Real if_damp_alpha
Immersed-forcing damping coefficient.
Definition: ERF_DataStruct.H:1466
bool rebalance_wrf_input
Whether to rebalance states from wrfinput and wrfbdy data.
Definition: ERF_DataStruct.H:1472
amrex::Real turb_disk_angle
Turbine disk angle from the x axis [deg].
Definition: ERF_DataStruct.H:1628
amrex::Real hindcast_data_interval_in_hrs
Time interval between hindcast data files [hr].
Definition: ERF_DataStruct.H:1659
amrex::Real const_massflux_layer_hi
Upper height of the constant-mass-flux forcing layer.
Definition: ERF_DataStruct.H:1654
std::string windfarm_spec_table_extra
Additional wind-farm turbine specification table path.
Definition: ERF_DataStruct.H:1625
amrex::Real if_ws_floor
Wind-speed floor for immersed-forcing MOST [m/s].
Definition: ERF_DataStruct.H:1465
bool is_init_for_ensemble
Whether initialization is for an ensemble simulation.
Definition: ERF_DataStruct.H:1669
bool uses_shoc_family() const noexcept
Query whether any SHOC-family PBL scheme is active.
Definition: ERF_DataStruct.H:1566
bool test_mapfactor
Whether to use test map scale factors.
Definition: ERF_DataStruct.H:1434
std::string coarse_bckgnd_data_file
Coarse background data file used for ensemble initialization.
Definition: ERF_DataStruct.H:1673
bool do_forest_drag
Whether forest canopy drag is enabled.
Definition: ERF_DataStruct.H:1647
amrex::Real dz0
Initial vertical grid spacing for stretched-grid setup.
Definition: ERF_DataStruct.H:1482
amrex::Real windfarm_x_shift
Wind-farm x-coordinate shift.
Definition: ERF_DataStruct.H:1629
bool use_lagged_delta_rt
Whether to use lagged delta terms for moving terrain.
Definition: ERF_DataStruct.H:1469
amrex::Real ens_pert_amplitude
Amplitude of ensemble initialization perturbations.
Definition: ERF_DataStruct.H:1672
std::string windfarm_airfoil_tables
Wind-farm airfoil table paths.
Definition: ERF_DataStruct.H:1626
amrex::Real bdy_rho_nudge_factor
Definition: ERF_DataStruct.H:1638
amrex::Vector< amrex::Vector< amrex::Real > > vert_implicit_fac
Per-level, per-stage implicit vertical diffusion factors.
Definition: ERF_DataStruct.H:1416
bool transport_scalar
Whether the passive scalar component is transported.
Definition: ERF_DataStruct.H:1512
bool hindcast_zhi_sponge_damping
Whether upper-boundary hindcast sponge damping is enabled.
Definition: ERF_DataStruct.H:1664
amrex::Real hurricane_eye_longitude
Initial hurricane-eye longitude.
Definition: ERF_DataStruct.H:1667
LandSurfaceType lsm_type
Land-surface model.
Definition: ERF_DataStruct.H:1607
int massflux_khi
Upper vertical index for constant-mass-flux forcing.
Definition: ERF_DataStruct.H:1656
bool substepping_diag
Whether to emit extra CFL diagnostics for compressible substepping.
Definition: ERF_DataStruct.H:1406
static TerrainType terrain_type
Terrain or immersed-boundary representation.
Definition: ERF_DataStruct.H:1368
std::string windfarm_blade_table
Wind-farm blade table path.
Definition: ERF_DataStruct.H:1626
amrex::Vector< int > is_land
Per-level land/water selector.
Definition: ERF_DataStruct.H:1403
amrex::Real hindcast_lateral_sponge_strength
Strength of the hindcast lateral sponge layer.
Definition: ERF_DataStruct.H:1662
amrex::Real hurricane_eye_latitude
Initial hurricane-eye latitude.
Definition: ERF_DataStruct.H:1667
amrex::Real cosphi
Cosine of the latitude used for Coriolis forcing.
Definition: ERF_DataStruct.H:1486
amrex::Real if_Cd_scalar
Immersed-forcing drag coefficient for scalars.
Definition: ERF_DataStruct.H:1453
static BuildingsType buildings_type
Building representation.
Definition: ERF_DataStruct.H:1371
std::string windfarm_loc_table
Wind-farm location table path.
Definition: ERF_DataStruct.H:1625
std::string hindcast_surface_data_dir
Directory containing hindcast surface boundary data.
Definition: ERF_DataStruct.H:1658
bool custom_rhotheta_forcing
Whether custom rho-theta forcing is enabled.
Definition: ERF_DataStruct.H:1490
amrex::Real zsurf
Nominal surface height for stretched-grid setup.
Definition: ERF_DataStruct.H:1481
amrex::Real if_init_surf_temp
Initial immersed-forcing surface temperature [K].
Definition: ERF_DataStruct.H:1460
int massflux_klo
Lower vertical index for constant-mass-flux forcing.
Definition: ERF_DataStruct.H:1655
std::string windfarm_spec_table
Wind-farm turbine specification table path.
Definition: ERF_DataStruct.H:1625
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_geo_forcing
Applied geostrophic-wind forcing vector.
Definition: ERF_DataStruct.H:1612
ABLDriverType abl_driver_type
Atmospheric boundary-layer driver type.
Definition: ERF_DataStruct.H:1610
DiffChoice diffChoice
Diffusion-related options.
Definition: ERF_DataStruct.H:1390
amrex::Real if_surf_temp_flux
Immersed-forcing surface temperature flux [K m/s].
Definition: ERF_DataStruct.H:1459
bool spatial_rhotheta_forcing
Whether spatially varying rho-theta forcing is enabled.
Definition: ERF_DataStruct.H:1497
WindFarmType windfarm_type
Wind-farm model.
Definition: ERF_DataStruct.H:1605
bool use_source_perturbation(int lev) const
Query whether source-term turbulent perturbations are enabled on a level.
Definition: ERF_DataStruct.H:1547
bool custom_w_subsidence
Whether custom vertical subsidence is enabled.
Definition: ERF_DataStruct.H:1492
bool custom_moisture_forcing
Whether custom moisture forcing is enabled.
Definition: ERF_DataStruct.H:1491
amrex::Real if_surf_heating_rate
Immersed-forcing surface heating rate [K/hr].
Definition: ERF_DataStruct.H:1461
MoistureComponentIndices moisture_indices
Conserved-state component indices for active moisture species.
Definition: ERF_DataStruct.H:1621
RadiationType rad_type
Radiation model.
Definition: ERF_DataStruct.H:1608
amrex::Real grid_stretching_ratio
Vertical grid stretching ratio.
Definition: ERF_DataStruct.H:1480
bool hindcast_surface_bcs
Whether hindcast surface boundary conditions are enabled.
Definition: ERF_DataStruct.H:1661
bool immersed_forcing_substep
Whether immersed-forcing source terms are applied only during substeps.
Definition: ERF_DataStruct.H:1448
bool if_use_most
Whether immersed-forcing MOST is enabled.
Definition: ERF_DataStruct.H:1463
amrex::Real const_massflux_tau
Relaxation time scale for constant-mass-flux forcing.
Definition: ERF_DataStruct.H:1652
amrex::Real hindcast_lateral_sponge_length
Length of the hindcast lateral sponge layer.
Definition: ERF_DataStruct.H:1662
bool use_eamxx_shoc
Whether any level uses the EAMxx SHOC PBL scheme.
Definition: ERF_DataStruct.H:1508
amrex::Real sinphi
Sine of the latitude used for Coriolis forcing.
Definition: ERF_DataStruct.H:1487
amrex::Real hindcast_zhi_sponge_strength
Strength of the upper hindcast sponge layer.
Definition: ERF_DataStruct.H:1663
bool coriolis_3d
Whether the three-dimensional Coriolis terms are included.
Definition: ERF_DataStruct.H:1443
int force_stage1_single_substep
Flag forcing a single substep in the first RK stage.
Definition: ERF_DataStruct.H:1396
amrex::Real c_p
Specific heat at constant pressure for dry air [J/(kg-K)].
Definition: ERF_DataStruct.H:1476
bool if_implicit_drag
Definition: ERF_DataStruct.H:1456
bool implicit_momentum_diffusion
Whether implicit vertical momentum diffusion is included.
Definition: ERF_DataStruct.H:1422
bool do_mom_advection
Whether custom vertical subsidence is applied to momentum.
Definition: ERF_DataStruct.H:1494
bool if_stability_correction
Whether immersed-forcing stability corrections are enabled.
Definition: ERF_DataStruct.H:1464
bool custom_forcing_prim_vars
Whether custom forcing operates on primitive variables.
Definition: ERF_DataStruct.H:1496
bool nudging_from_input_sounding
Whether solution fields are nudged toward input sounding data.
Definition: ERF_DataStruct.H:1502
static void set_mesh_type(MeshType new_mesh_type)
Override the globally selected mesh type.
Definition: ERF_DataStruct.H:1384
bool use_num_diff
Whether sixth-order numerical diffusion is enabled.
Definition: ERF_DataStruct.H:1600
Definition: ERF_SpongeStruct.H:22
void display()
Print the configured sponge-layer options.
Definition: ERF_SpongeStruct.H:85
void init_params(std::string pp_prefix)
Read sponge-layer options from the input parameter database.
Definition: ERF_SpongeStruct.H:28