ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TurbStruct.H
Go to the documentation of this file.
1 #ifndef ERF_TURB_STRUCT_H_
2 #define ERF_TURB_STRUCT_H_
3 
4 #include <ERF_MYNNStruct.H>
5 
6 AMREX_ENUM(LESType, None, Smagorinsky, Smagorinsky2D, Deardorff);
7 
8 AMREX_ENUM(RANSType, None, kEqn);
9 
10 AMREX_ENUM(PBLType, None, MYJ, MYNN25, MYNNEDMF, YSU, YSUNew, MRF, SHOC, EAMXX_SHOC, NATIVE_SHOC);
11 
12 AMREX_ENUM(StratType, theta, thetav, thetal);
13 
14 template <typename T>
15 int
17  const amrex::ParmParse& pp,
18  const char* query_string,
19  T& query_var,
20  const int lev,
21  const int maxlev)
22 {
23  int count = pp.countval(query_string);
24  if (count == 0) {
25  return 0; // nothing to do
26  } else if (count == 1) {
27  // In this case, we assume the same value is used at every level
28  return pp.query(query_string, query_var);
29  } else if (count >= maxlev + 1) {
30  // In this case, there may be more values than levels so we
31  // will just read the number of values we need and ignore the
32  // extra levels
33  return pp.query(query_string, query_var, lev);
34  } else {
35  // In this case, there is more than one value AND there
36  // are more levels than values; as an example, if max_level = 2
37  // but count = 2 so we have three levels but only two values --
38  // it is not clear how to interpret this so we abort
39  amrex::Error(
40  "For parmparse variable " + pp.prefixedName(query_string) +
41  ": if specified, specify once total or at least once for each level");
42  return 0; // avoid compiler warning
43  }
44 }
45 
46 template <typename T>
47 int
49  const amrex::ParmParse& pp,
50  const char* query_string,
51  T& query_var,
52  const int lev,
53  const int maxlev)
54 {
55  int count = pp.countval(query_string);
56  if (count == 0) {
57  return 0; // nothing to do
58  } else if (count == 1) {
59  // In this case, we assume the same value is used at every level
60  return pp.query_enum_case_insensitive(query_string, query_var);
61  } else if (count >= maxlev + 1) {
62  // In this case, there may be more values than levels so we
63  // will just read the number of values we need and ignore the
64  // extra levels
65  return pp.query_enum_case_insensitive(query_string, query_var, lev);
66  } else {
67  // In this case, there is more than one value AND there
68  // are more levels than values; as an example, if max_level = 2
69  // but count = 2 so we have three levels but only two values --
70  // it is not clear how to interpret this so we abort
71  amrex::Error(
72  "For parmparse variable " + pp.prefixedName(query_string) +
73  ": if specified, specify once total or at least once for each level");
74  return 0; // avoid compiler warning
75  }
76 }
77 
78 /**
79  * Container holding quantities related to turbulence parametrizations
80  */
81 struct TurbChoice
82 {
83 public:
84  void init_params (int lev, int max_level, std::string pp_prefix)
85  {
86  amrex::ParmParse pp(pp_prefix);
87 
88  // Which LES closure?
89  query_one_or_per_level(pp, "les_type", les_type, lev, max_level);
90 
91  // Handle 2-D Smag
92  if (les_type == LESType::Smagorinsky2D) {
93  les_type = LESType::Smagorinsky;
94  smag2d = true;
95  }
96 
97  // Which RANS closure?
98  query_one_or_per_level(pp, "rans_type", rans_type, lev, max_level);
99 
100  if ((rans_type != RANSType::None) && (les_type != LESType::None)) {
101  amrex::Error("Hybrid RANS-LES not implemented");
102  }
103 
104  // Which PBL Closure
105  query_one_or_per_level_enum_case_insensitive(pp, "pbl_type", pbl_type, lev, max_level);
106  if (pbl_type == PBLType::SHOC) {
107  static bool warned_legacy_shoc = false;
108  if (!warned_legacy_shoc) {
109  amrex::Warning("erf.pbl_type = SHOC is deprecated; use erf.pbl_type = EAMXX_SHOC");
110  warned_legacy_shoc = true;
111  }
112  pbl_type = PBLType::EAMXX_SHOC;
113  }
114 
115  // Do some more stuff for PBL Modeling
116  if (pbl_type != PBLType::None) {
117  // Check for compatibility between PBL, LES, Molec Transport
118  if (les_type != LESType::None) {
119  amrex::Print() << "Selected a PBL model and an LES model: "
120  << "Using PBL for vertical transport, LES for horizontal"
121  << std::endl;
122  }
123  if (les_type == LESType::Smagorinsky) {
124  if (!smag2d)
125  amrex::Error("If using Smagorinsky with a PBL model, the 2-D "
126  "formulation should be used");
127  } else if (les_type == LESType::Deardorff) {
128  amrex::Error(
129  "It is not recommended to use Deardorff LES and a PBL model");
130  }
131 
132  if (pbl_type == PBLType::MYNN25 || pbl_type == PBLType::MYNNEDMF) {
133  query_one_or_per_level(pp, "pbl_mynn_A1", pbl_mynn.A1, lev, max_level);
134  query_one_or_per_level(pp, "pbl_mynn_A2", pbl_mynn.A2, lev, max_level);
135  query_one_or_per_level(pp, "pbl_mynn_B1", pbl_mynn.B1, lev, max_level);
136  query_one_or_per_level(pp, "pbl_mynn_B2", pbl_mynn.B2, lev, max_level);
137  query_one_or_per_level(pp, "pbl_mynn_C1", pbl_mynn.C1, lev, max_level);
138  query_one_or_per_level(pp, "pbl_mynn_C2", pbl_mynn.C2, lev, max_level);
139  query_one_or_per_level(pp, "pbl_mynn_C3", pbl_mynn.C3, lev, max_level);
140  query_one_or_per_level(pp, "pbl_mynn_C4", pbl_mynn.C4, lev, max_level);
141  query_one_or_per_level(pp, "pbl_mynn_C5", pbl_mynn.C5, lev, max_level);
146  pp, "pbl_mynn_diffuse_moistvars", pbl_mynn.diffuse_moistvars, lev,
147  max_level);
149  pp, "pbl_mynn_SMmin", pbl_mynn.SMmin, lev, max_level);
151  pp, "pbl_mynn_SMmax", pbl_mynn.SMmax, lev, max_level);
153  pp, "pbl_mynn_SHmin", pbl_mynn.SHmin, lev, max_level);
155  pp, "pbl_mynn_SHmax", pbl_mynn.SHmax, lev, max_level);
157  pp, "pbl_mynn_SQfactor", pbl_mynn.SQfac, lev, max_level);
158  } else if (pbl_type == PBLType::YSU || pbl_type == PBLType::YSUNew) {
160  pp, "pbl_ysu_coriolis_freq", pbl_ysu_coriolis_freq, lev, max_level);
162  pp, "pbl_ysu_use_consistent_coriolis",
163  pbl_ysu_use_consistent_coriolis, lev, max_level);
165  pp, "pbl_ysu_force_over_water", pbl_ysu_force_over_water, lev,
166  max_level);
168  pp, "pbl_ysu_land_Ribcr", pbl_ysu_land_Ribcr, lev, max_level);
170  pp, "pbl_ysu_unst_Ribcr", pbl_ysu_unst_Ribcr, lev, max_level);
172  pp, "enable_ysu_liquid_theta", enable_ysu_liquid_theta, lev, max_level);
174  pp, "enable_ysu_countergradient", enable_ysu_countergradient, lev, max_level);
176  pp, "enable_ysu_terrain_pblh_floor", enable_ysu_terrain_pblh_floor, lev, max_level);
178  pp, "enable_ysu_sat_limiter", enable_ysu_sat_limiter, lev, max_level);
180  pp, "enable_ysu_topdown", enable_ysu_topdown, lev, max_level);
182  pp, "enable_ysu_entrainment", enable_ysu_entrainment, lev, max_level);
184  pp, "enable_ysu_cloud_pblh", enable_ysu_cloud_pblh, lev, max_level);
186  pp, "enable_mrf_unbounded_vpert", enable_mrf_unbounded_vpert, lev, max_level);
188  pp, "ysu_qcloud_threshold", ysu_qcloud_threshold, lev, max_level);
190  pp, "ysu_moistvars", ysu_moistvars, lev, max_level);
192  pp, "pbl_ysunew_highres_bounds", pbl_ysunew_highres_bounds, lev, max_level);
193  } else if (pbl_type == PBLType::MRF) {
195  pp, "pbl_mrf_coriolis_freq", pbl_mrf_coriolis_freq, lev, max_level);
197  pp, "pbl_mrf_Ribcr", pbl_mrf_Ribcr, lev, max_level);
199  pp, "pbl_mrf_const_b", pbl_mrf_const_b, lev, max_level);
200  query_one_or_per_level(pp, "pbl_mrf_sf", pbl_mrf_sf, lev, max_level);
202  pp, "mrf_moistvars", mrf_moistvars, lev, max_level);
204  pp, "enable_mrf_countergradient", enable_mrf_countergradient, lev, max_level);
206  pp, "enable_mrf_cloud_adjustment", enable_mrf_cloud_adjustment, lev, max_level);
208  pp, "pbl_mrf_highres_bounds", pbl_mrf_highres_bounds, lev, max_level);
210  pp, "enable_mrf_unbounded_vpert", enable_mrf_unbounded_vpert, lev, max_level);
212  pp, "pbl_mrf_use_zero_ri_extent", pbl_mrf_use_zero_ri_extent, lev, max_level);
213  } else if (pbl_type == PBLType::SHOC) {
214 #ifndef ERF_USE_SHOC
215  amrex::Abort("You set use_shoc to true but didn't build with SHOC; you must rebuild the executable");
216  }
217 #endif
218  if (uses_eamxx_shoc()) {
219 #ifndef ERF_USE_EAMXX_SHOC
220  amrex::Abort("PBLType::EAMXX_SHOC requested, but ERF was not built with ERF_ENABLE_EAMXX_SHOC=ON");
221 #endif
222  }
223 
225  std::string zlo_bc = "none";
226  amrex::ParmParse pp_bc("zlo");
227  pp_bc.get("type",zlo_bc);
228  if (amrex::toLower(zlo_bc) != "surface_layer") {
229  amrex::Abort("You must use the surface_layer BC at zlo with the selected PBL.");
230  }
231  }
232  }
233 
234  // Flags for QKE/TKE equation
235  if (pbl_type == PBLType::MYJ || pbl_type == PBLType::MYNN25 || pbl_type == PBLType::MYNNEDMF) {
236  // Add sources/sinks to QKE/TKE? (MYJ does this inline)
237  if (pbl_type == PBLType::MYNN25 || pbl_type == PBLType::MYNNEDMF) {
238  use_pbl_tke = true;
239  }
240  // Advect QKE/TKE?
241  query_one_or_per_level(pp, "advect_tke" , advect_tke , lev, max_level);
242  // Apply numerical diffusion to QKE/TKE?
243  query_one_or_per_level(pp, "diffuse_tke_3D", diffuse_tke_3D, lev, max_level);
244  }
245 
246  // There is a default value of 1e-6 but the user can override the value here,
247  // and in addition can add perturbational values. and in addition can add perturbational values.
248  pp.query("tke_min",tke_min);
249 
250  // LES constants...
251  query_one_or_per_level(pp, "Cs", Cs, lev, max_level);
252 
253  query_one_or_per_level(pp, "Pr_t", Pr_t, lev, max_level);
254  query_one_or_per_level(pp, "Sc_t", Sc_t, lev, max_level);
255 
256  // Compute relevant forms of diffusion parameters
257  Pr_t_inv = one / Pr_t;
258  Sc_t_inv = one / Sc_t;
259 
260  if (les_type == LESType::Deardorff) {
261  query_one_or_per_level(pp, "Ck", Ck, lev, max_level);
262  query_one_or_per_level(pp, "Ce", Ce, lev, max_level);
263  query_one_or_per_level(pp, "Ce_wall", Ce_wall, lev, max_level);
264  }
265 
266  // To quantify atmospheric stability for subgrid modeling
267  query_one_or_per_level(pp, "thermal_stratification", strat_type, lev, max_level);
268  if (strat_type == StratType::theta) {
269  amrex::Print() << "Thermal stratification based on gradient of potential temperature" << std::endl;
270  } else if (strat_type == StratType::thetav) {
271  amrex::Print() << "Thermal stratification based on gradient of virtual potential temperature" << std::endl;
272  } else if (strat_type == StratType::thetal) {
273  amrex::Print() << "Thermal stratification based on gradient of linearized liquid-water potential temperature" << std::endl;
274  }
275 
276  // k-eqn constants
277  query_one_or_per_level(pp, "Cmu0", Cmu0, lev, max_level);
278  query_one_or_per_level(pp, "Cb", Cb, lev, max_level);
279  query_one_or_per_level(pp, "Rt_crit", Rt_crit, lev, max_level);
280  query_one_or_per_level(pp, "Rt_min", Rt_min, lev, max_level);
281  query_one_or_per_level(pp, "max_geom_lscale", l_g_max, lev, max_level);
282  query_one_or_per_level(pp, "dirichlet_k", dirichlet_k, lev, max_level);
283 
284  // Common inputs (LES or RANS)
285  if (!query_one_or_per_level(pp, "sigma_k", sigma_k, lev, max_level) && rans_type == RANSType::kEqn) {
286  amrex::Print() << "Overriding default sigma_k for k-eqn RANS" << std::endl;
287  sigma_k = one;
288  };
289  query_one_or_per_level(pp, "theta_ref", theta_ref, lev, max_level);
290 
291  query_one_or_per_level(pp, "mix_isotropic", mix_isotropic, lev, max_level);
292  query_one_or_per_level(pp, "use_Ri_correction", use_Ri_correction, lev, max_level);
293  query_one_or_per_level(pp, "Ri_crit", Ri_crit, lev, max_level);
294 
295  // Set common flags
296  use_kturb =
297  ((les_type != LESType::None) || (rans_type != RANSType::None) ||
298  (pbl_type != PBLType::None));
299  use_keqn =
300  ((les_type == LESType::Deardorff) || (rans_type == RANSType::kEqn));
301  use_tke =
302  ((les_type == LESType::Deardorff) || (rans_type == RANSType::kEqn) ||
303  (pbl_type == PBLType::MYJ) || (pbl_type == PBLType::MYNN25) ||
304  (pbl_type == PBLType::MYNNEDMF) || uses_shoc_family());
305 
306  if (use_tke) {
307  query_one_or_per_level(pp, "init_tke_from_ustar", init_tke_from_ustar, lev, max_level);
308  }
309 
310  // Validate inputs
311  if (les_type == LESType::Smagorinsky) {
312  if (Cs == 0) {
313  amrex::Error("Need to specify Cs for Smagorsinky LES");
314  }
315  if (smag2d && mix_isotropic) {
316  amrex::Print() << "Turning off mix_isotropic for 2-D Smagorinsky" << std::endl;
317  mix_isotropic = false;
318  }
319  }
320  }
321 
322  void check_params (amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2>& phys_bc_type)
323  {
324  // BC compatibility
326  phys_bc_type[amrex::Orientation(amrex::Direction::z,amrex::Orientation::low)] != ERF_BC::surface_layer ) {
327  amrex::Abort("The selected PBL model requires MOST at lower boundary");
328  }
329  if ( (les_type == LESType::Deardorff) && (Ce_wall > 0) &&
330  (phys_bc_type[amrex::Orientation(amrex::Direction::z,amrex::Orientation::low)] != ERF_BC::surface_layer) &&
331  (phys_bc_type[amrex::Orientation(amrex::Direction::z,amrex::Orientation::low)] != ERF_BC::slip_wall) &&
332  (phys_bc_type[amrex::Orientation(amrex::Direction::z,amrex::Orientation::low)] != ERF_BC::no_slip_wall) )
333  {
334  amrex::Warning("Deardorff LES assumes wall at zlo when applying Ce_wall");
335  }
336  }
337 
338  void display (int lev)
339  {
340  amrex::Print() << "Turbulence Settings at level " << lev << std::endl;
341 
342  if (
343  les_type == LESType::None && rans_type == RANSType::None &&
344  pbl_type == PBLType::None) {
345  amrex::Print() << " Using DNS model at level " << lev << std::endl;
346  } else if (les_type == LESType::Smagorinsky) {
347  if (smag2d) {
348  amrex::Print() << " Using 2D Smagorinsky LES model at level " << lev << std::endl;
349  } else {
350  amrex::Print() << " Using Smagorinsky LES model at level " << lev << std::endl;
351  }
352  if (use_Ri_correction) {
353  amrex::Print() << " Smagorinsky uses Richardson number correction with Ri_crit = "
354  << Ri_crit << std::endl;
355  }
356  } else if (les_type == LESType::Deardorff) {
357  amrex::Print() << " Using Deardorff LES model at level " << lev << std::endl;
358  } else if (rans_type == RANSType::kEqn) {
359  amrex::Print()
360  << " Using Axell & Liungman one-equation RANS k model at level " << lev
361  << std::endl;
362  } else if (pbl_type == PBLType::MYJ) {
363  amrex::Print() << " Using MYJ PBL model at level " << lev << std::endl;
364  } else if (pbl_type == PBLType::MYNN25) {
365  amrex::Print() << " Using MYNN2.5 PBL model at level " << lev << std::endl;
366  } else if (pbl_type == PBLType::MYNNEDMF) {
367  amrex::Print() << " Using MYNNEDMF PBL model at level " << lev << std::endl;
368  } else if (pbl_type == PBLType::YSU) {
369  amrex::Print() << " Using YSU PBL model at level " << lev << std::endl;
370  } else if (pbl_type == PBLType::YSUNew) {
371  amrex::Print() << " Using YSU PBL model at level " << lev << std::endl;
372  } else if (pbl_type == PBLType::MRF) {
373  amrex::Print() << " Using MRF PBL model at level " << lev << std::endl;
374  } else if (pbl_type == PBLType::EAMXX_SHOC) {
375  amrex::Print() << " Using EAMxx SHOC PBL model at level " << lev << std::endl;
376  } else if (pbl_type == PBLType::NATIVE_SHOC) {
377  amrex::Print() << " Using native SHOC PBL model at level " << lev << std::endl;
378  } else {
379  amrex::Error("Unknown turbulence model");
380  }
381 
382  if (les_type != LESType::None) {
383  if (les_type == LESType::Smagorinsky) {
384  amrex::Print() << " Cs : " << Cs << std::endl;
385  }
386  if (les_type == LESType::Deardorff) {
387  amrex::Print() << " Ce : " << Ce << std::endl;
388  amrex::Print() << " Ce at wall : " << Ce_wall << std::endl;
389  amrex::Print() << " Ck : " << Ck << std::endl;
390  amrex::Print() << " sigma_k : " << sigma_k << std::endl;
391 
392  // Sullivan et al 1994, Eqn 14
393  amrex::Real Cs_equiv = std::sqrt(Ck * std::sqrt(Ck / Ce));
394  amrex::Print() << " equivalent Cs : " << Cs_equiv
395  << std::endl;
396  }
397  amrex::Print() << " isotropic mixing : " << mix_isotropic
398  << std::endl;
399  }
400 
401  if (rans_type != RANSType::None) {
402  if (rans_type == RANSType::kEqn) {
403  amrex::Print() << "Cmu0 : " << Cmu0 << std::endl;
404  amrex::Print() << "sigma_k : " << sigma_k << std::endl;
405  amrex::Print() << "Cb : " << Cb << std::endl;
406  amrex::Print() << "Rt_crit : " << Rt_crit << std::endl;
407  amrex::Print() << "Rt_min : " << Rt_min << std::endl;
408  amrex::Print() << "max_geom_lscale : " << l_g_max << std::endl;
409  }
410  }
411 
412  if ((les_type == LESType::Deardorff) ||
413  (rans_type == RANSType::kEqn)) {
414  if (theta_ref > 0) {
415  amrex::Print() << " reference theta : " << theta_ref << std::endl;
416  } else {
417  amrex::Print() << " reference theta : n/a" << std::endl;
418  }
419  }
420 
421  if ((les_type != LESType::None) || (rans_type != RANSType::None)) {
422  amrex::Print() << " Pr_t : " << Pr_t << std::endl;
423  amrex::Print() << " Sc_t : " << Sc_t << std::endl;
424  }
425 
426  if (pbl_type == PBLType::MYNN25 || pbl_type == PBLType::MYNNEDMF) {
427  amrex::Print() << " pbl_mynn_A1 : " << pbl_mynn.A1 << std::endl;
428  amrex::Print() << " pbl_mynn_A2 : " << pbl_mynn.A2 << std::endl;
429  amrex::Print() << " pbl_mynn_B1 : " << pbl_mynn.B1 << std::endl;
430  amrex::Print() << " pbl_mynn_B2 : " << pbl_mynn.B2 << std::endl;
431  amrex::Print() << " pbl_mynn_C1 : " << pbl_mynn.C1 << std::endl;
432  amrex::Print() << " pbl_mynn_C2 : " << pbl_mynn.C2 << std::endl;
433  amrex::Print() << " pbl_mynn_C3 : " << pbl_mynn.C3 << std::endl;
434  amrex::Print() << " pbl_mynn_C4 : " << pbl_mynn.C4 << std::endl;
435  amrex::Print() << " pbl_mynn_C5 : " << pbl_mynn.C5 << std::endl;
436  } else if (pbl_type == PBLType::YSU || pbl_type == PBLType::YSUNew) {
437  amrex::Print() << " pbl_ysu_coriolis_freq : "
438  << pbl_ysu_coriolis_freq << std::endl;
439  amrex::Print() << " pbl_ysu_use_consistent_coriolis : "
440  << pbl_ysu_use_consistent_coriolis << std::endl;
441  amrex::Print() << " pbl_ysu_force_over_water : "
442  << pbl_ysu_force_over_water << std::endl;
443  amrex::Print() << " pbl_ysu_land_Ribcr : "
444  << pbl_ysu_land_Ribcr << std::endl;
445  amrex::Print() << " pbl_ysu_unst_Ribcr : "
446  << pbl_ysu_unst_Ribcr << std::endl;
447  amrex::Print() << " enable_ysu_liquid_theta : "
448  << enable_ysu_liquid_theta << std::endl;
449  amrex::Print() << " enable_ysu_countergradient : "
450  << enable_ysu_countergradient << std::endl;
451  amrex::Print() << " enable_ysu_terrain_pblh_floor : "
452  << enable_ysu_terrain_pblh_floor << std::endl;
453  amrex::Print() << " enable_ysu_sat_limiter : "
454  << enable_ysu_sat_limiter << std::endl;
455  amrex::Print() << " enable_ysu_topdown : "
456  << enable_ysu_topdown << std::endl;
457  amrex::Print() << " enable_ysu_entrainment : "
458  << enable_ysu_entrainment << std::endl;
459  amrex::Print() << " enable_ysu_cloud_pblh : "
460  << enable_ysu_cloud_pblh << std::endl;
461  amrex::Print() << " ysu_qcloud_threshold : "
462  << ysu_qcloud_threshold << std::endl;
463  amrex::Print() << " ysu_moistvars : "
464  << ysu_moistvars << std::endl;
465  amrex::Print() << " pbl_ysunew_highres_bounds : "
466  << pbl_ysunew_highres_bounds << std::endl;
467  amrex::Print() << " enable_mrf_unbounded_vpert : "
468  << enable_mrf_unbounded_vpert << std::endl;
469  } else if (pbl_type == PBLType::MRF) {
470  amrex::Print() << " pbl_mrf_coriolis_freq : " << pbl_mrf_coriolis_freq
471  << std::endl;
472  amrex::Print() << " pbl_mrf_Ribcr : " << pbl_mrf_Ribcr
473  << std::endl;
474  amrex::Print() << " pbl_mrf_const_b : " << pbl_mrf_const_b
475  << std::endl;
476  amrex::Print() << " pbl_mrf_sf : " << pbl_mrf_sf
477  << std::endl;
478  amrex::Print() << " mrf_moistvars : " << mrf_moistvars
479  << std::endl;
480  amrex::Print() << " enable_mrf_countergradient : " << enable_mrf_countergradient
481  << std::endl;
482  amrex::Print() << " enable_mrf_cloud_adjustment : " << enable_mrf_cloud_adjustment
483  << std::endl;
484  amrex::Print() << " pbl_mrf_highres_bounds : " << pbl_mrf_highres_bounds
485  << std::endl;
486  amrex::Print() << " enable_mrf_unbounded_vpert : " << enable_mrf_unbounded_vpert
487  << std::endl;
488  amrex::Print() << " pbl_mrf_use_zero_ri_extent : " << pbl_mrf_use_zero_ri_extent
489  << std::endl;
490  }
491  }
492 
493  // LES model
494  LESType les_type = LESType::None;
495 
496  // Turbulent Prandtl number
499 
500  // Turbulent Schmidt number
503 
504  // Smagorinsky
506  bool smag2d = false;
507 
508  // Deardorff
510  amrex::Real Ce_wall = zero; // if > 0, then set Ce to this at k=0
512 
513  // k-eqn RANS coefficients (Axell & Liungman 2001)
518  amrex::Real l_g_max = amrex::Real(30.0); // ~ kappa * (amrex::Real(0.1) * zi)
519 
520  // Deardorff or k-eqn RANS
521  // - diffusivity of tke is 1/sigma_k times the eddy viscosity
523  // - reference potential temperature used to quantify the stratification in
524  // a stable region
526  // - how to quantify stratification effects
528 
529  // Anisotropic length scales
530  bool mix_isotropic = true;
531 
532  bool use_Ri_correction = true;
534 
535  // RANS type
536  RANSType rans_type = RANSType::None;
537 
538  bool dirichlet_k = false;
539 
540  // PBL model
541  PBLType pbl_type = PBLType::None;
542 
543  bool uses_eamxx_shoc () const noexcept
544  {
545  return pbl_type == PBLType::EAMXX_SHOC;
546  }
547 
548  bool uses_native_shoc () const noexcept
549  {
550  return pbl_type == PBLType::NATIVE_SHOC;
551  }
552 
553  bool uses_shoc_family () const noexcept
554  {
555  return uses_eamxx_shoc() || uses_native_shoc();
556  }
557 
558  bool pbl_requires_surface_layer () const noexcept
559  {
560  return (pbl_type == PBLType::MYNN25) ||
561  (pbl_type == PBLType::MYNNEDMF) ||
562  (pbl_type == PBLType::YSU) ||
563  (pbl_type == PBLType::YSUNew) ||
564  (pbl_type == PBLType::MRF) ||
566  }
567 
569  {
570  return uses_shoc_family();
571  }
572 
574  MYNNLevel2 pbl_mynn_level2; // limiting in the decaying turbulence regime
575 
576  // Common Flags
577  bool use_kturb = false; // Any turbulence modeling?
578  bool use_keqn =
579  false; // Any microscale turbulence modeling (LES, RANS) with TKE closure?
580  // Then need to populate SmnSmn_lev for production term.
581  bool use_pbl_tke =
582  false; // Any mesoscale turbulence modeling (PBL) with TKE closure?
583  bool use_tke = false; // Any TKE closure (meso or microscale)?
584 
585  // Initialize TKE/QKE with linear profiles whose surface values are a
586  // function of the friction velocity calculated by the surface layer scheme
587  // (e.g., as done in MYNN-EDMF)
588  bool init_tke_from_ustar = false;
589 
590  // This is the value of tke_min in WRF 4.5
592 
593  // Model coefficients - YSU
594  // TODO: Add parmparse for all of these above
596  amrex::Real(1.0e-4); // 1e-4 is hardcoded in WRF, we let the user specify or take the
597  // value from ERF coriolis forcing
599  false; // ignore input pbl_ysu_coriolis_freq, take value from ERF coriolis
600  // forcing instead
602  false; // Force YSU to act as if it is over water regardless of other inputs
603  // (for testing)
605  fourth; // Critical Bulk Richardson number of Land for stable conditions
607  zero; // Critical Bulk Richardson number for unstable conditions
609  true; // if true, use liquid-water virtual potential temperature in YSU stability
611  true; // if true, apply YSU-style HGAMT/HGAMQ/HGAMU/HGAMV countergradient correction
613  true; // if true, apply terrain-following floor on PBL height
615  false; // if true, apply saturation limiter to moisture countergradient
617  true; // if true, enable top-down mixing for cloud-topped boundary layers
619  true; // if true, enable entrainment layer parameterization
621  true; // if true, enable cloud-based PBL height detection
623  amrex::Real(1.0e-4); // Cloud liquid water threshold for YSUNew (kg/kg)
624  bool ysu_moistvars = false; // if true, adds turbulence to moisture
625  bool pbl_ysunew_highres_bounds = false; // if true, apply high-resolution grid-dependent diffusivity bounds
626  // Model coefficients - MRF
628  amrex::Real pbl_mrf_Ribcr = amrex::Real(0.5); // Critical Bulk Richardson number for MRF PBL model
629  amrex::Real pbl_mrf_const_b = amrex::Real(7.8); // Constant b in MRF PBL model, used to compute the PBL height
630  amrex::Real pbl_mrf_sf = amrex::Real(0.1); // MRF surface flux, used to compute the PBL height
631  bool mrf_moistvars = false; // if true, adds turbulence to moisture
632  bool enable_mrf_countergradient = false; // if true, apply WRF-style HGAMT/HGAMQ correction to PBL height
633  bool enable_mrf_cloud_adjustment = false; // if true, apply cloud-aware stability function adjustments in MRF scheme
634  bool pbl_mrf_highres_bounds = false; // if true, apply high-resolution grid-dependent diffusivity bounds instead of global forecast bounds
635  bool enable_mrf_unbounded_vpert = false; // if true, does not limit VPERT to GAMCRT
636  bool pbl_mrf_use_zero_ri_extent = false; // if true, use Ri=0 (pbli_zero_arr) for K-profile extent; default false uses Ri=0.5 corrector (pbli_arr) for WRF compatibility
637  // MYNN2.5 PBL model
638  // TKE/QKE stuff
639  bool advect_tke = true; // if MYNN2.5 PBL is used default is turb transport in
640  // Z-direction only
641  bool diffuse_tke_3D = true; // if numerical diffusion is turned on
642 };
643 #endif
constexpr amrex::Real three
Definition: ERF_Constants.H:11
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real fourth
Definition: ERF_Constants.H:14
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
@ no_slip_wall
@ surface_layer
ParmParse pp("prob")
Real T
Definition: ERF_InitCustomPert_Bubble.H:106
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_ENUM(LESType, None, Smagorinsky, Smagorinsky2D, Deardorff)
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)
Definition: ERF_TurbStruct.H:48
int query_one_or_per_level(const amrex::ParmParse &pp, const char *query_string, T &query_var, const int lev, const int maxlev)
Definition: ERF_TurbStruct.H:16
@ theta
Definition: ERF_MM5.H:20
Definition: ERF_MYNNStruct.H:11
amrex::Real SMmax
Definition: ERF_MYNNStruct.H:58
amrex::Real SHmax
Definition: ERF_MYNNStruct.H:60
amrex::Real SQfac
Definition: ERF_MYNNStruct.H:54
amrex::Real C4
Definition: ERF_MYNNStruct.H:50
amrex::Real C1
Definition: ERF_MYNNStruct.H:47
amrex::Real C3
Definition: ERF_MYNNStruct.H:49
amrex::Real C2
Definition: ERF_MYNNStruct.H:48
amrex::Real A2
Definition: ERF_MYNNStruct.H:44
amrex::Real SHmin
Definition: ERF_MYNNStruct.H:59
amrex::Real B1
Definition: ERF_MYNNStruct.H:45
amrex::Real B2
Definition: ERF_MYNNStruct.H:46
amrex::Real C5
Definition: ERF_MYNNStruct.H:51
amrex::Real SMmin
Definition: ERF_MYNNStruct.H:57
amrex::Real A1
Definition: ERF_MYNNStruct.H:43
bool diffuse_moistvars
Definition: ERF_MYNNStruct.H:65
Definition: ERF_MYNNStruct.H:68
void init_coeffs(amrex::Real A1_lvl25, amrex::Real A2_lvl25, amrex::Real B1, amrex::Real B2, amrex::Real C1, amrex::Real C2, amrex::Real C3, amrex::Real, amrex::Real C5)
Definition: ERF_MYNNStruct.H:69
Definition: ERF_TurbStruct.H:82
bool enable_ysu_countergradient
Definition: ERF_TurbStruct.H:610
amrex::Real tke_min
Definition: ERF_TurbStruct.H:591
bool smag2d
Definition: ERF_TurbStruct.H:506
amrex::Real sigma_k
Definition: ERF_TurbStruct.H:522
bool pbl_mrf_use_zero_ri_extent
Definition: ERF_TurbStruct.H:636
MYNNLevel25 pbl_mynn
Definition: ERF_TurbStruct.H:573
PBLType pbl_type
Definition: ERF_TurbStruct.H:541
amrex::Real pbl_mrf_const_b
Definition: ERF_TurbStruct.H:629
bool use_pbl_tke
Definition: ERF_TurbStruct.H:581
amrex::Real ysu_qcloud_threshold
Definition: ERF_TurbStruct.H:622
void check_params(amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 > &phys_bc_type)
Definition: ERF_TurbStruct.H:322
amrex::Real Sc_t_inv
Definition: ERF_TurbStruct.H:502
amrex::Real Rt_min
Definition: ERF_TurbStruct.H:517
bool use_keqn
Definition: ERF_TurbStruct.H:578
amrex::Real pbl_mrf_coriolis_freq
Definition: ERF_TurbStruct.H:627
bool pbl_ysunew_highres_bounds
Definition: ERF_TurbStruct.H:625
bool enable_ysu_topdown
Definition: ERF_TurbStruct.H:616
MYNNLevel2 pbl_mynn_level2
Definition: ERF_TurbStruct.H:574
amrex::Real Ri_crit
Definition: ERF_TurbStruct.H:533
RANSType rans_type
Definition: ERF_TurbStruct.H:536
StratType strat_type
Definition: ERF_TurbStruct.H:527
bool uses_eamxx_shoc() const noexcept
Definition: ERF_TurbStruct.H:543
bool enable_mrf_unbounded_vpert
Definition: ERF_TurbStruct.H:635
bool dirichlet_k
Definition: ERF_TurbStruct.H:538
amrex::Real pbl_mrf_Ribcr
Definition: ERF_TurbStruct.H:628
bool advect_tke
Definition: ERF_TurbStruct.H:639
amrex::Real Ck
Definition: ERF_TurbStruct.H:511
bool uses_shoc_family() const noexcept
Definition: ERF_TurbStruct.H:553
amrex::Real Cmu0
Definition: ERF_TurbStruct.H:514
bool pbl_ysu_use_consistent_coriolis
Definition: ERF_TurbStruct.H:598
bool uses_native_shoc() const noexcept
Definition: ERF_TurbStruct.H:548
amrex::Real Cb
Definition: ERF_TurbStruct.H:515
amrex::Real pbl_mrf_sf
Definition: ERF_TurbStruct.H:630
void init_params(int lev, int max_level, std::string pp_prefix)
Definition: ERF_TurbStruct.H:84
bool enable_mrf_countergradient
Definition: ERF_TurbStruct.H:632
bool use_Ri_correction
Definition: ERF_TurbStruct.H:532
bool enable_ysu_sat_limiter
Definition: ERF_TurbStruct.H:614
bool init_tke_from_ustar
Definition: ERF_TurbStruct.H:588
amrex::Real pbl_ysu_land_Ribcr
Definition: ERF_TurbStruct.H:604
bool mrf_moistvars
Definition: ERF_TurbStruct.H:631
bool use_tke
Definition: ERF_TurbStruct.H:583
bool diffuse_tke_3D
Definition: ERF_TurbStruct.H:641
bool enable_ysu_entrainment
Definition: ERF_TurbStruct.H:618
amrex::Real Cs
Definition: ERF_TurbStruct.H:505
amrex::Real Pr_t_inv
Definition: ERF_TurbStruct.H:498
bool pbl_suppresses_microphysics_condensation() const noexcept
Definition: ERF_TurbStruct.H:568
amrex::Real Ce_wall
Definition: ERF_TurbStruct.H:510
amrex::Real Ce
Definition: ERF_TurbStruct.H:509
bool enable_mrf_cloud_adjustment
Definition: ERF_TurbStruct.H:633
bool enable_ysu_cloud_pblh
Definition: ERF_TurbStruct.H:620
LESType les_type
Definition: ERF_TurbStruct.H:494
bool enable_ysu_terrain_pblh_floor
Definition: ERF_TurbStruct.H:612
amrex::Real pbl_ysu_coriolis_freq
Definition: ERF_TurbStruct.H:595
bool pbl_ysu_force_over_water
Definition: ERF_TurbStruct.H:601
bool enable_ysu_liquid_theta
Definition: ERF_TurbStruct.H:608
void display(int lev)
Definition: ERF_TurbStruct.H:338
bool pbl_mrf_highres_bounds
Definition: ERF_TurbStruct.H:634
amrex::Real Pr_t
Definition: ERF_TurbStruct.H:497
bool use_kturb
Definition: ERF_TurbStruct.H:577
amrex::Real theta_ref
Definition: ERF_TurbStruct.H:525
amrex::Real Sc_t
Definition: ERF_TurbStruct.H:501
amrex::Real Rt_crit
Definition: ERF_TurbStruct.H:516
bool ysu_moistvars
Definition: ERF_TurbStruct.H:624
amrex::Real pbl_ysu_unst_Ribcr
Definition: ERF_TurbStruct.H:606
bool mix_isotropic
Definition: ERF_TurbStruct.H:530
amrex::Real l_g_max
Definition: ERF_TurbStruct.H:518
bool pbl_requires_surface_layer() const noexcept
Definition: ERF_TurbStruct.H:558