ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_WallScalarBC.H
Go to the documentation of this file.
1 #ifndef ERF_WALL_SCALAR_BC_H_
2 #define ERF_WALL_SCALAR_BC_H_
3 
4 #include <AMReX_REAL.H>
5 #include <AMReX_ParmParse.H>
6 
7 #include <string>
8 
9 namespace erf_wall_scalar_bc {
10 
11 // Host-side intent for a scalar supplied on one physical solid-wall face.
12 // Presence is represented by this value, never by the numerical value itself.
13 enum class WallScalarBCIntent : unsigned char {
17  Neumann
18 };
19 
20 enum class SolidWallKind : unsigned char {
21  NoSlip,
22  Slip
23 };
24 
28 };
29 
34 };
35 
38  std::string error;
39 
40  /**
41  * Return whether parsing completed without an error.
42  */
43  [[nodiscard]] bool ok () const noexcept { return error.empty(); }
44 };
45 
46 /**
47  * Resolve a wall scalar value into primitive or conserved storage.
48  *
49  * @param[in] value_specified whether the scalar value was specified
50  * @param[in] primitive_value primitive scalar value from inputs
51  * @param[in] density_specified_on_same_face whether density was specified on the same face
52  * @param[in] density_value density value used for conserved conversion
53  */
54 inline ParsedWallScalarBC
55 resolve_wall_scalar_value (bool value_specified,
56  amrex::Real primitive_value,
57  bool density_specified_on_same_face,
58  amrex::Real density_value)
59 {
60  if (!value_specified) {
61  return {};
62  }
63 
64  if (density_specified_on_same_face) {
66  density_value * primitive_value};
67  }
68 
69  return {WallScalarBCIntent::DirichletPrimitive, primitive_value};
70 }
71 
72 /**
73  * Resolve a wall scalar gradient into Neumann storage.
74  *
75  * @param[in] gradient_specified whether the scalar gradient was specified
76  * @param[in] gradient gradient value from inputs
77  */
78 inline ParsedWallScalarBC
79 resolve_wall_scalar_gradient (bool gradient_specified,
80  amrex::Real gradient)
81 {
82  if (!gradient_specified) {
83  return {};
84  }
85  return {WallScalarBCIntent::Neumann, gradient};
86 }
87 
88 /**
89  * Test whether value and gradient inputs conflict.
90  *
91  * @param[in] value_specified whether a scalar value was specified
92  * @param[in] gradient_specified whether a scalar gradient was specified
93  */
94 inline bool
96  bool gradient_specified)
97 {
98  return value_specified && gradient_specified;
99 }
100 
101 /**
102  * Build the error message for mutually exclusive wall scalar inputs.
103  *
104  * @param[in] face face name used in the input keys
105  * @param[in] variable variable name used in the input keys
106  */
107 inline std::string
108 wall_scalar_value_gradient_error (const std::string& face,
109  const std::string& variable)
110 {
111  return face + "." + variable + " and " + face + "." + variable
112  + "_grad are mutually exclusive";
113 }
114 
115 /**
116  * Build the anelastic-mode density error message for a wall face.
117  *
118  * @param[in] face face name used in the input keys
119  * @param[in] density_specified whether density was specified
120  * @param[in] density_gradient_specified whether density_grad was specified
121  */
122 inline std::string
123 anelastic_wall_density_error (const std::string& face,
124  bool density_specified,
125  bool density_gradient_specified)
126 {
127  if (!density_specified && !density_gradient_specified) {
128  return {};
129  }
130 
131  std::string message = face + ": density and density_grad must be omitted "
132  "on solid walls in anelastic mode (density is fixed by the base state)";
133  if (density_specified && density_gradient_specified) {
134  message += "; both keywords were supplied";
135  } else if (density_specified) {
136  message += "; " + face + ".density was supplied";
137  } else {
138  message += "; " + face + ".density_grad was supplied";
139  }
140  return message;
141 }
142 
143 /**
144  * Build the unsupported no-slip density-gradient error message.
145  *
146  * @param[in] face face name used in the input keys
147  */
148 inline std::string
149 no_slip_density_gradient_error (const std::string& face)
150 {
151  return face + ".density_grad is not supported for NoSlipWall; use "
152  + face + ".density for a fixed compressible wall density or omit "
153  "wall density in anelastic mode";
154 }
155 
156 /**
157  * Parse scalar wall boundary-condition inputs for one face.
158  *
159  * @param[in] pp ParmParse object scoped to the wall face
160  * @param[in] face face name used in errors
161  * @param[in] wall_kind no-slip or slip wall type
162  * @param[in] anelastic whether anelastic mode is active
163  */
164 inline WallFaceParseResult
165 parse_wall_face_scalars (amrex::ParmParse& pp,
166  const std::string& face,
167  SolidWallKind wall_kind,
168  bool anelastic)
169 {
170  amrex::Real density = amrex::Real(0.0);
171  const bool density_specified = pp.query("density", density);
172  amrex::Real density_grad = amrex::Real(0.0);
173  const bool density_gradient_specified = pp.query("density_grad", density_grad);
175  const bool theta_specified = pp.query("theta", theta);
176  amrex::Real theta_grad = amrex::Real(0.0);
177  const bool theta_gradient_specified = pp.query("theta_grad", theta_grad);
178 
179  amrex::Real qv = amrex::Real(0.0);
180  const bool qv_specified = (wall_kind == SolidWallKind::NoSlip) &&
181  pp.query("qv", qv);
182 
183  WallFaceParseResult result;
184  if (anelastic && (density_specified || density_gradient_specified)) {
186  face, density_specified, density_gradient_specified);
187  return result;
188  }
189 
190  if (wall_kind == SolidWallKind::NoSlip && density_gradient_specified) {
191  result.error = no_slip_density_gradient_error(face);
192  return result;
193  }
194 
195  if (wall_kind == SolidWallKind::Slip &&
196  wall_scalar_value_gradient_conflict(density_specified,
197  density_gradient_specified)) {
198  result.error = wall_scalar_value_gradient_error(face, "density");
199  return result;
200  }
201 
202  if (wall_scalar_value_gradient_conflict(theta_specified,
203  theta_gradient_specified)) {
204  result.error = wall_scalar_value_gradient_error(face, "theta");
205  return result;
206  }
207 
208  if (density_specified) {
209  result.scalars.density = {
211  }
213  theta_specified, theta, density_specified, density);
214  if (theta_gradient_specified) {
215  result.scalars.theta = resolve_wall_scalar_gradient(true, theta_grad);
216  }
217 
218  if (wall_kind == SolidWallKind::Slip && density_gradient_specified) {
219  result.scalars.density = resolve_wall_scalar_gradient(true, density_grad);
220  }
221 
222  if (qv_specified) {
224  true, qv, density_specified, density);
225  }
226 
227  return result;
228 }
229 
230 } // namespace erf_wall_scalar_bc
231 
232 #endif
ParmParse pp("prob")
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ theta
Definition: ERF_SLM.H:20
@ qv
Definition: ERF_Kessler.H:30
Definition: ERF_WallScalarBC.H:9
WallScalarBCIntent
Definition: ERF_WallScalarBC.H:13
std::string wall_scalar_value_gradient_error(const std::string &face, const std::string &variable)
Definition: ERF_WallScalarBC.H:108
bool wall_scalar_value_gradient_conflict(bool value_specified, bool gradient_specified)
Definition: ERF_WallScalarBC.H:95
std::string anelastic_wall_density_error(const std::string &face, bool density_specified, bool density_gradient_specified)
Definition: ERF_WallScalarBC.H:123
ParsedWallScalarBC resolve_wall_scalar_value(bool value_specified, amrex::Real primitive_value, bool density_specified_on_same_face, amrex::Real density_value)
Definition: ERF_WallScalarBC.H:55
SolidWallKind
Definition: ERF_WallScalarBC.H:20
std::string no_slip_density_gradient_error(const std::string &face)
Definition: ERF_WallScalarBC.H:149
ParsedWallScalarBC resolve_wall_scalar_gradient(bool gradient_specified, amrex::Real gradient)
Definition: ERF_WallScalarBC.H:79
WallFaceParseResult parse_wall_face_scalars(amrex::ParmParse &pp, const std::string &face, SolidWallKind wall_kind, bool anelastic)
Definition: ERF_WallScalarBC.H:165
Definition: ERF_WallScalarBC.H:30
ParsedWallScalarBC qv
Definition: ERF_WallScalarBC.H:33
ParsedWallScalarBC theta
Definition: ERF_WallScalarBC.H:32
ParsedWallScalarBC density
Definition: ERF_WallScalarBC.H:31
Definition: ERF_WallScalarBC.H:25
WallScalarBCIntent intent
Definition: ERF_WallScalarBC.H:26
amrex::Real stored_value
Definition: ERF_WallScalarBC.H:27
Definition: ERF_WallScalarBC.H:36
bool ok() const noexcept
Definition: ERF_WallScalarBC.H:43
ParsedWallFaceScalars scalars
Definition: ERF_WallScalarBC.H:37
std::string error
Definition: ERF_WallScalarBC.H:38