ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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, MYNN25, MYNNEDMF, YSU);
11 
12 template <typename T>
13 void query_one_or_per_level(const amrex::ParmParse& pp, const char* query_string, T& query_var, const int lev, const int maxlev)
14 {
15  int count = pp.countval(query_string);
16  if (count == 0) {
17  return; // nothing to do
18  } else if (count == 1) {
19  pp.query(query_string, query_var);
20  } else if (count == maxlev + 1) {
21  pp.query(query_string, query_var, lev);
22  } else {
23  amrex::Error("For parmparse variable " + pp.prefixedName(query_string)
24  + ": if specified, specify once total or once for each level");
25  }
26 }
27 
28 /**
29  * Container holding quantities related to turbulence parametrizations
30  */
31 struct TurbChoice {
32  public:
33  void init_params(int lev, int max_level, std::string pp_prefix)
34  {
35  amrex::ParmParse pp(pp_prefix);
36 
37  // Which LES closure?
38  std::string les_type_string = "None";
39  query_one_or_per_level(pp, "les_type", les_type, lev, max_level);
40 
41  // Handle 2-D Smag
42  if (les_type == LESType::Smagorinsky2D) {
43  les_type = LESType::Smagorinsky;
44  smag2d = true;
45  }
46 
47  // Which RANS closure?
48  std::string rans_type_string = "None";
49  query_one_or_per_level(pp, "rans_type", rans_type, lev, max_level);
50 
51  if ((rans_type != RANSType::None) && (les_type != LESType::None)) {
52  amrex::Error("Hybrid RANS-LES not implemented");
53  }
54 
55  // Which PBL Closure
56  static std::string pbl_type_string = "None";
57  query_one_or_per_level(pp, "pbl_type", pbl_type, lev, max_level);
58 
59  // Do some more stuff for PBL Modeling
60  if (pbl_type != PBLType::None) {
61  // Check for compatibility between PBL, LES, Molec Transport
62  if (les_type != LESType::None) {
63  amrex::Print() << "Selected a PBL model and an LES model: " <<
64  "Using PBL for vertical transport, LES for horizontal" << std::endl;
65  }
66  if (les_type == LESType::Smagorinsky) {
67  if (!smag2d) amrex::Error("If using Smagorinsky with a PBL model, the 2-D formulation should be used");
68  } else if (les_type == LESType::Deardorff) {
69  amrex::Error("It is not recommended to use Deardorff LES and a PBL model");
70  }
71 
72  if (pbl_type == PBLType::MYNN25 || pbl_type == PBLType::MYNNEDMF) {
73  query_one_or_per_level(pp, "pbl_mynn_A1", pbl_mynn.A1, lev, max_level);
74  query_one_or_per_level(pp, "pbl_mynn_A2", pbl_mynn.A2, lev, max_level);
75  query_one_or_per_level(pp, "pbl_mynn_B1", pbl_mynn.B1, lev, max_level);
76  query_one_or_per_level(pp, "pbl_mynn_B2", pbl_mynn.B2, lev, max_level);
77  query_one_or_per_level(pp, "pbl_mynn_C1", pbl_mynn.C1, lev, max_level);
78  query_one_or_per_level(pp, "pbl_mynn_C2", pbl_mynn.C2, lev, max_level);
79  query_one_or_per_level(pp, "pbl_mynn_C3", pbl_mynn.C3, lev, max_level);
80  query_one_or_per_level(pp, "pbl_mynn_C4", pbl_mynn.C4, lev, max_level);
81  query_one_or_per_level(pp, "pbl_mynn_C5", pbl_mynn.C5, lev, max_level);
84  query_one_or_per_level(pp, "pbl_mynn_diffuse_moistvars", pbl_mynn.diffuse_moistvars, lev, max_level);
85  query_one_or_per_level(pp, "pbl_mynn_SMmin", pbl_mynn.SMmin, lev, max_level);
86  query_one_or_per_level(pp, "pbl_mynn_SMmax", pbl_mynn.SMmax, lev, max_level);
87  query_one_or_per_level(pp, "pbl_mynn_SHmin", pbl_mynn.SHmin, lev, max_level);
88  query_one_or_per_level(pp, "pbl_mynn_SHmax", pbl_mynn.SHmax, lev, max_level);
89  } else if (pbl_type == PBLType::YSU) {
90  query_one_or_per_level(pp, "pbl_ysu_coriolis_freq", pbl_ysu_coriolis_freq, lev, max_level);
91  query_one_or_per_level(pp, "pbl_ysu_use_consistent_coriolis", pbl_ysu_use_consistent_coriolis, lev, max_level);
92  query_one_or_per_level(pp, "pbl_ysu_force_over_water", pbl_ysu_force_over_water, lev, max_level);
93  query_one_or_per_level(pp, "pbl_ysu_land_Ribcr", pbl_ysu_land_Ribcr, lev, max_level);
94  query_one_or_per_level(pp, "pbl_ysu_unst_Ribcr", pbl_ysu_unst_Ribcr, lev, max_level);
95  }
96  }
97 
98  // Right now, solving the QKE equation is only supported when MYNN PBL is turned on
99  if (pbl_type == PBLType::MYNN25 || pbl_type == PBLType::MYNNEDMF) {
100  use_pbl_tke = true;
101  query_one_or_per_level(pp, "advect_tke" , advect_tke, lev, max_level);
102  query_one_or_per_level(pp, "diffuse_tke_3D", diffuse_tke_3D, lev, max_level);
103  }
104 
105  // LES constants...
106  query_one_or_per_level(pp, "Cs" ,Cs, lev, max_level);
107 
108  query_one_or_per_level(pp, "Pr_t",Pr_t, lev, max_level);
109  query_one_or_per_level(pp, "Sc_t",Sc_t, lev, max_level);
110 
111  // Compute relevant forms of diffusion parameters
112  Pr_t_inv = amrex::Real(1.0) / Pr_t;
113  Sc_t_inv = amrex::Real(1.0) / Sc_t;
114 
115  query_one_or_per_level(pp, "Ce" , Ce, lev, max_level);
116  query_one_or_per_level(pp, "Ce_wall" , Ce_wall, lev, max_level);
117 
118  if (les_type == LESType::Deardorff) {
119  query_one_or_per_level(pp, "Ck" , Ck, lev, max_level);
120  }
121 
122  // k-eqn constants
123  query_one_or_per_level(pp, "Cmu0" , Cmu0 , lev, max_level);
124  query_one_or_per_level(pp, "Cb" , Cb , lev, max_level);
125  query_one_or_per_level(pp, "Rt_crit" , Rt_crit, lev, max_level);
126  query_one_or_per_level(pp, "Rt_min" , Rt_min , lev, max_level);
127  query_one_or_per_level(pp, "max_geom_lscale", l_g_max, lev, max_level);
128 
129  // Common inputs (LES or RANS)
130  query_one_or_per_level(pp, "sigma_k" , sigma_k, lev, max_level);
131  query_one_or_per_level(pp, "theta_ref", theta_ref, lev, max_level);
132 
133  query_one_or_per_level(pp, "mix_isotropic", mix_isotropic, lev, max_level);
134 
135  // Set common flags
136  use_kturb = ( (les_type != LESType::None) ||
137  (rans_type != RANSType::None) ||
138  (pbl_type != PBLType::None) );
139  use_keqn = ( (les_type == LESType::Deardorff) ||
140  (rans_type == RANSType::kEqn) );
141  use_tke = ( (les_type == LESType::Deardorff) ||
142  (rans_type == RANSType::kEqn) ||
143  (pbl_type == PBLType::MYNN25) ||
144  (pbl_type == PBLType::MYNNEDMF) );
145 
146  // Validate inputs
147  if (les_type == LESType::Smagorinsky) {
148  if (Cs == 0) {
149  amrex::Error("Need to specify Cs for Smagorsinky LES");
150  }
151  if (smag2d && mix_isotropic) {
152  amrex::Print() << "Turning off mix_isotropic for 2-D Smagorinsky" << std::endl;
153  mix_isotropic = false;
154  }
155  }
156  }
157 
158  void display(int lev)
159  {
160  amrex::Print() << "Turbulence Settings at level " << lev << std::endl;
161 
162  if (les_type == LESType::None && rans_type == RANSType::None && pbl_type == PBLType::None) {
163  amrex::Print() << " Using DNS model at level " << lev << std::endl;
164  } else if (les_type == LESType::Smagorinsky) {
165  if (smag2d) {
166  amrex::Print() << " Using 2D Smagorinsky LES model at level " << lev << std::endl;
167  } else {
168  amrex::Print() << " Using Smagorinsky LES model at level " << lev << std::endl;
169  }
170  } else if (les_type == LESType::Deardorff) {
171  amrex::Print() << " Using Deardorff LES model at level " << lev << std::endl;
172  } else if (rans_type == RANSType::kEqn) {
173  amrex::Print() << " Using Axell & Liungman one-equation RANS k model at level " << lev << std::endl;
174  } else if (pbl_type == PBLType::MYNN25) {
175  amrex::Print() << " Using MYNN2.5 PBL model at level " << lev << std::endl;
176  } else if (pbl_type == PBLType::MYNNEDMF) {
177  amrex::Print() << " Using MYNNEDMF PBL model at level " << lev << std::endl;
178  } else if (pbl_type == PBLType::YSU) {
179  amrex::Print() << " Using YSU PBL model at level " << lev << std::endl;
180  }
181 
182  if (les_type != LESType::None) {
183  if (les_type == LESType::Smagorinsky) {
184  amrex::Print() << "Cs : " << Cs << std::endl;
185  }
186  if (les_type == LESType::Deardorff) {
187  amrex::Print() << "Ce : " << Ce << std::endl;
188  amrex::Print() << "Ce at wall : " << Ce_wall << std::endl;
189  amrex::Print() << "Ck : " << Ck << std::endl;
190  amrex::Print() << "sigma_k : " << sigma_k << std::endl;
191  amrex::Print() << "reference theta : " << theta_ref << std::endl;
192  // Sullivan et al 1994, Eqn 14
193  amrex::Real Cs_equiv = std::sqrt(Ck * std::sqrt(Ck/Ce));
194  amrex::Print() << "equivalent Cs : " << Cs_equiv << std::endl;
195  }
196  amrex::Print() << "isotropic mixing : " << mix_isotropic << std::endl;
197  }
198 
199  if (rans_type != RANSType::None) {
200  if (rans_type == RANSType::kEqn) {
201  amrex::Print() << "Cmu0 : " << Cmu0 << std::endl;
202  amrex::Print() << "sigma_k : " << sigma_k << std::endl;
203  amrex::Print() << "Cb : " << Cb << std::endl;
204  amrex::Print() << "Rt_crit : " << Rt_crit << std::endl;
205  amrex::Print() << "Rt_min : " << Rt_min << std::endl;
206  amrex::Print() << "max_geom_lscale : " << l_g_max << std::endl;
207  amrex::Print() << "reference theta : " << theta_ref << std::endl;
208  }
209  }
210 
211  if ((les_type != LESType::None) || (rans_type != RANSType::None)) {
212  amrex::Print() << "Pr_t : " << Pr_t << std::endl;
213  amrex::Print() << "Sc_t : " << Sc_t << std::endl;
214  }
215 
216  if (pbl_type == PBLType::MYNN25 || pbl_type == PBLType::MYNNEDMF) {
217  amrex::Print() << " pbl_mynn_A1 : " << pbl_mynn.A1 << std::endl;
218  amrex::Print() << " pbl_mynn_A2 : " << pbl_mynn.A2 << std::endl;
219  amrex::Print() << " pbl_mynn_B1 : " << pbl_mynn.B1 << std::endl;
220  amrex::Print() << " pbl_mynn_B2 : " << pbl_mynn.B2 << std::endl;
221  amrex::Print() << " pbl_mynn_C1 : " << pbl_mynn.C1 << std::endl;
222  amrex::Print() << " pbl_mynn_C2 : " << pbl_mynn.C2 << std::endl;
223  amrex::Print() << " pbl_mynn_C3 : " << pbl_mynn.C3 << std::endl;
224  amrex::Print() << " pbl_mynn_C4 : " << pbl_mynn.C4 << std::endl;
225  amrex::Print() << " pbl_mynn_C5 : " << pbl_mynn.C5 << std::endl;
226  } else if (pbl_type == PBLType::YSU) {
227  amrex::Print() << " pbl_ysu_coriolis_freq : " << pbl_ysu_coriolis_freq << std::endl;
228  amrex::Print() << " pbl_ysu_use_consistent_coriolis : " << pbl_ysu_use_consistent_coriolis << std::endl;
229  amrex::Print() << " pbl_ysu_force_over_water : " << pbl_ysu_force_over_water << std::endl;
230  amrex::Print() << " pbl_ysu_land_Ribcr : " << pbl_ysu_land_Ribcr << std::endl;
231  amrex::Print() << " pbl_ysu_unst_Ribcr : " << pbl_ysu_unst_Ribcr << std::endl;
232  }
233  }
234 
235  // LES model
236  LESType les_type;
237 
238  // Turbulent Prandtl number
239  amrex::Real Pr_t = amrex::Real(1.0) / amrex::Real(3.0);
240  amrex::Real Pr_t_inv = amrex::Real(3.0);
241 
242  // Turbulent Schmidt number
243  amrex::Real Sc_t = 1.0;
244  amrex::Real Sc_t_inv = 1.0;
245 
246  // Smagorinsky
247  amrex::Real Cs = 0.0;
248  bool smag2d = false;
249 
250  // Deardorff
251  amrex::Real Ce = 0.93;
252  amrex::Real Ce_wall = 0.0; // if > 0, then set Ce to this at k=0
253  amrex::Real Ck = 0.1;
254 
255  // k-eqn RANS coefficients (Axell & Liungman 2001)
256  amrex::Real Cmu0 = 0.5562;
257  amrex::Real Cb = 0.35;
258  amrex::Real Rt_crit = -1.0;
259  amrex::Real Rt_min = -3.0;
260  amrex::Real l_g_max = 1e99;
261 
262  // Deardorff or k-eqn RANS
263  // - diffusivity of tke is 1/sigma_k times the eddy viscosity
264  amrex::Real sigma_k = 0.5;
265  // - reference potential temperature used to quantify the stratification in
266  // a stable region
267  amrex::Real theta_ref = 300.0;
268 
269  // Anistropic length scales
270  bool mix_isotropic = true;
271 
272  // RANS type
273  RANSType rans_type;
274 
275  // PBL model
276  PBLType pbl_type;
277 
279  MYNNLevel2 pbl_mynn_level2; // for filtering
280 
281  // Common Flags
282  bool use_kturb = false; // Any turbulence modeling?
283  bool use_keqn = false; // Any microscale turbulence modeling (LES, RANS) with TKE closure? Then need to populate SmnSmn_lev for production term.
284  bool use_pbl_tke = false; // Any mesoscale turbulence modeling (PBL) with TKE closure?
285  bool use_tke = false; // Any TKE closure (meso or microscale)?
286 
287  // Model coefficients - YSU
288  // TODO: Add parmparse for all of these above
289  amrex::Real pbl_ysu_coriolis_freq = 1.0e-4; // 1e-4 is hardcoded in WRF, we let the user specify or tske the value from ERF coriolis forcing
290  bool pbl_ysu_use_consistent_coriolis = false; // ignore input pbl_ysu_coriolis_freq, take value from ERF coriolis forcing instead
291  bool pbl_ysu_force_over_water = false; // Force YSU to act as if it is over water regardless of other inputs (for testing)
292  amrex::Real pbl_ysu_land_Ribcr = 0.25; // Critical Bulk Richardson number of Land for stable conditions
293  amrex::Real pbl_ysu_unst_Ribcr = 0.0; // Critical Bulk Richardson number for unstable conditions
294 
295  // TKE/QKE stuff
296  bool advect_tke = true; // if MYNN2.5 PBL is used default is turb transport in Z-direction only
297  bool diffuse_tke_3D = true; // if numerical diffusion is turned on
298 };
299 #endif
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:219
AMREX_ENUM(LESType, None, Smagorinsky, Smagorinsky2D, Deardorff)
void 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:13
@ T
Definition: ERF_IndexDefines.H:110
Definition: ERF_MYNNStruct.H:9
amrex::Real SMmax
Definition: ERF_MYNNStruct.H:53
amrex::Real SHmax
Definition: ERF_MYNNStruct.H:55
amrex::Real C4
Definition: ERF_MYNNStruct.H:48
amrex::Real C1
Definition: ERF_MYNNStruct.H:45
amrex::Real C3
Definition: ERF_MYNNStruct.H:47
amrex::Real C2
Definition: ERF_MYNNStruct.H:46
amrex::Real A2
Definition: ERF_MYNNStruct.H:42
amrex::Real SHmin
Definition: ERF_MYNNStruct.H:54
amrex::Real B1
Definition: ERF_MYNNStruct.H:43
amrex::Real B2
Definition: ERF_MYNNStruct.H:44
amrex::Real C5
Definition: ERF_MYNNStruct.H:49
amrex::Real SMmin
Definition: ERF_MYNNStruct.H:52
amrex::Real A1
Definition: ERF_MYNNStruct.H:41
bool diffuse_moistvars
Definition: ERF_MYNNStruct.H:60
Definition: ERF_MYNNStruct.H:63
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:64
Definition: ERF_TurbStruct.H:31
bool smag2d
Definition: ERF_TurbStruct.H:248
amrex::Real sigma_k
Definition: ERF_TurbStruct.H:264
MYNNLevel25 pbl_mynn
Definition: ERF_TurbStruct.H:278
PBLType pbl_type
Definition: ERF_TurbStruct.H:276
bool use_pbl_tke
Definition: ERF_TurbStruct.H:284
amrex::Real Sc_t_inv
Definition: ERF_TurbStruct.H:244
amrex::Real Rt_min
Definition: ERF_TurbStruct.H:259
bool use_keqn
Definition: ERF_TurbStruct.H:283
MYNNLevel2 pbl_mynn_level2
Definition: ERF_TurbStruct.H:279
RANSType rans_type
Definition: ERF_TurbStruct.H:273
bool advect_tke
Definition: ERF_TurbStruct.H:296
amrex::Real Ck
Definition: ERF_TurbStruct.H:253
amrex::Real Cmu0
Definition: ERF_TurbStruct.H:256
bool pbl_ysu_use_consistent_coriolis
Definition: ERF_TurbStruct.H:290
amrex::Real Cb
Definition: ERF_TurbStruct.H:257
void init_params(int lev, int max_level, std::string pp_prefix)
Definition: ERF_TurbStruct.H:33
amrex::Real pbl_ysu_land_Ribcr
Definition: ERF_TurbStruct.H:292
bool use_tke
Definition: ERF_TurbStruct.H:285
bool diffuse_tke_3D
Definition: ERF_TurbStruct.H:297
amrex::Real Cs
Definition: ERF_TurbStruct.H:247
amrex::Real Pr_t_inv
Definition: ERF_TurbStruct.H:240
amrex::Real Ce_wall
Definition: ERF_TurbStruct.H:252
amrex::Real Ce
Definition: ERF_TurbStruct.H:251
LESType les_type
Definition: ERF_TurbStruct.H:236
amrex::Real pbl_ysu_coriolis_freq
Definition: ERF_TurbStruct.H:289
bool pbl_ysu_force_over_water
Definition: ERF_TurbStruct.H:291
void display(int lev)
Definition: ERF_TurbStruct.H:158
amrex::Real Pr_t
Definition: ERF_TurbStruct.H:239
bool use_kturb
Definition: ERF_TurbStruct.H:282
amrex::Real theta_ref
Definition: ERF_TurbStruct.H:267
amrex::Real Sc_t
Definition: ERF_TurbStruct.H:243
amrex::Real Rt_crit
Definition: ERF_TurbStruct.H:258
amrex::Real pbl_ysu_unst_Ribcr
Definition: ERF_TurbStruct.H:293
bool mix_isotropic
Definition: ERF_TurbStruct.H:270
amrex::Real l_g_max
Definition: ERF_TurbStruct.H:260