ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_AdvStruct.H
Go to the documentation of this file.
1 #ifndef ERF_ADV_STRUCT_H_
2 #define ERF_ADV_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 
15 /**
16  * Container holding the advection-related choices
17  */
18 
19 struct AdvChoice {
20  public:
21  void init_params(std::string pp_prefix)
22  {
23  amrex::ParmParse pp(pp_prefix);
24 
25  // Order and type of spatial discretizations used in advection
26  pp.query("use_efficient_advection", use_efficient_advection);
27  std::string dycore_horiz_adv_string = "" ; std::string dycore_vert_adv_string = "";
28  std::string dryscal_horiz_adv_string = "" ; std::string dryscal_vert_adv_string = "";
29  pp.query("dycore_horiz_adv_type" , dycore_horiz_adv_string);
30  pp.query("dycore_vert_adv_type" , dycore_vert_adv_string);
31  pp.query("dryscal_horiz_adv_type" , dryscal_horiz_adv_string);
32  pp.query("dryscal_vert_adv_type" , dryscal_vert_adv_string);
33 
34  std::string moistscal_horiz_adv_string = ""; std::string moistscal_vert_adv_string = "";
35  pp.query("moistscal_horiz_adv_type", moistscal_horiz_adv_string);
36  pp.query("moistscal_vert_adv_type" , moistscal_vert_adv_string);
37 
39  amrex::Print() << "Using efficient advection scheme" << std::endl;
40  }
41 
42  if ( (dycore_horiz_adv_string == "Blended_3rd4th") ||
43  (dycore_horiz_adv_string == "Blended_5th6th") )
44  {
45  pp.query("dycore_horiz_upw_frac" , dycore_horiz_upw_frac);
46  AMREX_ASSERT_WITH_MESSAGE((dycore_horiz_upw_frac >= 0.) && (dycore_horiz_upw_frac <= 1.),
47  "The dycore horizontal upwinding fraction must be between 0 and 1");
48  }
49 
50  if ( (dycore_vert_adv_string == "Blended_3rd4th") ||
51  (dycore_vert_adv_string == "Blended_5th6th") )
52  {
53  pp.query("dycore_vert_upw_frac" , dycore_vert_upw_frac);
54  AMREX_ASSERT_WITH_MESSAGE((dycore_vert_upw_frac >= 0.) && (dycore_vert_upw_frac <= 1.),
55  "The dycore vertical upwinding fraction must be between 0 and 1");
56  }
57 
58  if ( (dryscal_horiz_adv_string == "Blended_3rd4th") ||
59  (dryscal_horiz_adv_string == "Blended_5th6th") )
60  {
61  pp.query("dryscal_horiz_upw_frac" , dryscal_horiz_upw_frac);
62  AMREX_ASSERT_WITH_MESSAGE((dryscal_horiz_upw_frac >= 0.) && (dryscal_horiz_upw_frac <= 1.),
63  "The dry scalar horizontal upwinding fraction must be between 0 and 1");
64  }
65 
66  if ( (dryscal_vert_adv_string == "Blended_3rd4th") ||
67  (dryscal_vert_adv_string == "Blended_5th6th") )
68  {
69  pp.query("dryscal_vert_upw_frac" , dryscal_vert_upw_frac);
70  AMREX_ASSERT_WITH_MESSAGE((dryscal_vert_upw_frac >= 0.) && (dryscal_vert_upw_frac <= 1.),
71  "The dry scalar vertical upwinding fraction must be between 0 and 1");
72  }
73 
74  if ( (moistscal_horiz_adv_string == "Blended_3rd4th") ||
75  (moistscal_horiz_adv_string == "Blended_5th6th") )
76  {
77  pp.query("moistscal_horiz_upw_frac" , moistscal_horiz_upw_frac);
78  AMREX_ASSERT_WITH_MESSAGE((moistscal_horiz_upw_frac >= 0.) && (moistscal_horiz_upw_frac <= 1.),
79  "The moist scalar horizontal upwinding fraction must be between 0 and 1");
80  }
81 
82  if ( (moistscal_vert_adv_string == "Blended_3rd4th") ||
83  (moistscal_vert_adv_string == "Blended_5th6th") )
84  {
85  pp.query("moistscal_vert_upw_frac" , moistscal_vert_upw_frac);
86  AMREX_ASSERT_WITH_MESSAGE((moistscal_vert_upw_frac >= 0.) && (moistscal_vert_upw_frac <= 1.),
87  "The moist scalar vertical upwinding fraction must be between 0 and 1");
88  }
89 
90  if (dycore_horiz_adv_string != "") {
91  if ( (dycore_horiz_adv_string == "Centered_2nd") ||
92  (dycore_horiz_adv_string == "Upwind_3rd" ) ||
93  (dycore_horiz_adv_string == "Blended_3rd4th") ||
94  (dycore_horiz_adv_string == "Centered_4th") ||
95  (dycore_horiz_adv_string == "Upwind_5th" ) ||
96  (dycore_horiz_adv_string == "Blended_5th6th") ||
97  (dycore_horiz_adv_string == "Centered_6th") ||
98  (dycore_horiz_adv_string == "WENO3" ) ||
99  (dycore_horiz_adv_string == "WENOZ3" ) ||
100  (dycore_horiz_adv_string == "WENO5" ) ||
101  (dycore_horiz_adv_string == "WENOZ5" ) ||
102  (dycore_horiz_adv_string == "WENO7" ) ||
103  (dycore_horiz_adv_string == "WENOZ7" ))
104  {
106  } else {
107  amrex::Error("Don't know this dycore_horiz_adv_string");
108  }
109  }
110 
111  if (dycore_vert_adv_string != "") {
112  if ( (dycore_vert_adv_string == "Centered_2nd") ||
113  (dycore_vert_adv_string == "Upwind_3rd" ) ||
114  (dycore_vert_adv_string == "Blended_3rd4th") ||
115  (dycore_vert_adv_string == "Centered_4th") ||
116  (dycore_vert_adv_string == "Upwind_5th" ) ||
117  (dycore_vert_adv_string == "Blended_5th6th") ||
118  (dycore_vert_adv_string == "Centered_6th") ||
119  (dycore_vert_adv_string == "WENO3" ) ||
120  (dycore_vert_adv_string == "WENOZ3" ) ||
121  (dycore_vert_adv_string == "WENO5" ) ||
122  (dycore_vert_adv_string == "WENOZ5" ) ||
123  (dycore_vert_adv_string == "WENO7" ) ||
124  (dycore_vert_adv_string == "WENOZ7" ))
125  {
127  } else {
128  amrex::Error("Don't know this dycore_vert_adv_string");
129  }
130  }
131 
132  if (dryscal_horiz_adv_string != "") {
133  if ( (dryscal_horiz_adv_string == "Centered_2nd") ||
134  (dryscal_horiz_adv_string == "Upwind_3rd" ) ||
135  (dryscal_horiz_adv_string == "Upwind_3rd_SL") ||
136  (dryscal_horiz_adv_string == "Blended_3rd4th") ||
137  (dryscal_horiz_adv_string == "Centered_4th") ||
138  (dryscal_horiz_adv_string == "Upwind_5th" ) ||
139  (dryscal_horiz_adv_string == "Blended_5th6th") ||
140  (dryscal_horiz_adv_string == "Centered_6th") ||
141  (dryscal_horiz_adv_string == "WENO3" ) ||
142  (dryscal_horiz_adv_string == "WENOZ3" ) ||
143  (dryscal_horiz_adv_string == "WENOMZQ3" ) ||
144  (dryscal_horiz_adv_string == "WENO5" ) ||
145  (dryscal_horiz_adv_string == "WENOZ5" ) ||
146  (dryscal_horiz_adv_string == "WENO7" ) ||
147  (dryscal_horiz_adv_string == "WENOZ7" ) )
148  {
150  } else {
151  amrex::Error("Don't know this dryscal_horiz_adv_string");
152  }
153  }
154 
155  if (dryscal_vert_adv_string != "") {
156  if ( (dryscal_vert_adv_string == "Centered_2nd") ||
157  (dryscal_vert_adv_string == "Upwind_3rd" ) ||
158  (dryscal_vert_adv_string == "Upwind_3rd_SL") ||
159  (dryscal_vert_adv_string == "Blended_3rd4th") ||
160  (dryscal_vert_adv_string == "Centered_4th") ||
161  (dryscal_vert_adv_string == "Upwind_5th" ) ||
162  (dryscal_vert_adv_string == "Blended_5th6th") ||
163  (dryscal_vert_adv_string == "Centered_6th") ||
164  (dryscal_vert_adv_string == "WENO3" ) ||
165  (dryscal_vert_adv_string == "WENOZ3" ) ||
166  (dryscal_vert_adv_string == "WENOMZQ3" ) ||
167  (dryscal_vert_adv_string == "WENO5" ) ||
168  (dryscal_vert_adv_string == "WENOZ5" ) ||
169  (dryscal_vert_adv_string == "WENO7" ) ||
170  (dryscal_vert_adv_string == "WENOZ7" ))
171  {
173  } else {
174  amrex::Error("Don't know this dryscal_vert_adv_string");
175  }
176  }
177 
178  if (moistscal_horiz_adv_string != "") {
179  if ( (moistscal_horiz_adv_string == "Centered_2nd") ||
180  (moistscal_horiz_adv_string == "Upwind_3rd" ) ||
181  (moistscal_horiz_adv_string == "Upwind_3rd_SL" ) ||
182  (moistscal_horiz_adv_string == "Blended_3rd4th") ||
183  (moistscal_horiz_adv_string == "Centered_4th") ||
184  (moistscal_horiz_adv_string == "Upwind_5th" ) ||
185  (moistscal_horiz_adv_string == "Blended_5th6th") ||
186  (moistscal_horiz_adv_string == "Centered_6th") ||
187  (moistscal_horiz_adv_string == "WENO3" ) ||
188  (moistscal_horiz_adv_string == "WENOZ3" ) ||
189  (moistscal_horiz_adv_string == "WENOMZQ3" ) ||
190  (moistscal_horiz_adv_string == "WENO5" ) ||
191  (moistscal_horiz_adv_string == "WENOZ5" ) ||
192  (moistscal_horiz_adv_string == "WENO7" ) ||
193  (moistscal_horiz_adv_string == "WENOZ7" ))
194  {
195  moistscal_horiz_adv_type = adv_type_convert_string_to_advtype(moistscal_horiz_adv_string);
196  } else {
197  amrex::Error("Don't know this moistscal_horiz_adv_string");
198  }
199  }
200 
201  if (moistscal_vert_adv_string != "") {
202  if ( (moistscal_vert_adv_string == "Centered_2nd") ||
203  (moistscal_vert_adv_string == "Upwind_3rd" ) ||
204  (moistscal_vert_adv_string == "Upwind_3rd_SL" ) ||
205  (moistscal_vert_adv_string == "Blended_3rd4th") ||
206  (moistscal_vert_adv_string == "Centered_4th") ||
207  (moistscal_vert_adv_string == "Upwind_5th" ) ||
208  (moistscal_vert_adv_string == "Blended_5th6th") ||
209  (moistscal_vert_adv_string == "Centered_6th") ||
210  (moistscal_vert_adv_string == "WENO3" ) ||
211  (moistscal_vert_adv_string == "WENOZ3" ) ||
212  (moistscal_vert_adv_string == "WENOMZQ3" ) ||
213  (moistscal_vert_adv_string == "WENO5" ) ||
214  (moistscal_vert_adv_string == "WENOZ5" ) ||
215  (moistscal_vert_adv_string == "WENO7" ) ||
216  (moistscal_vert_adv_string == "WENOZ7" ))
217  {
218  moistscal_vert_adv_type = adv_type_convert_string_to_advtype(moistscal_vert_adv_string);
219  } else {
220  amrex::Error("Don't know this moistscal_vert_adv_string");
221  }
222  }
223 
224  // We can can't use weno with Embedded Boundaries (for now)
225  std::string terrain_type;
226  pp.query("terrain_type", terrain_type);
227  validate_weno_momentum_compatibility(terrain_type == "EB");
228 
229  pp.queryarr("zero_xflux_faces", zero_xflux);
230  pp.queryarr("zero_yflux_faces", zero_yflux);
231  pp.queryarr("zero_zflux_faces", zero_zflux);
232  have_zero_flux_faces = ((zero_xflux.size() > 0) || (zero_yflux.size() > 0) || (zero_zflux.size() > 0));
233  }
234 
235  void display(std::string& pp_prefix)
236  {
237  amrex::Print() << "Advection Choices: " << std::endl;
238 
239  // We read these again here just as a convenience to avoid passing them
240  amrex::ParmParse pp(pp_prefix);
241  std::string dycore_horiz_adv_string = "" ; std::string dycore_vert_adv_string = "";
242  std::string dryscal_horiz_adv_string = "" ; std::string dryscal_vert_adv_string = "";
243  pp.query("dycore_horiz_adv_type" , dycore_horiz_adv_string);
244  pp.query("dycore_vert_adv_type" , dycore_vert_adv_string);
245  pp.query("dryscal_horiz_adv_type" , dryscal_horiz_adv_string);
246  pp.query("dryscal_vert_adv_type" , dryscal_vert_adv_string);
247  std::string moistscal_horiz_adv_string = ""; std::string moistscal_vert_adv_string = "";
248  pp.query("moistscal_horiz_adv_type", moistscal_horiz_adv_string);
249  pp.query("moistscal_vert_adv_type" , moistscal_vert_adv_string);
250 
251  if (dycore_horiz_adv_string != "") {
252  amrex::Print() << " dycore_horiz_adv_type : " << dycore_horiz_adv_string;
253  } else {
254  amrex::Print() << " dycore_horiz_adv_type : " << adv_type_convert_int_to_string(dycore_horiz_adv_type);
255  }
256  if ( (dycore_horiz_adv_string == "Blended_3rd4th") ||
257  (dycore_horiz_adv_string == "Blended_5th6th") ) {
258  amrex::Print() << " with " << 100*dycore_horiz_upw_frac << "% upwinding";
259  }
260  amrex::Print() << std::endl;
261 
262  if (dycore_vert_adv_string != "") {
263  amrex::Print() << " dycore_vert_adv_type : " << dycore_vert_adv_string;
264  } else {
265  amrex::Print() << " dycore_vert_adv_type : " << adv_type_convert_int_to_string(dycore_vert_adv_type);
266  }
267  if ( (dycore_vert_adv_string == "Blended_3rd4th") ||
268  (dycore_vert_adv_string == "Blended_5th6th") ) {
269  amrex::Print() << " with " << 100*dycore_vert_upw_frac << "% upwinding";
270  }
271  amrex::Print() << std::endl;
272 
273  if (dryscal_horiz_adv_string != "") {
274  amrex::Print() << " dryscal_horiz_adv_type : " << dryscal_horiz_adv_string;
275  } else {
276  amrex::Print() << " dryscal_horiz_adv_type : " << adv_type_convert_int_to_string(dryscal_horiz_adv_type);
277  }
278  if ( (dryscal_horiz_adv_string == "Blended_3rd4th") ||
279  (dryscal_horiz_adv_string == "Blended_5th6th") ) {
280  amrex::Print() << " with " << 100*dryscal_horiz_upw_frac << "% upwinding";
281  }
282  amrex::Print() << std::endl;
283 
284  if (dryscal_vert_adv_string != "") {
285  amrex::Print() << " dryscal_vert_adv_type : " << dryscal_vert_adv_string;
286  } else {
287  amrex::Print() << " dryscal_vert_adv_type : " << adv_type_convert_int_to_string(dryscal_vert_adv_type);
288  }
289  if ( (dryscal_vert_adv_string == "Blended_3rd4th") ||
290  (dryscal_vert_adv_string == "Blended_5th6th") ) {
291  amrex::Print() << " with " << 100*dryscal_vert_upw_frac << "% upwinding";
292  }
293  amrex::Print() << std::endl;
294 
295  if (moistscal_horiz_adv_string != "") {
296  amrex::Print() << " moistscal_horiz_adv_type : " << moistscal_horiz_adv_string;
297  } else {
298  amrex::Print() << " moistscal_horiz_adv_type : " << adv_type_convert_int_to_string(moistscal_horiz_adv_type);
299  }
300  if ( (moistscal_horiz_adv_string == "Blended_3rd4th") ||
301  (moistscal_horiz_adv_string == "Blended_5th6th") ) {
302  amrex::Print() << " with " << 100*moistscal_horiz_upw_frac << "% upwinding";
303  }
304  amrex::Print() << std::endl;
305 
306  if (moistscal_vert_adv_string != "") {
307  amrex::Print() << " moistscal_vert_adv_type : " << moistscal_vert_adv_string;
308  } else {
309  amrex::Print() << " moistscal_vert_adv_type : " << adv_type_convert_int_to_string(moistscal_vert_adv_type);
310  }
311  if ( (moistscal_vert_adv_string == "Blended_3rd4th") ||
312  (moistscal_vert_adv_string == "Blended_5th6th") ) {
313  amrex::Print() << " with " << 100*moistscal_vert_upw_frac << "% upwinding";
314  }
315  amrex::Print() << std::endl;
316  }
317 
318  std::string
320  {
321  if (adv_int == AdvType::Centered_2nd) {
322  return "Centered_2nd";
323  } else if (adv_int == AdvType::Upwind_3rd) {
324  return "Upwind_3rd";
325  } else if (adv_int == AdvType::Upwind_3rd_SL) {
326  return "Upwind_3rd_SL";
327  } else if (adv_int == AdvType::Centered_4th) {
328  return "Centered_4th";
329  } else if (adv_int == AdvType::Upwind_5th) {
330  return "Upwind_5th";
331  } else if (adv_int == AdvType::Centered_6th) {
332  return "Centered_6th";
333  } else if (adv_int == AdvType::Weno_3) {
334  return "WENO3";
335  } else if (adv_int == AdvType::Weno_3Z) {
336  return "WENOZ3";
337  } else if (adv_int == AdvType::Weno_5) {
338  return "WENO5";
339  } else if (adv_int == AdvType::Weno_5Z) {
340  return "WENOZ5";
341  } else if (adv_int == AdvType::Weno_3MZQ) {
342  return "WENOMZQ3";
343  } else if (adv_int == AdvType::Weno_7) {
344  return "WENO7";
345  } else if (adv_int == AdvType::Weno_7Z) {
346  return "WENOZ7";
347  } else {
348  return "Unknown";
349  }
350  }
351 
353  {
354  if (adv_string == "Centered_2nd") {
355  return AdvType::Centered_2nd;
356  } else if ((adv_string == "Upwind_3rd") || (adv_string == "Blended_3rd4th")) {
357  return AdvType::Upwind_3rd;
358  } else if (adv_string == "Upwind_3rd_SL") {
359  return AdvType::Upwind_3rd_SL;
360  } else if (adv_string == "Centered_4th") {
361  return AdvType::Centered_4th;
362  } else if (adv_string == "Upwind_5th" || (adv_string == "Blended_5th6th")) {
363  return AdvType::Upwind_5th;
364  } else if (adv_string == "Centered_6th") {
365  return AdvType::Centered_6th;
366  } else if (adv_string == "WENO3") {
367  return AdvType::Weno_3;
368  } else if (adv_string == "WENOZ3") {
369  return AdvType::Weno_3Z;
370  } else if (adv_string == "WENO5") {
371  return AdvType::Weno_5;
372  } else if (adv_string == "WENOZ5") {
373  return AdvType::Weno_5Z;
374  } else if (adv_string == "WENOMZQ3") {
375  return AdvType::Weno_3MZQ;
376  } else if (adv_string == "WENO7") {
377  return AdvType::Weno_7;
378  } else if (adv_string == "WENOZ7") {
379  return AdvType::Weno_7Z;
380  } else {
381  return AdvType::Unknown;
382  }
383  }
384 
385  void validate_weno_momentum_compatibility(bool use_embedded_boundary)
386  {
387  // Check if any WENO momentum advection is being used
388  bool using_weno_momentum =
403 
404  // Check embedded boundary incompatibility
405  amrex::ignore_unused(use_embedded_boundary, using_weno_momentum);
406  AMREX_ASSERT_WITH_MESSAGE(!using_weno_momentum || !use_embedded_boundary,
407  "WENO momentum advection schemes are not yet implemented for embedded boundaries. "
408  "Please use traditional momentum advection schemes when using embedded boundaries:\n"
409  " - Centered_2nd\n"
410  " - Upwind_3rd\n"
411  " - Centered_4th\n"
412  " - Upwind_5th\n"
413  " - Centered_6th");
414  }
415 
416  // Order and type of spatial discretizations used in advection
417  // Defaults given below but these can be over-written at run-time
425 
426  // Blending between upwind and the next-highest order central scheme
427  // Note: This is used by both Upwind_* and Blended_* schemes -- the default
428  // is a pure upwind scheme
435 
436  // Thin immersed bodies
437  amrex::Vector<amrex::IntVect> zero_xflux;
438  amrex::Vector<amrex::IntVect> zero_yflux;
439  amrex::Vector<amrex::IntVect> zero_zflux;
440  bool have_zero_flux_faces = false;
441 };
442 #endif
AdvType
Definition: ERF_IndexDefines.H:221
@ Upwind_3rd_SL
@ Centered_4th
@ Centered_6th
@ Centered_2nd
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:233
amrex::Real Real
Definition: ERF_ShocInterface.H:19
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
amrex::Vector< amrex::IntVect > zero_yflux
Definition: ERF_AdvStruct.H:438
void validate_weno_momentum_compatibility(bool use_embedded_boundary)
Definition: ERF_AdvStruct.H:385
AdvType adv_type_convert_string_to_advtype(std::string adv_string)
Definition: ERF_AdvStruct.H:352
amrex::Real dryscal_vert_upw_frac
Definition: ERF_AdvStruct.H:432
AdvType moistscal_horiz_adv_type
Definition: ERF_AdvStruct.H:423
AdvType dycore_vert_adv_type
Definition: ERF_AdvStruct.H:420
AdvType moistscal_vert_adv_type
Definition: ERF_AdvStruct.H:424
amrex::Real moistscal_vert_upw_frac
Definition: ERF_AdvStruct.H:434
amrex::Real dycore_vert_upw_frac
Definition: ERF_AdvStruct.H:430
bool use_efficient_advection
Definition: ERF_AdvStruct.H:418
amrex::Real moistscal_horiz_upw_frac
Definition: ERF_AdvStruct.H:433
AdvType dryscal_horiz_adv_type
Definition: ERF_AdvStruct.H:421
amrex::Vector< amrex::IntVect > zero_xflux
Definition: ERF_AdvStruct.H:437
amrex::Vector< amrex::IntVect > zero_zflux
Definition: ERF_AdvStruct.H:439
AdvType dycore_horiz_adv_type
Definition: ERF_AdvStruct.H:419
bool have_zero_flux_faces
Definition: ERF_AdvStruct.H:440
amrex::Real dycore_horiz_upw_frac
Definition: ERF_AdvStruct.H:429
std::string adv_type_convert_int_to_string(AdvType adv_int)
Definition: ERF_AdvStruct.H:319
AdvType dryscal_vert_adv_type
Definition: ERF_AdvStruct.H:422
amrex::Real dryscal_horiz_upw_frac
Definition: ERF_AdvStruct.H:431