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 enum MapFacType {
23 // This version assumes isotropic
24  m_x, u_x, v_x, num,
25  m_y = 0, u_y = 1, v_y = 2
26 // This version allows for non-isotropic
27 // m_x, u_x, v_x,
28 // m_y, u_y, v_y, num
29 };
30 
31 enum TauType {
33 };
34 
35 AMREX_ENUM(InitType,
36  None, Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, ConstantDensity, ConstantDensityLinearTheta,
37  Isentropic, MoistBaseState, HindCast
38 );
39 
40 AMREX_ENUM(SoundingType,
41  ConstantDensity, Ideal, Isentropic, DryIsentropic
42 );
43 
44 AMREX_ENUM(ABLDriverType,
45  None, PressureGradient, GeostrophicWind
46 );
47 
48 AMREX_ENUM(CouplingType,
49  OneWay, TwoWay
50 );
51 
52 AMREX_ENUM(SubsteppingType,
53  None, Implicit
54 );
55 
56 AMREX_ENUM(MeshType,
57  ConstantDz, StretchedDz, VariableDz
58 );
59 
60 AMREX_ENUM(TerrainType,
61  None, StaticFittedMesh, MovingFittedMesh, EB, ImmersedForcing
62 );
63 
64 AMREX_ENUM(BuildingsType,
65  None, ImmersedForcing
66 );
67 
68 AMREX_ENUM(MoistureModelType,
69  Eulerian, Lagrangian, Undefined
70 );
71 
72 AMREX_ENUM(MoistureType,
73  SAM, SAM_NoIce, SAM_NoPrecip_NoIce, Kessler, Kessler_NoRain, SatAdj, Morrison, Morrison_NoIce, WSM6, SuperDroplets, None
74 );
75 
76 AMREX_ENUM(WindFarmType,
77  Fitch, EWP, SimpleAD, GeneralAD, None
78 );
79 
80 AMREX_ENUM(WindFarmLocType,
81  lat_lon, x_y, None
82 );
83 
84 AMREX_ENUM(LandSurfaceType,
85  SLM, MM5, None, NOAHMP
86 );
87 
88 AMREX_ENUM(RadiationType,
89  None, RRTMGP
90 );
91 
92 enum struct Coord {
93  x, y, z
94 };
95 
96 // These are used as integers so must be enum not enum struct
97 enum Rayleigh {
99 };
100 
101 // These are used as integers so must be enum not enum struct
102 enum Sponge {
104 };
105 
107  int qv = -1; // Water vapor
108  int qc = -1; // Cloud liquid water
109  int qi = -1; // Cloud ice
110  int qr = -1; // Rain
111  int qs = -1; // Snow
112  int qg = -1; // Graupel
113 
114  // Constructor for easy initialization
115  MoistureComponentIndices (int qv_comp, int qc_comp,
116  int qi_comp=-1,
117  int qr_comp=-1,
118  int qs_comp=-1,
119  int qg_comp=-1)
120  : qv(qv_comp), qc(qc_comp), qi(qi_comp), qr(qr_comp), qs(qs_comp), qg(qg_comp) {}
121 
122  // Default constructor
124 };
125 
126 /**
127  * Container holding many of the algorithmic options and parameters
128  */
129 
130 struct SolverChoice {
131  public:
132  void init_params (int max_level, std::string pp_prefix)
133  {
134  amrex::ParmParse pp(pp_prefix);
135 
136  bool bogus_bool;
137  if (pp.query("use_terrain",bogus_bool) > 0) {
138  amrex::Error("The input use_terrain is deprecated. Set terrain_type instead.");
139  }
140 
141  if (pp.query("use_moist_background",bogus_bool) > 0) {
142  amrex::Error("The input use_moist_background is deprecated. Set init_type = MoistBaseState instead.");
143  }
144 
145  // Do we set map scale factors to myhalf instead of 1 for testing?
146  pp.query("test_mapfactor", test_mapfactor);
147 
148  // Which horizontal pressure gradient formulation to use with terrain fitted coords?
149  // 0: dp/dx with dp/dz correction (default)
150  // 1: gradient of vertically interpolated p, see Klemp 2011
151  pp.query("gradp_type", gradp_type);
153 
154  // What type of moisture model to use?
155  moisture_type = MoistureType::None; // Default
156  if (pp.query("moisture_type",moisture_type) > 0) {
157  amrex::Error("The input moisture_type is deprecated. Set moisture_model instead.");
158  }
159  pp.query_enum_case_insensitive("moisture_model",moisture_type);
160  if ( (moisture_type == MoistureType::Morrison) ||
161  (moisture_type == MoistureType::WSM6) ||
162  (moisture_type == MoistureType::SAM) ) {
164  RhoQ1_comp, // water vapor
165  RhoQ2_comp, // cloud water
166  RhoQ3_comp, // cloud ice
167  RhoQ4_comp, // rain
168  RhoQ5_comp, // snow
169  RhoQ6_comp // graupel
170  );
171  } else if ( (moisture_type == MoistureType::Morrison_NoIce) ||
172  (moisture_type == MoistureType::SAM_NoIce) ) {
174  RhoQ1_comp, // water vapor
175  RhoQ2_comp, // cloud water
176  -1, // cloud ice
177  RhoQ4_comp // rain
178  );
179  } else if ( (moisture_type == MoistureType::SAM_NoPrecip_NoIce) ||
180  (moisture_type == MoistureType::Kessler_NoRain) ||
181  (moisture_type == MoistureType::SatAdj) ) {
183  RhoQ1_comp, // water vapor
184  RhoQ2_comp // cloud water
185  );
186  } else if (moisture_type == MoistureType::Kessler) {
188  RhoQ1_comp, // water vapor
189  RhoQ2_comp, // cloud water
190  -1, // cloud ice
191  RhoQ3_comp // rain
192  );
193  } else if (moisture_type == MoistureType::SuperDroplets) {
195  RhoQ1_comp, // water vapor
196  RhoQ2_comp, // cloud water
197  RhoQ3_comp // rain
198  );
199  }
200 
201  // Set a default for dry
202  buoyancy_type.resize(max_level+1);
203  for (int i = 0; i <= max_level; ++i) {
204  buoyancy_type[i] = 1; // uses Rhoprime
205  }
206 
207  // Set a default for moist
208  if (moisture_type != MoistureType::None) {
209  if ( !(moisture_type == MoistureType::Kessler_NoRain ||
210  moisture_type == MoistureType::SAM ||
211  moisture_type == MoistureType::SAM_NoIce ||
212  moisture_type == MoistureType::SAM_NoPrecip_NoIce ||
213  moisture_type == MoistureType::Morrison ||
214  moisture_type == MoistureType::Morrison_NoIce ||
215  moisture_type == MoistureType::WSM6 ||
216  moisture_type == MoistureType::SatAdj) )
217  {
218  for (int i = 0; i <= max_level; ++i) {
219  buoyancy_type[i] = 2; // uses Tprime
220  }
221  }
222 
223  pp.query("moisture_tight_coupling",moisture_tight_coupling);
224  }
225 
226  // Which expression (1,2/3 or 4) to use for buoyancy
227  int default_buoyancy_type = buoyancy_type[0];
228  read_int_string(max_level, "buoyancy_type", buoyancy_type, default_buoyancy_type);
229 
230  // What type of land surface model to use
231  lsm_type = LandSurfaceType::None; // Default
232  pp.query_enum_case_insensitive("land_surface_model",lsm_type);
233 
234  // What type of radiation model to use
235  rad_type = RadiationType::None; // Default
236  pp.query_enum_case_insensitive("radiation_model", rad_type);
237 
238  // Verify that radiation model cannot be RRTMGP if ERF was not compiled with RRTMGP
239 #ifndef ERF_USE_RRTMGP
240  if (rad_type == RadiationType::RRTMGP)
241  {
242  amrex::Error("ERF was not compiled with RRTMGP enabled!");
243  }
244 #endif
245 
246  // Is the terrain none, static or moving?
247  std::string terrain_type_temp = "";
248  pp.query("terrain_type", terrain_type_temp);
249  if (terrain_type_temp == "Moving") {
250  amrex::Warning("erf.terrain_type = Moving is deprecated; please replace Moving by MovingFittedMesh");
251  terrain_type = TerrainType::MovingFittedMesh;
252  } else if (terrain_type_temp == "Static") {
253  amrex::Warning("erf.terrain_type = Static is deprecated; please replace Static by StaticFittedMesh");
254  terrain_type = TerrainType::StaticFittedMesh;
255  } else {
256  pp.query_enum_case_insensitive("terrain_type",terrain_type);
257  }
258 
259  // Get buildings type
260  std::string buildings_type_temp = "";
261  pp.query("buildings_type", buildings_type_temp);
262  if (buildings_type_temp == "ImmersedForcing") {
263  buildings_type = BuildingsType::ImmersedForcing;
264  }
265 
266  //
267  // Read the init_type here to make sure we correctly set the mesh and terrain types
268  //
269  std::string init_type_temp_string;
270 
271  int found = pp.query("init_type",init_type_temp_string);
272 
273  if ( (init_type_temp_string == "Real") || (init_type_temp_string == "real") ) {
274  amrex::Error("erf.init_type = Real is deprecated; please replace Real by WRFInput");
275  } else if ( (init_type_temp_string == "Ideal") || (init_type_temp_string == "ideal") ) {
276  amrex::Error("erf.init_type = Ideal is deprecated; please replace Ideal by WRFInput");
277  } else {
278  pp.query_enum_case_insensitive("init_type",init_type);
279  use_real_bcs = ( (init_type == InitType::WRFInput) || (init_type == InitType::Metgrid) );
280  }
281 
282  if ( (init_type == InitType::WRFInput) || (init_type == InitType::Metgrid) ) {
283  if (terrain_type != TerrainType::StaticFittedMesh) {
284  amrex::Error("Only terrain_type = StaticFittedMesh are allowed with init_type = WRFInput or Metgrid");
285  }
286  }
287 
288  if (init_type == InitType::MoistBaseState) {
289  if (moisture_type == MoistureType::None) {
290  amrex::Error("Makes no sense to have moist base state with no moisture model");
291  }
292  }
293 
294  if (init_type == InitType::WRFInput) {
295  if (moisture_type == MoistureType::None) {
296  amrex::Error("Can't have moisture_type = None with init_type = WRFInput");
297  }
298 
299  // NetCDF wrfbdy lateral boundary file
300  std::string nc_bdy_file_temp_string;
301  bool has_bdy = pp.query("nc_bdy_file", nc_bdy_file_temp_string);
302  if (!has_bdy) use_real_bcs = false;
303 
304  bool use_real_bcs_temp = use_real_bcs;
305  pp.query("use_real_bcs", use_real_bcs_temp);
306  if (use_real_bcs && !use_real_bcs_temp) {
307  use_real_bcs = false;
308  }
309  }
310 
311  if (found == 0 || init_type == InitType::None) {
312  amrex::Print() << "init_type must now be set. The options are " << std::endl;
313  amrex::Print() << " Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, " << std::endl;
314  amrex::Print() << " ConstantDensity, Isentropic, MoistBaseState, or HindCast " << std::endl;
315  amrex::Error("Please add a string for init_type to your inputs file or command line");
316  }
317 
318  if (use_real_bcs) {
319  pp.query("upwind_real_bcs",upwind_real_bcs);
320  }
321 
322  // Check for rebalancing with wrfinput
323  if (init_type == InitType::WRFInput) {
324  pp.query("rebalance_wrfinput",rebalance_wrfinput);
325  }
326 
327  // How to interpret input_sounding
328  if (init_type == InitType::Input_Sounding) {
329  pp.query_enum_case_insensitive("sounding_type",sounding_type);
330  }
331 
332  if (terrain_type == TerrainType::StaticFittedMesh ||
333  terrain_type == TerrainType::MovingFittedMesh) {
334  mesh_type = MeshType::VariableDz;
335  }
336 
337  pp.query("grid_stretching_ratio", grid_stretching_ratio);
338  if (grid_stretching_ratio != 0) {
340  "The grid stretching ratio must be greater than 1");
341  }
342  if (grid_stretching_ratio >= 1) {
343  if (terrain_type == TerrainType::None) {
344  terrain_type = TerrainType::StaticFittedMesh;
345  }
346  if (mesh_type == MeshType::ConstantDz) {
347  mesh_type = MeshType::StretchedDz;
348  }
349  pp.query("zsurface", zsurf);
350  if (zsurf != zero) {
351  amrex::Print() << "Nominal zsurface height != 0, may result in unexpected behavior"
352  << std::endl;
353  }
354  pp.get("initial_dz", dz0);
355  }
356 
357  int n_zlevels = pp.countval("terrain_z_levels");
358  if (n_zlevels > 0)
359  {
360  if (terrain_type == TerrainType::None) {
361  terrain_type = TerrainType::StaticFittedMesh;
362  }
363  if (mesh_type == MeshType::ConstantDz) {
364  mesh_type = MeshType::StretchedDz;
365  }
366  }
367 
368  // Use lagged_delta_rt in the fast integrator?
369  pp.query("use_lagged_delta_rt", use_lagged_delta_rt);
370 
371  // These default to true but are used for unit testing
372  pp.query("use_gravity", use_gravity);
374 
375  pp.query("c_p", c_p);
376  rdOcp = R_d / c_p;
377 
378  // *******************************************************************************
379  // Read anelastic etc and over-ride if necessary
380  // *******************************************************************************
381 
382  read_int_string(max_level, "anelastic", anelastic, 0);
383  read_int_string(max_level, "fixed_density", fixed_density, 0);
384  read_int_string(max_level, "project_initial_velocity", project_initial_velocity, 0);
385 
386  for (int i = 0; i <= max_level; ++i) {
387  if (anelastic[i] == 1) {
389  fixed_density[i] = 1; // We default to true but are allowed to override below
390  buoyancy_type[i] = 3; // (This isn't actually used when anelastic is set)
391  }
392  }
393 
394  // *******************************************************************************
395 
396  if (!upwind_real_bcs && anelastic[0]) {
397  amrex::Print() << "Setting upwind_real_bcs to true because we are doing anelastic at level 0" << std::endl;
398  upwind_real_bcs = true;
399  }
400 
401  // *******************************************************************************
402  // Read substepping_type and allow for different values at each level
403  // *******************************************************************************
404  substepping_type.resize(max_level+1);
405 
406  for (int i = 0; i <= max_level; i++) {
407  substepping_type[i] = SubsteppingType::Implicit;
408  }
409 
410  int nvals = pp.countval("substepping_type");
411  AMREX_ALWAYS_ASSERT(nvals == 0 || nvals == 1 || nvals >= max_level+1);
412 
413  if (nvals == 1) {
414  pp.query_enum_case_insensitive("substepping_type",substepping_type[0]);
415  for (int i = 1; i <= max_level; i++) {
417  }
418  } else if (nvals > 1) { // in this case we have asserted nvals >= max_level+1
419  for (int i = 0; i <= max_level; i++) {
420  pp.query_enum_case_insensitive("substepping_type",substepping_type[i],i);
421  }
422  }
423 
424  pp.query("substepping_diag", substepping_diag);
425 
426  pp.query("beta_s", beta_s);
427 
428 
429 
430  // *******************************************************************************
431  // Error check on deprecated input
432  // *******************************************************************************
433  int nvals_old = pp.countval("no_substepping");
434  if (nvals_old > 0) {
435  amrex::Error("The no_substepping flag is deprecated -- set substepping_type instead");
436  }
437 
438  // *******************************************************************************
439 
440  pp.query("ncorr", ncorr);
441  pp.query("poisson_abstol", poisson_abstol);
442  pp.query("poisson_reltol", poisson_reltol);
443 
444  for (int lev = 0; lev <= max_level; lev++) {
445  if (anelastic[lev] != 0)
446  {
447  substepping_type[lev] = SubsteppingType::None;
448  }
449  }
450 
451  pp.query("force_stage1_single_substep", force_stage1_single_substep);
452 
453  // Include Coriolis forcing?
454  pp.query("use_coriolis", use_coriolis);
455  pp.query("variable_coriolis", variable_coriolis);
456 
457  // Include four stream radiation approximation
458  pp.query("four_stream_radiation", four_stream_radiation);
459 
460  // flags for whether to apply other source terms in substep only
461  pp.query("immersed_forcing_substep", immersed_forcing_substep); // apply immersed forcing source terms in substep only
462  pp.query("forest_substep", forest_substep); // apply canopy-related source terms in substep only
463 
464  // immersed forcing parameters
465  pp.query("if_Cd_scalar", if_Cd_scalar);
466  pp.query("if_Cd_momentum", if_Cd_momentum);
467  pp.query("if_z0", if_z0);
468  pp.query("if_surf_temp_flux", if_surf_temp_flux);
469  pp.query("if_init_surf_temp", if_init_surf_temp);
470  pp.query("if_surf_heating_rate", if_surf_heating_rate);
471  pp.query("if_Olen", if_Olen_in);
472  pp.query("if_use_most",if_use_most);
473 
474  if ((if_init_surf_temp > zero && if_surf_temp_flux != 1e-8) ||
475  (if_init_surf_temp > zero && if_Olen_in != 1e-8) ||
476  (if_Olen_in != 1e-8 && if_surf_temp_flux != 1e-8))
477  {
478  amrex::Error("Can only specify one of init_surf_temp, surf_temp_flux, or Olen");
479  }
480 
481  if (if_use_most && buildings_type == BuildingsType::ImmersedForcing)
482  {
483  amrex::Error("MOST wall-model with immersed forcing for buildings is not currently supported");
484  }
485 
486  if (if_surf_temp_flux != 1e-8 && buildings_type == BuildingsType::ImmersedForcing)
487  {
488  amrex::Error("Specifying surf_temp_flux with immersed forcing for buildings is not currently supported");
489  }
490 
491  if (if_Olen_in != 1e-8 && buildings_type == BuildingsType::ImmersedForcing)
492  {
493  amrex::Error("Specifying Olen with immersed forcing for buildings is not currently supported");
494  }
495 
496  // Flag to do MOST rotations with terrain
497  pp.query("use_rotate_surface_flux",use_rotate_surface_flux);
499  AMREX_ASSERT_WITH_MESSAGE(terrain_type != TerrainType::None,"MOST stress rotations are only valid with terrain!");
500  }
501 
502  // Which external forcings?
503  abl_driver_type = ABLDriverType::None; // Default: no ABL driver for simulating classical fluid dynamics problems
504  pp.query_enum_case_insensitive("abl_driver_type",abl_driver_type);
505  pp.query("const_massflux_u", const_massflux_u);
506  pp.query("const_massflux_v", const_massflux_v);
507  pp.query("const_massflux_tau", const_massflux_tau);
508  pp.query("const_massflux_layer_lo", const_massflux_layer_lo);
509  pp.query("const_massflux_layer_hi", const_massflux_layer_hi);
510 
511  // Which type of inflow turbulent generation
512  pert_type = PerturbationType::None; // Default
513  pp.query_enum_case_insensitive("perturbation_type",pert_type);
514 
515  amrex::Vector<amrex::Real> abl_pressure_grad_in = {zero, zero, zero};
516  pp.queryarr("abl_pressure_grad",abl_pressure_grad_in);
517  for(int i = 0; i < AMREX_SPACEDIM; ++i) abl_pressure_grad[i] = abl_pressure_grad_in[i];
518 
519  amrex::Vector<amrex::Real> abl_geo_forcing_in = {zero, zero, zero};
520  if(pp.queryarr("abl_geo_forcing",abl_geo_forcing_in)) {
521  amrex::Print() << "Specified abl_geo_forcing: (";
522  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
523  abl_geo_forcing[i] = abl_geo_forcing_in[i];
524  amrex::Print() << abl_geo_forcing[i] << " ";
525  }
526  amrex::Print() << ")" << std::endl;
527  }
528 
529  if (use_coriolis)
530  {
532  }
533 
534  pp.query("add_custom_rhotheta_forcing", custom_rhotheta_forcing);
535  pp.query("add_custom_moisture_forcing", custom_moisture_forcing);
536  pp.query("add_custom_w_subsidence", custom_w_subsidence);
537  pp.query("add_do_theta_advection", do_theta_advection); // If true, apply custom subsidence to (rho*theta) when add_custom_w_subsidence is used
538  pp.query("add_do_mom_advection", do_mom_advection); // If true, apply custom subsidence to momentum when add_custom_w_subsidence is used
539  pp.query("add_custom_geostrophic_profile", custom_geostrophic_profile);
540  pp.query("custom_forcing_uses_primitive_vars", custom_forcing_prim_vars);
541  pp.query("spatial_rhotheta_forcing", spatial_rhotheta_forcing);
542  pp.query("spatial_moisture_forcing", spatial_moisture_forcing);
543 
544  pp.query("nudging_from_input_sounding", nudging_from_input_sounding);
545 
547  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(!(!abl_geo_wind_table.empty() && custom_geostrophic_profile),
548  "Should not have both abl_geo_wind_table and custom_geostrophic_profile set.");
549 
550  pp.query("Ave_Plane", ave_plane);
551 
552  // Use numerical diffusion?
553  pp.query("num_diff_coeff",num_diff_coeff);
555  "Numerical diffusion coefficient must be between 0 & one");
557  if (use_num_diff) {
558  amrex::Print() << "6th-order numerical diffusion turned on with coefficient = "
559  << num_diff_coeff << std::endl;
560  num_diff_coeff *= std::pow(two,-6);
561  }
562 
563  advChoice.init_params(pp_prefix);
564  diffChoice.init_params(pp_prefix);
565  dampingChoice.init_params(pp_prefix);
566  spongeChoice.init_params(pp_prefix);
567  ebChoice.init_params(pp_prefix);
568 
569  turbChoice.resize(max_level+1);
570  for (int lev = 0; lev <= max_level; lev++) {
571  turbChoice[lev].init_params(lev,max_level,pp_prefix);
572  }
573 
574  // YSU PBL: use consistent coriolis frequency
575  for (int lev = 0; lev <= max_level; lev++) {
576  if (turbChoice[lev].pbl_ysu_use_consistent_coriolis) {
577  if (use_coriolis) {
578  turbChoice[lev].pbl_ysu_coriolis_freq = coriolis_factor * sinphi;
579  if (lev == 0) {
580  amrex::Print() << "YSU PBL using ERF coriolis frequency: " << turbChoice[lev].pbl_ysu_coriolis_freq << std::endl;
581  }
582  } else {
583  amrex::Error("YSU cannot use ERF coriolis frequency if not using coriolis");
584  }
585  }
586  }
587  // MRF
588  for (int lev = 0; lev <= max_level; lev++) {
589  if (turbChoice[lev].pbl_ysu_use_consistent_coriolis) {
590  if (use_coriolis) {
591  turbChoice[lev].pbl_ysu_coriolis_freq = coriolis_factor * sinphi;
592  if (lev == 0) {
593  amrex::Print() << "MRF PBL using ERF coriolis frequency: " << turbChoice[lev].pbl_ysu_coriolis_freq << std::endl;
594  }
595  } else {
596  amrex::Error("MRF cannot use ERF coriolis frequency if not using coriolis");
597  }
598  }
599  }
600 
601  // What's the strength of the bdy nudging?
602  pp.query("bdy_nudge_factor",bdy_nudge_factor);
603 
604  // Are me transporting the scalar component?
605  pp.query("transport_scalar",transport_scalar);
606 
607  // Are we using SHOC? (test on compilation done in turb struct)
608  if (turbChoice[0].pbl_type == PBLType::SHOC) { use_shoc = true; }
609 
610  // Implicit vertical diffusion (not available with Shoc)
611  if (!use_shoc) {
612  // This controls the time-centering of the vertical differences in the diffusive term
613  bool do_vert_implicit = false;
614  if (pp.query("vert_implicit", do_vert_implicit) && do_vert_implicit) {
615  // set to default here
616  vert_implicit_fac[0] = one;
617  vert_implicit_fac[1] = one;
618  vert_implicit_fac[2] = zero;
619  }
620 
621  // This may be one value for all RK stages or a different value in each stage
622  int n_impfac = pp.countval("vert_implicit_fac");
623  AMREX_ALWAYS_ASSERT(n_impfac == 0 || n_impfac == 1 || n_impfac==3);
624  if (n_impfac > 0 && do_vert_implicit) {
625  amrex::Print() << "Overriding defaults with specified implicit factor(s)" << std::endl;
626  }
627 
628  if (n_impfac == 1) {
629  amrex::Real fac_in;
630  pp.get("vert_implicit_fac", fac_in);
631  for (int i=0; i<3; ++i) { vert_implicit_fac[i] = fac_in; }
632  } else if (n_impfac == 3) {
633  pp.getarr("vert_implicit_fac", vert_implicit_fac);
634  }
635 
636  // If true (default), include implicit contributions to vertical
637  // thermal diffusion
638  pp.query("implicit_thermal_diffusion", implicit_thermal_diffusion);
639 
640  // If true (default), include implicit contributions to vertical
641  // moisture diffusion
642  pp.query("implicit_moisture_diffusion", implicit_moisture_diffusion);
643 
644  // If true (default), include implicit contributions in tau13, tau23,
645  // (and if ERF_IMPLICIT_W is set, tau33) to correct u, v, (and w).
646  pp.query("implicit_momentum_diffusion", implicit_momentum_diffusion);
647 
651  amrex::Print() << "Thermal and momentum diffusion are both turned off -- turning off vertical implicit solve" << std::endl;
652  vert_implicit_fac[0] = zero;
653  vert_implicit_fac[1] = zero;
654  vert_implicit_fac[2] = zero;
655  }
656 
657  // This controls when the vertical implicit solve for the diffusive terms will happen relative to
658  // the acoustic substepping (if it happens, i.e. if any of the implicit_fac > zero)
659  // The default is true (i.e. that it happens before the acoustic substepping).
660  pp.query("implicit_before_substep", implicit_before_substep);
661  }
662 
663  // Which type of multilevel coupling
664  coupling_type = CouplingType::TwoWay; // Default
665  pp.query_enum_case_insensitive("coupling_type",coupling_type);
666 
667  // Test for hybrid (compressible + anelastic) -- in this case we must use one-way coupling
668  bool any_anelastic = false;
669  bool any_compress = false;
670  for (int lev = 0; lev <= max_level; lev++) {
671  if (anelastic[lev] == 0) {
672  any_compress = true;
673  } else {
674  any_anelastic = true;
675  }
676  }
677  if (any_anelastic && any_compress) {
678  coupling_type = CouplingType::OneWay;
679  }
680 
681  // Which type of windfarm model
682  windfarm_type = WindFarmType::None; // Default
683  pp.query_enum_case_insensitive("windfarm_type",windfarm_type);
684 
685  static std::string windfarm_loc_type_string = "None";
686  windfarm_loc_type = WindFarmLocType::None;
687  pp.query_enum_case_insensitive("windfarm_loc_type",windfarm_loc_type);
688 
689  pp.query("windfarm_loc_table", windfarm_loc_table);
690  pp.query("windfarm_spec_table", windfarm_spec_table);
691  pp.query("windfarm_blade_table", windfarm_blade_table);
692  pp.query("windfarm_airfoil_tables", windfarm_airfoil_tables);
693  pp.query("windfarm_spec_table_extra", windfarm_spec_table_extra);
694 
695  // Sampling distance upstream of the turbine to find the
696  // incoming free stream velocity as a factor of the diameter of the
697  // turbine. ie. the sampling distance will be this number multiplied
698  // by the diameter of the turbine
699  pp.query("sampling_distance_by_D", sampling_distance_by_D);
700  pp.query("turb_disk_angle_from_x", turb_disk_angle);
701 
702  pp.query("windfarm_x_shift",windfarm_x_shift);
703  pp.query("windfarm_y_shift",windfarm_y_shift);
704  // Test if time averaged data is to be output
705  pp.query("time_avg_vel",time_avg_vel);
706 
707  pp.query("hindcast_lateral_forcing", hindcast_lateral_forcing);
708 
710  pp.query("hindcast_boundary_data_dir", hindcast_boundary_data_dir);
711 
712  if(hindcast_boundary_data_dir.empty()) {
713  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_boundary_data_dir' for boundary data for lateral forcing");
714  }
715  pp.query("hindcast_data_interval_in_hrs", hindcast_data_interval_in_hrs);
717  amrex::Error("ERROR: Input parameter 'erf.hindcast_data_interval_in_hrs' which is the time interval between the "
718  "data files is either missing or set to less than zero");
719  }
720  pp.query("hindcast_lateral_sponge_strength", hindcast_lateral_sponge_strength);
721  pp.query("hindcast_lateral_sponge_length", hindcast_lateral_sponge_length);
722 
723  pp.query("hindcast_zhi_sponge_length", hindcast_zhi_sponge_length);
724  pp.query("hindcast_zhi_sponge_strength", hindcast_zhi_sponge_strength);
725 
726  pp.query("hindcast_zhi_sponge_damping", hindcast_zhi_sponge_damping);
727 
729  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_lateral_sponge_strength' or it is specified to be less than zero");
730  }
731 
733  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_lateral_sponge_length' or it is specified to be less than zero");
734  }
735 
737  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_zhi_sponge_strength' or it is specified to be less than zero");
738  }
739 
741  amrex::Error("ERROR: Missing input parameter 'erf.hindcast_zhi_sponge_strength' or it is specified to be less than zero");
742  }
743  }
744 
745  pp.query("hindcast_surface_bcs", hindcast_surface_bcs);
747  pp.query("hindcast_surface_data_dir", hindcast_surface_data_dir);
748  }
749 
750  pp.query("io_hurricane_eye_tracker", io_hurricane_eye_tracker);
752  pp.query("hurricane_eye_latitude", hurricane_eye_latitude);
753  pp.query("hurricane_eye_longitude", hurricane_eye_longitude);
754  if(hurricane_eye_latitude == -1e10 or hurricane_eye_longitude == -1e10) {
755  amrex::Error("ERROR: You are using 'erf.io_hurricane_eye_tracker' to write out the files that track the eye of the hurricane"
756  " but have not provided the initial location of the eye of the hurricane to be tracked. There has to be two"
757  " options in the inputs - erf.hurricane_eye_latitude and erf.hurricane_eye_longitude that gives an approximate"
758  " location of the eye in the initial condition");
759  }
760  }
761 
762  amrex::ParmParse pp_ens("ensemble");
763  pp_ens.query("is_init_with_correlated_pert", is_init_with_correlated_pert);
765  pp_ens.query("pert_correlated_radius", pert_correlated_radius);
767  amrex::Error("You are using initialization with spatially correlated perturbations using the inputs option "
768  "ensemble.is_init_with_correlated_pert=true. In this case, there has to be an option "
769  "ensemble.pert_correlated_radius which is the value of the the spatial correlation radius, "
770  "and has to be greater than zero");
771  }
772  }
773  }
774 
775  void check_params (int max_level, const amrex::Vector<amrex::Geometry>& geom_vect, amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2> phys_bc_type)
776  {
777 #if 0
778  // Warn for PBL models and moisture - these may not yet be compatible
779  for (int lev = 0; lev <= max_level; lev++) {
780  if ((moisture_type != MoistureType::None) && (turbChoice[lev].pbl_type != PBLType::None)) {
781  amrex::Warning("\n*** WARNING: Moisture may not yet be compatible with PBL models, \n proceed with caution ***");
782  }
783  }
784 #endif
785  //
786  // Buoyancy type check
787  //
788  for (int lev = 0; lev <= max_level; lev++) {
789  if (buoyancy_type[lev] != 1 && buoyancy_type[lev] != 2 && buoyancy_type[lev] != 3 && buoyancy_type[lev] != 4) {
790  amrex::Error("buoyancy_type must be 1, 2, 3 or 4");
791  }
792  }
793 
794  if (!use_lagged_delta_rt && !(terrain_type == TerrainType::MovingFittedMesh)) {
795  amrex::Error("Can't turn off lagged_delta_rt when terrain not moving");
796  }
797 
798  //
799  // Wind farm checks
800  //
801  if (windfarm_type==WindFarmType::SimpleAD and sampling_distance_by_D < zero) {
802  amrex::Error("To use simplified actuator disks, you need to provide a variable"
803  " erf.sampling_distance_by_D in the inputs which specifies the upstream"
804  " distance as a factor of the turbine diameter at which the incoming free stream"
805  " velocity will be computed at.");
806  }
807  if ( (windfarm_type==WindFarmType::SimpleAD ||
808  windfarm_type==WindFarmType::GeneralAD ) && turb_disk_angle < zero) {
809  amrex::Error("To use simplified actuator disks, you need to provide a variable"
810  " erf.turb_disk_angle_from_x in the inputs which is the angle of the face of the"
811  " turbine disk from the x-axis. A turbine facing an oncoming flow in the x-direction"
812  " will have turb_disk_angle value of 90 deg.");
813  }
814  if (windfarm_loc_type == WindFarmLocType::lat_lon and (windfarm_x_shift < zero or windfarm_y_shift < zero)) {
815  amrex::Error("You are using windfarms with latitude-logitude option to position the turbines."
816  " For this you should provide the inputs erf.windfarm_x_shift and"
817  " erf.windfarm_y_shift which are the values by which the bounding box of the"
818  " windfarm is shifted from the x and the y axes.");
819  }
820 
821 
822  if ( (const_massflux_u != 0) && !(geom_vect[0].isPeriodic(0)) ) {
823  amrex::Error("Constant mass flux (in x) should be used with periodic boundaries");
824  }
825 
826  if ( (const_massflux_v != 0) && !(geom_vect[0].isPeriodic(1)) ) {
827  amrex::Error("Constant mass flux (in y) should be used with periodic boundaries");
828  }
829 
830  // Mesoscale diffusion -- test if LES appropriate with this dx,dy
831  for (int lev = 0; lev <= max_level; lev++) {
832  if ((geom_vect[lev].CellSize(0) > amrex::Real(2000.)) || (geom_vect[lev].CellSize(1) > amrex::Real(2000.)))
833  {
834  if ( (turbChoice[lev].les_type == LESType::Smagorinsky) && !turbChoice[lev].smag2d ) {
835  amrex::Warning("Should use 2-D Smagorinsky for mesoscale resolution");
836  } else if (turbChoice[lev].les_type == LESType::Deardorff) {
837  amrex::Warning("Should not use Deardorff LES for mesoscale resolution");
838  }
839  }
840  }
841 
842  // Turn off implicit solve if we have no diffusion
843  bool l_use_kturb = turbChoice[0].use_kturb;
844  for (int lev = 1; lev <= max_level; lev++) {
845  l_use_kturb = (l_use_kturb || turbChoice[lev].use_kturb);
846  }
847  bool l_use_diff = ( (diffChoice.molec_diff_type != MolecDiffType::None) || l_use_kturb );
848  bool l_implicit_diff = (vert_implicit_fac[0] > 0 ||
849  vert_implicit_fac[1] > 0 ||
850  vert_implicit_fac[2] > 0);
851  if (l_implicit_diff && !l_use_diff) {
852  amrex:: Print() << "No molecular or turbulent diffusion, turning off implicit solve" << std::endl;
853  vert_implicit_fac[0] = 0;
854  vert_implicit_fac[1] = 0;
855  vert_implicit_fac[2] = 0;
856  }
857 
858  for (int lev = 0; lev <= max_level; lev++) {
859  turbChoice[lev].check_params(phys_bc_type);
860  }
861  }
862 
863  void display (int max_level, std::string pp_prefix)
864  {
865  amrex::Print() << "SOLVER CHOICE: " << std::endl;
866  for (int lev = 0; lev <= max_level; lev++) {
867  amrex::Print() << "At level " << lev << " : " << std::endl;
868  if (anelastic[lev]) {
869  amrex::Print() << " anelastic with no substepping" << std::endl;
870  } else {
871  if (substepping_type[lev] == SubsteppingType::None) {
872  amrex::Print() << " compressible with no substepping" << std::endl;
873  } else if (substepping_type[lev] == SubsteppingType::Implicit) {
874  amrex::Print() << " compressible with implicit substepping" << std::endl;
875  }
876  }
877  if (fixed_density[lev]) {
878  amrex::Print() << " and fixed density" << std::endl;
879  }
880  }
881 
882  amrex::Print() << "vert_implicit_fac : " << vert_implicit_fac[0] << " "
883  << vert_implicit_fac[1] << " "
884  << vert_implicit_fac[2];
885  if (vert_implicit_fac[0] > 0 ||
886  vert_implicit_fac[0] > 1 ||
887  vert_implicit_fac[0] > 2)
888  {
889  amrex::Print() << " (theta=" << implicit_thermal_diffusion
890  << ", moisture=" << implicit_moisture_diffusion
891  << ", momenta=" << implicit_momentum_diffusion;
892 #ifdef ERF_IMPLICIT_W
893  amrex::Print() << ", including w";
894 #endif
895  amrex::Print() << ")";
896  }
897  amrex::Print() << std::endl;
898  amrex::Print() << "use_coriolis : " << use_coriolis << std::endl;
899  amrex::Print() << "use_gravity : " << use_gravity << std::endl;
900 
901  if (moisture_type == MoistureType::SAM) {
902  amrex::Print() << "Moisture Model: SAM" << std::endl;
903  } else if (moisture_type == MoistureType::SAM_NoIce) {
904  amrex::Print() << "Moisture Model: SAM No Ice" << std::endl;
905  } else if (moisture_type == MoistureType::SAM_NoPrecip_NoIce) {
906  amrex::Print() << "Moisture Model: SAM No Precip No Ice" << std::endl;
907  } else if (moisture_type == MoistureType::Morrison) {
908  amrex::Print() << "Moisture Model: Morrison" << std::endl;
909  } else if (moisture_type == MoistureType::Morrison_NoIce) {
910  amrex::Print() << "Moisture Model: Morrison_NoIce" << std::endl;
911  } else if (moisture_type == MoistureType::WSM6) {
912  amrex::Print() << "Moisture Model: WSM6" << std::endl;
913  } else if (moisture_type == MoistureType::Kessler) {
914  amrex::Print() << "Moisture Model: Kessler" << std::endl;
915  } else if (moisture_type == MoistureType::Kessler_NoRain) {
916  amrex::Print() << "Moisture Model: Kessler No Rain" << std::endl;
917  } else if (moisture_type == MoistureType::SatAdj) {
918  amrex::Print() << "Moisture Model: Saturation Adjustment" << std::endl;
919  } else {
920  amrex::Print() << "Moisture Model: None" << std::endl;
921  }
922 
923  if (terrain_type == TerrainType::StaticFittedMesh) {
924  amrex::Print() << "Terrain Type: StaticFittedMesh" << std::endl;
925  } else if (terrain_type == TerrainType::MovingFittedMesh) {
926  amrex::Print() << "Terrain Type: MovingFittedMesh" << std::endl;
927  } else if (terrain_type == TerrainType::EB) {
928  amrex::Print() << "Terrain Type: EB" << std::endl;
929  ebChoice.display();
930  } else if (terrain_type == TerrainType::ImmersedForcing) {
931  amrex::Print() << "Terrain Type: ImmersedForcing" << std::endl;
932  } else {
933  amrex::Print() << "Terrain Type: None" << std::endl;
934  }
935 
936  if (buildings_type == BuildingsType::ImmersedForcing) {
937  amrex::Print() << "Buildings Type: ImmersedForcing" << std::endl;
938  } else {
939  amrex::Print() << "Buildings Type: None" << std::endl;
940  }
941 
942  if (mesh_type == MeshType::ConstantDz) {
943  amrex::Print() << " Mesh Type: ConstantDz" << std::endl;
944  } else if (mesh_type == MeshType::StretchedDz) {
945  amrex::Print() << " Mesh Type: StretchedDz" << std::endl;
946  } else if (mesh_type == MeshType::VariableDz) {
947  amrex::Print() << " Mesh Type: VariableDz" << std::endl;
948  } else {
949  amrex::Error("No mesh_type set!");
950  }
951 
952  amrex::Print() << "ABL Driver Type: " << std::endl;
953  if (abl_driver_type == ABLDriverType::None) {
954  amrex::Print() << " None" << std::endl;
955  } else if (abl_driver_type == ABLDriverType::PressureGradient) {
956  amrex::Print() << " Pressure Gradient "
957  << amrex::RealVect(abl_pressure_grad[0],abl_pressure_grad[1],abl_pressure_grad[2])
958  << std::endl;
959  } else if (abl_driver_type == ABLDriverType::GeostrophicWind) {
960  amrex::Print() << " Geostrophic Wind "
961  << amrex::RealVect(abl_geo_forcing[0],abl_geo_forcing[1],abl_geo_forcing[2])
962  << std::endl;
963  }
964 
965  if (max_level > 0) {
966  amrex::Print() << "Coupling Type: " << std::endl;
967  if (coupling_type == CouplingType::TwoWay) {
968  amrex::Print() << " Two-way" << std::endl;
969  } else if (coupling_type == CouplingType::OneWay) {
970  amrex::Print() << " One-way" << std::endl;
971  }
972  }
973 
974  if (rad_type == RadiationType::RRTMGP) {
975  amrex::Print() << "Radiation Model: RRTMGP" << std::endl;
976  } else {
977  amrex::Print() << "Radiation Model: None" << std::endl;
978  }
979 
980  amrex::Print() << "Gradp_type : " << gradp_type << std::endl;
981 
982  for (int lev = 0; lev <= max_level; lev++) {
983  amrex::Print() << "Buoyancy_type at level " << lev << " : " << buoyancy_type[lev] << std::endl;
984  }
985 
986  advChoice.display(pp_prefix);
990 
991  for (int lev = 0; lev <= max_level; lev++) {
992  turbChoice[lev].display(lev);
993  }
994  }
995 
996  void build_coriolis_forcings_const_lat (std::string pp_prefix)
997  {
998  amrex::ParmParse pp(pp_prefix);
999 
1000  // Read the rotational time period (in seconds)
1001  amrex::Real rot_time_period = amrex::Real(86400.0);
1002  pp.query("rotational_time_period", rot_time_period);
1003 
1004  coriolis_factor = two * two * PI / rot_time_period;
1005 
1006  amrex::Real latitude = amrex::Real(90.0);
1007  pp.query("latitude", latitude);
1008 
1009  pp.query("coriolis_3d", coriolis_3d);
1010 
1011  // Convert to radians
1012  latitude *= (PI/amrex::Real(180.));
1013  sinphi = std::sin(latitude);
1014  if (coriolis_3d) {
1015  cosphi = std::cos(latitude);
1016  }
1017 
1018  amrex::Print() << "Coriolis frequency, f = " << coriolis_factor * sinphi << " 1/s" << std::endl;
1019 
1020  if (abl_driver_type == ABLDriverType::GeostrophicWind) {
1021  // Read in the geostrophic wind -- we only use this to construct
1022  // the forcing term so no need to keep it
1023  amrex::Vector<amrex::Real> abl_geo_wind(3);
1024  pp.queryarr("abl_geo_wind",abl_geo_wind);
1025 
1026  if(!pp.query("abl_geo_wind_table",abl_geo_wind_table)) {
1027  abl_geo_forcing = {
1028  -coriolis_factor * (abl_geo_wind[1]*sinphi - abl_geo_wind[2]*cosphi),
1029  coriolis_factor * abl_geo_wind[0]*sinphi,
1030  -coriolis_factor * abl_geo_wind[0]*cosphi
1031  };
1032  } else {
1033  amrex::Print() << "NOTE: abl_geo_wind_table provided, ignoring input abl_geo_wind" << std::endl;
1034  }
1035  }
1036  }
1037 
1038  void read_int_string (int max_level, const char* string_to_read,
1039  amrex::Vector<int>& vec_to_fill, int default_int)
1040  {
1041  amrex::ParmParse pp("erf");
1042  int nvals = pp.countval(string_to_read);
1043  AMREX_ALWAYS_ASSERT(nvals == 0 || nvals == 1 || nvals >= max_level+1);
1044  amrex::Vector<int> temp; temp.resize(nvals);
1045  pp.queryarr(string_to_read,temp);
1046 
1047  if (vec_to_fill.size() < max_level+1) {
1048  vec_to_fill.resize(max_level+1);
1049  }
1050 
1051  if (nvals == 0) {
1052  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = default_int;
1053  } else if (nvals == 1) {
1054  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = temp[0];
1055  } else {
1056  for (int i = 0; i <= max_level; ++i) vec_to_fill[i] = temp[i];
1057  }
1058  }
1059 
1060  inline static
1061  InitType init_type = InitType::None;
1062 
1063  inline static
1064  SoundingType sounding_type = SoundingType::Ideal;
1065 
1066  inline static
1067  TerrainType terrain_type = TerrainType::None;
1068 
1069  inline static
1070  BuildingsType buildings_type = BuildingsType::None;
1071 
1072  inline static
1073  bool use_real_bcs = false;
1074 
1075  inline static
1076  bool upwind_real_bcs = false;
1077 
1078  inline static
1079  MeshType mesh_type = MeshType::ConstantDz;
1080 
1081  static
1082  void set_mesh_type (MeshType new_mesh_type)
1083  {
1084  mesh_type = new_mesh_type;
1085  }
1086 
1091  amrex::Vector<TurbChoice> turbChoice;
1093 
1095 
1096  amrex::Vector<SubsteppingType> substepping_type;
1097  amrex::Vector<int> anelastic;
1098  amrex::Vector<int> fixed_density;
1099  amrex::Vector<int> project_initial_velocity;
1100  amrex::Vector<int> buoyancy_type;
1101 
1102  // do some extra CFL diagnostics for compressible with substepping
1103  bool substepping_diag = false;
1104 
1105  // time off-centering coefficient, > 0 for forward weighting (i.e., bias
1106  // towards the future time step)
1108 
1109  // This controls the time-centering of the *vertical* differences in the diffusive term for
1110  // theta, u, v (and w if ERF_IMPLICIT_W is set)
1111  // 0: fully explicit
1112  // 1: fully implicit
1113  amrex::Vector<amrex::Real> vert_implicit_fac = {zero, zero, zero}; // one value per RK stage
1114  // if any vert_implicit_fac > 0, then the following apply:
1119 
1120  int ncorr = 1;
1123 
1124  bool test_mapfactor = false;
1125 
1126  int gradp_type = 0;
1127 
1128  // Specify what additional physics/forcing modules we use
1129  bool use_gravity = false;
1130  bool use_coriolis = false;
1131  bool coriolis_3d = true;
1132 
1134 
1135  // Specify whether to apply other various source terms on substep only
1137  bool forest_substep = false;
1138 
1139  // immersed forcing parameters
1142  // immersed forcing MOST parameters.
1144  amrex::Real if_surf_temp_flux = 1e-8; // [K m/s]
1147  amrex::Real if_Olen_in = 1e-8; // [m]
1148  bool if_use_most = false;
1149 
1150  // This defaults to true but can be set to false for moving terrain cases only
1151  bool use_lagged_delta_rt = true;
1152 
1153  // Constants
1155  amrex::Real c_p = Cp_d; // specific heat at constant pressure for dry air [J/(kg-K)]
1157 
1158  // Staggered z levels for vertical grid stretching
1162 
1163  // Coriolis forcing
1167 
1168  // User-specified forcings in problem definition
1171  bool custom_w_subsidence = false;
1172  bool do_theta_advection = true; // Apply custom vertical subsidence to (rho*theta) equation when using custom w subsidence
1173  bool do_mom_advection = true; // Apply custom vertical subsidence to momentum equations when using custom w subsidence
1178 
1179  // Do we use source terms to nudge the solution towards
1180  // the time-varying data provided in input sounding files?
1182 
1183  // MOST stress rotations
1185 
1186  // Should we use SHOC?
1187  bool use_shoc = false;
1188 
1189  // Transport the passive scalar?
1190  bool transport_scalar = true;
1191 
1192  // User wishes to output time averaged velocity fields
1193  bool time_avg_vel = false;
1194 
1195  // Type of perturbation
1196  PerturbationType pert_type;
1197 
1198  // Numerical diffusion
1199  bool use_num_diff{false};
1201 
1202  // Rebalance wrfinput
1203  bool rebalance_wrfinput{false};
1204 
1205  CouplingType coupling_type;
1206  MoistureType moisture_type;
1207  WindFarmType windfarm_type;
1208  WindFarmLocType windfarm_loc_type;
1209  LandSurfaceType lsm_type;
1210  RadiationType rad_type;
1211 
1212  ABLDriverType abl_driver_type;
1213  amrex::GpuArray<amrex::Real, AMREX_SPACEDIM> abl_pressure_grad;
1214  amrex::GpuArray<amrex::Real, AMREX_SPACEDIM> abl_geo_forcing;
1215  std::string abl_geo_wind_table;
1217 
1218  bool variable_coriolis{false};
1219 
1220  int ave_plane {2};
1221 
1222  // Microphysics params
1224 
1226 
1233 
1234  // Nudging factor for bdy sponging : F1 = 1/(nudge_factor * dt)
1236 
1237  // Use forest canopy model?
1238  bool do_forest_drag {false};
1239 
1240  // Enforce constant mass flux?
1246  int massflux_klo {0}; // these are updated in ERF.cpp
1247  int massflux_khi {0};
1248 
1252  bool hindcast_surface_bcs = false;
1256 
1259 
1262 };
1263 #endif
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:22
constexpr amrex::Real two
Definition: ERF_Constants.H:8
constexpr amrex::Real one
Definition: ERF_Constants.H:7
constexpr amrex::Real zero
Definition: ERF_Constants.H:6
constexpr amrex::Real PI
Definition: ERF_Constants.H:16
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:31
constexpr amrex::Real R_d
Definition: ERF_Constants.H:20
TauType
Definition: ERF_DataStruct.H:31
@ tau12
Definition: ERF_DataStruct.H:32
@ tau23
Definition: ERF_DataStruct.H:32
@ tau33
Definition: ERF_DataStruct.H:32
@ tau22
Definition: ERF_DataStruct.H:32
@ tau11
Definition: ERF_DataStruct.H:32
@ tau32
Definition: ERF_DataStruct.H:32
@ tau31
Definition: ERF_DataStruct.H:32
@ tau21
Definition: ERF_DataStruct.H:32
@ tau13
Definition: ERF_DataStruct.H:32
AMREX_ENUM(InitType, None, Input_Sounding, NCFile, WRFInput, Metgrid, Uniform, ConstantDensity, ConstantDensityLinearTheta, Isentropic, MoistBaseState, HindCast)
Rayleigh
Definition: ERF_DataStruct.H:97
@ ubar
Definition: ERF_DataStruct.H:98
@ wbar
Definition: ERF_DataStruct.H:98
@ nvars
Definition: ERF_DataStruct.H:98
@ vbar
Definition: ERF_DataStruct.H:98
@ thetabar
Definition: ERF_DataStruct.H:98
Sponge
Definition: ERF_DataStruct.H:102
@ nvars_sponge
Definition: ERF_DataStruct.H:103
@ vbar_sponge
Definition: ERF_DataStruct.H:103
@ ubar_sponge
Definition: ERF_DataStruct.H:103
MapFacType
Definition: ERF_DataStruct.H:22
@ v_x
Definition: ERF_DataStruct.H:24
@ num
Definition: ERF_DataStruct.H:24
@ u_y
Definition: ERF_DataStruct.H:25
@ v_y
Definition: ERF_DataStruct.H:25
@ m_y
Definition: ERF_DataStruct.H:25
@ u_x
Definition: ERF_DataStruct.H:24
@ m_x
Definition: ERF_DataStruct.H:24
Coord
Definition: ERF_DataStruct.H:92
#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 RhoQ1_comp
Definition: ERF_IndexDefines.H:42
#define RhoQ6_comp
Definition: ERF_IndexDefines.H:47
#define RhoQ5_comp
Definition: ERF_IndexDefines.H:46
ParmParse pp("prob")
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
amrex::Real Real
Definition: ERF_ShocInterface.H:19
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:38
Definition: ERF_MM5.H:26
Definition: ERF_Morrison.H:58
Definition: ERF_NOAHMP.H:53
Definition: ERF_SAM.H:53
Definition: ERF_SLM.H:26
Definition: ERF_SatAdj.H:41
Definition: ERF_SimpleAD.H:8
Definition: ERF_WSM6.H:37
Definition: ERF_AdvStruct.H:19
void display(std::string &pp_prefix)
Definition: ERF_AdvStruct.H:235
void init_params(std::string pp_prefix)
Definition: ERF_AdvStruct.H:21
Definition: ERF_DampingStruct.H:19
void init_params(std::string pp_prefix)
Definition: ERF_DampingStruct.H:21
void display()
Definition: ERF_DampingStruct.H:61
Definition: ERF_DiffStruct.H:19
void init_params(std::string pp_prefix)
Definition: ERF_DiffStruct.H:21
void display()
Definition: ERF_DiffStruct.H:67
MolecDiffType molec_diff_type
Definition: ERF_DiffStruct.H:84
Definition: ERF_EBStruct.H:23
void init_params(std::string pp_prefix)
Definition: ERF_EBStruct.H:25
void display()
Definition: ERF_EBStruct.H:43
Definition: ERF_DataStruct.H:106
int qs
Definition: ERF_DataStruct.H:111
int qr
Definition: ERF_DataStruct.H:110
MoistureComponentIndices()=default
int qi
Definition: ERF_DataStruct.H:109
int qv
Definition: ERF_DataStruct.H:107
int qc
Definition: ERF_DataStruct.H:108
int qg
Definition: ERF_DataStruct.H:112
MoistureComponentIndices(int qv_comp, int qc_comp, int qi_comp=-1, int qr_comp=-1, int qs_comp=-1, int qg_comp=-1)
Definition: ERF_DataStruct.H:115
Definition: ERF_DataStruct.H:130
bool is_init_with_correlated_pert
Definition: ERF_DataStruct.H:1260
amrex::Real hurricane_eye_latitude
Definition: ERF_DataStruct.H:1258
bool do_mom_advection
Definition: ERF_DataStruct.H:1173
amrex::Real if_init_surf_temp
Definition: ERF_DataStruct.H:1145
amrex::Real dz0
Definition: ERF_DataStruct.H:1161
amrex::Real const_massflux_layer_lo
Definition: ERF_DataStruct.H:1244
bool use_lagged_delta_rt
Definition: ERF_DataStruct.H:1151
amrex::Real coriolis_factor
Definition: ERF_DataStruct.H:1164
static MeshType mesh_type
Definition: ERF_DataStruct.H:1079
amrex::Real if_surf_temp_flux
Definition: ERF_DataStruct.H:1144
amrex::Real windfarm_x_shift
Definition: ERF_DataStruct.H:1231
void check_params(int max_level, const amrex::Vector< amrex::Geometry > &geom_vect, amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 > phys_bc_type)
Definition: ERF_DataStruct.H:775
amrex::Real pert_correlated_radius
Definition: ERF_DataStruct.H:1261
void display(int max_level, std::string pp_prefix)
Definition: ERF_DataStruct.H:863
bool rebalance_wrfinput
Definition: ERF_DataStruct.H:1203
amrex::Real hindcast_lateral_sponge_strength
Definition: ERF_DataStruct.H:1253
amrex::Real poisson_reltol
Definition: ERF_DataStruct.H:1122
void build_coriolis_forcings_const_lat(std::string pp_prefix)
Definition: ERF_DataStruct.H:996
bool if_use_most
Definition: ERF_DataStruct.H:1148
DampingChoice dampingChoice
Definition: ERF_DataStruct.H:1089
amrex::Real rdOcp
Definition: ERF_DataStruct.H:1156
bool spatial_moisture_forcing
Definition: ERF_DataStruct.H:1177
RadiationType rad_type
Definition: ERF_DataStruct.H:1210
void read_int_string(int max_level, const char *string_to_read, amrex::Vector< int > &vec_to_fill, int default_int)
Definition: ERF_DataStruct.H:1038
amrex::Vector< int > project_initial_velocity
Definition: ERF_DataStruct.H:1099
std::string windfarm_spec_table
Definition: ERF_DataStruct.H:1227
amrex::Real hindcast_zhi_sponge_length
Definition: ERF_DataStruct.H:1254
DiffChoice diffChoice
Definition: ERF_DataStruct.H:1088
amrex::Real const_massflux_v
Definition: ERF_DataStruct.H:1242
amrex::Real if_z0
Definition: ERF_DataStruct.H:1143
bool use_gravity
Definition: ERF_DataStruct.H:1129
int ncorr
Definition: ERF_DataStruct.H:1120
int force_stage1_single_substep
Definition: ERF_DataStruct.H:1094
bool hindcast_zhi_sponge_damping
Definition: ERF_DataStruct.H:1255
std::string windfarm_spec_table_extra
Definition: ERF_DataStruct.H:1227
amrex::Real cosphi
Definition: ERF_DataStruct.H:1165
LandSurfaceType lsm_type
Definition: ERF_DataStruct.H:1209
amrex::Real c_p
Definition: ERF_DataStruct.H:1155
amrex::Vector< int > buoyancy_type
Definition: ERF_DataStruct.H:1100
std::string windfarm_loc_table
Definition: ERF_DataStruct.H:1227
bool do_theta_advection
Definition: ERF_DataStruct.H:1172
amrex::Real gravity
Definition: ERF_DataStruct.H:1154
amrex::Real bdy_nudge_factor
Definition: ERF_DataStruct.H:1235
amrex::Real beta_s
Definition: ERF_DataStruct.H:1107
bool custom_rhotheta_forcing
Definition: ERF_DataStruct.H:1169
amrex::Real hindcast_lateral_sponge_length
Definition: ERF_DataStruct.H:1253
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_geo_forcing
Definition: ERF_DataStruct.H:1214
bool use_shoc
Definition: ERF_DataStruct.H:1187
WindFarmLocType windfarm_loc_type
Definition: ERF_DataStruct.H:1208
bool hindcast_lateral_forcing
Definition: ERF_DataStruct.H:1251
int massflux_klo
Definition: ERF_DataStruct.H:1246
bool moisture_tight_coupling
Definition: ERF_DataStruct.H:1225
bool custom_w_subsidence
Definition: ERF_DataStruct.H:1171
bool nudging_from_input_sounding
Definition: ERF_DataStruct.H:1181
bool custom_geostrophic_profile
Definition: ERF_DataStruct.H:1174
amrex::Real if_Cd_scalar
Definition: ERF_DataStruct.H:1140
bool immersed_forcing_substep
Definition: ERF_DataStruct.H:1136
amrex::Real grid_stretching_ratio
Definition: ERF_DataStruct.H:1159
amrex::Real sinphi
Definition: ERF_DataStruct.H:1166
bool have_geo_wind_profile
Definition: ERF_DataStruct.H:1216
amrex::Vector< amrex::Real > vert_implicit_fac
Definition: ERF_DataStruct.H:1113
amrex::Real hurricane_eye_longitude
Definition: ERF_DataStruct.H:1258
amrex::Real const_massflux_u
Definition: ERF_DataStruct.H:1241
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_pressure_grad
Definition: ERF_DataStruct.H:1213
bool implicit_moisture_diffusion
Definition: ERF_DataStruct.H:1116
std::string hindcast_surface_data_dir
Definition: ERF_DataStruct.H:1249
void init_params(int max_level, std::string pp_prefix)
Definition: ERF_DataStruct.H:132
bool io_hurricane_eye_tracker
Definition: ERF_DataStruct.H:1257
amrex::Vector< SubsteppingType > substepping_type
Definition: ERF_DataStruct.H:1096
bool coriolis_3d
Definition: ERF_DataStruct.H:1131
amrex::Real if_Olen_in
Definition: ERF_DataStruct.H:1147
bool use_num_diff
Definition: ERF_DataStruct.H:1199
amrex::Real sampling_distance_by_D
Definition: ERF_DataStruct.H:1229
bool implicit_thermal_diffusion
Definition: ERF_DataStruct.H:1115
amrex::Real hindcast_zhi_sponge_strength
Definition: ERF_DataStruct.H:1254
bool test_mapfactor
Definition: ERF_DataStruct.H:1124
bool use_coriolis
Definition: ERF_DataStruct.H:1130
static SoundingType sounding_type
Definition: ERF_DataStruct.H:1064
bool four_stream_radiation
Definition: ERF_DataStruct.H:1133
bool custom_moisture_forcing
Definition: ERF_DataStruct.H:1170
amrex::Real num_diff_coeff
Definition: ERF_DataStruct.H:1200
std::string windfarm_blade_table
Definition: ERF_DataStruct.H:1228
amrex::Real zsurf
Definition: ERF_DataStruct.H:1160
amrex::Real if_surf_heating_rate
Definition: ERF_DataStruct.H:1146
amrex::Vector< TurbChoice > turbChoice
Definition: ERF_DataStruct.H:1091
bool variable_coriolis
Definition: ERF_DataStruct.H:1218
amrex::Vector< int > anelastic
Definition: ERF_DataStruct.H:1097
amrex::Real if_Cd_momentum
Definition: ERF_DataStruct.H:1141
static bool upwind_real_bcs
Definition: ERF_DataStruct.H:1076
AdvChoice advChoice
Definition: ERF_DataStruct.H:1087
MoistureType moisture_type
Definition: ERF_DataStruct.H:1206
bool custom_forcing_prim_vars
Definition: ERF_DataStruct.H:1175
std::string abl_geo_wind_table
Definition: ERF_DataStruct.H:1215
static BuildingsType buildings_type
Definition: ERF_DataStruct.H:1070
static TerrainType terrain_type
Definition: ERF_DataStruct.H:1067
amrex::Real hindcast_data_interval_in_hrs
Definition: ERF_DataStruct.H:1250
ABLDriverType abl_driver_type
Definition: ERF_DataStruct.H:1212
amrex::Vector< int > fixed_density
Definition: ERF_DataStruct.H:1098
PerturbationType pert_type
Definition: ERF_DataStruct.H:1196
SpongeChoice spongeChoice
Definition: ERF_DataStruct.H:1090
WindFarmType windfarm_type
Definition: ERF_DataStruct.H:1207
static InitType init_type
Definition: ERF_DataStruct.H:1061
bool substepping_diag
Definition: ERF_DataStruct.H:1103
bool implicit_momentum_diffusion
Definition: ERF_DataStruct.H:1117
amrex::Real const_massflux_layer_hi
Definition: ERF_DataStruct.H:1245
bool implicit_before_substep
Definition: ERF_DataStruct.H:1118
static bool use_real_bcs
Definition: ERF_DataStruct.H:1073
amrex::Real poisson_abstol
Definition: ERF_DataStruct.H:1121
MoistureComponentIndices moisture_indices
Definition: ERF_DataStruct.H:1223
amrex::Real turb_disk_angle
Definition: ERF_DataStruct.H:1230
bool hindcast_surface_bcs
Definition: ERF_DataStruct.H:1252
amrex::Real windfarm_y_shift
Definition: ERF_DataStruct.H:1232
bool use_rotate_surface_flux
Definition: ERF_DataStruct.H:1184
bool do_forest_drag
Definition: ERF_DataStruct.H:1238
amrex::Real const_massflux_tau
Definition: ERF_DataStruct.H:1243
int massflux_khi
Definition: ERF_DataStruct.H:1247
bool time_avg_vel
Definition: ERF_DataStruct.H:1193
bool spatial_rhotheta_forcing
Definition: ERF_DataStruct.H:1176
bool forest_substep
Definition: ERF_DataStruct.H:1137
EBChoice ebChoice
Definition: ERF_DataStruct.H:1092
CouplingType coupling_type
Definition: ERF_DataStruct.H:1205
std::string windfarm_airfoil_tables
Definition: ERF_DataStruct.H:1228
bool transport_scalar
Definition: ERF_DataStruct.H:1190
int gradp_type
Definition: ERF_DataStruct.H:1126
static void set_mesh_type(MeshType new_mesh_type)
Definition: ERF_DataStruct.H:1082
int ave_plane
Definition: ERF_DataStruct.H:1220
std::string hindcast_boundary_data_dir
Definition: ERF_DataStruct.H:1249
Definition: ERF_SpongeStruct.H:15
void display()
Definition: ERF_SpongeStruct.H:47
void init_params(std::string pp_prefix)
Definition: ERF_SpongeStruct.H:17