ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TerrainDiffusionLimits.H
Go to the documentation of this file.
1 /** \file ERF_TerrainDiffusionLimits.H */
2 
3 #ifndef ERF_TERRAIN_DIFFUSION_LIMITS_H_
4 #define ERF_TERRAIN_DIFFUSION_LIMITS_H_
5 
6 #include <AMReX_Array4.H>
7 #include <AMReX_Extension.H>
8 #include <AMReX_GpuQualifiers.H>
9 #include <AMReX_Algorithm.H>
10 #include <AMReX_Array.H>
11 #include <AMReX_Math.H>
12 #include <AMReX_REAL.H>
13 
14 #include "ERF_NumericalConstants.H"
15 #include "ERF_IndexDefines.H"
16 
17 #include <cmath>
18 
19 /**
20  * Terrain drop across one cell of a terrain-fitted mesh.
21  *
22  * dx_drop and dy_drop are the height differences across the cell along the
23  * coordinate surfaces, each the mean of the absolute differences on the four
24  * cell edges in that direction; dz is the physical thickness of the cell, the
25  * mean of its four vertical edges (detJ * dz at the cell center). All three
26  * are in metres and read only the eight nodes of the cell.
27  */
29 {
33 };
34 
35 /**
36  * Compute the terrain drops across cell (i,j,k) from the nodal heights.
37  *
38  * @param[in] i,j,k cell-centered indices
39  * @param[in] z_nd nodal physical heights
40  */
41 AMREX_GPU_HOST_DEVICE
42 AMREX_FORCE_INLINE
44 ComputeTerrainCellDrops (int i, int j, int k,
45  const amrex::Array4<const amrex::Real>& z_nd) noexcept
46 {
47  using amrex::Math::abs;
49  d.dx_drop = fourth * ( abs(z_nd(i+1,j ,k ) - z_nd(i,j ,k ))
50  + abs(z_nd(i+1,j+1,k ) - z_nd(i,j+1,k ))
51  + abs(z_nd(i+1,j ,k+1) - z_nd(i,j ,k+1))
52  + abs(z_nd(i+1,j+1,k+1) - z_nd(i,j+1,k+1)) );
53  d.dy_drop = fourth * ( abs(z_nd(i ,j+1,k ) - z_nd(i ,j,k ))
54  + abs(z_nd(i+1,j+1,k ) - z_nd(i+1,j,k ))
55  + abs(z_nd(i ,j+1,k+1) - z_nd(i ,j,k+1))
56  + abs(z_nd(i+1,j+1,k+1) - z_nd(i+1,j,k+1)) );
57  d.dz = fourth * ( (z_nd(i ,j ,k+1) - z_nd(i ,j ,k))
58  + (z_nd(i+1,j ,k+1) - z_nd(i+1,j ,k))
59  + (z_nd(i ,j+1,k+1) - z_nd(i ,j+1,k))
60  + (z_nd(i+1,j+1,k+1) - z_nd(i+1,j+1,k)) );
61  return d;
62 }
63 
64 /**
65  * Slope factor alpha = max( sqrt(dx_drop^2 + dy_drop^2) / dz, 1 ) of a cell:
66  * the terrain drop across one cell measured in cell thicknesses, which is
67  * h * Delta_x / Delta_z with h the physical coordinate slope. This is the
68  * factor of WRF's Smagorinsky-2D slope limiter (dyn_em/module_diffusion_em.F,
69  * smag2d_km, diff_opt = 2). WRF averages |z_x| at the two x-faces and the two
70  * w-levels of the cell and multiplies by dx / msftx; here the drop is taken on
71  * the four x-edges of the cell (ERF heights are nodal) and carries no map
72  * factor, so that alpha is exactly h * Delta_x / Delta_z with the physical
73  * spacing. The two agree when the map factor is 1.
74  */
75 AMREX_GPU_HOST_DEVICE
76 AMREX_FORCE_INLINE
79 {
80  const amrex::Real a = std::sqrt(d.dx_drop*d.dx_drop + d.dy_drop*d.dy_drop) / d.dz;
81  return amrex::max(a, amrex::Real(1.0));
82 }
83 
84 /** Deformation threshold speed of WRF's slope limiter, def_limit = max(10/Delta_h, 1e-3) (m/s). */
86 /** Floor of WRF's deformation threshold (1/s). */
88 
89 /**
90  * Apply the opt-in limits of WRF's smag2d_km to a Smagorinsky-2D horizontal
91  * kinematic eddy viscosity, in WRF's order:
92  * 1. the cap nu <= kh_cap * Delta_h (only if kh_cap > 0; WRF uses 10 m/s);
93  * 2. the slope limiter (only if use_slope):
94  * nu /= alpha^2 if |D_h| > max(10/Delta_h, 1e-3),
95  * nu /= alpha otherwise.
96  * |D_h| is the horizontal deformation sqrt((u_x - v_y)^2 + (u_y + v_x)^2),
97  * which equals ERF's sqrt(2 S_mn S_mn) of ComputeSmnSmn2D and WRF's
98  * sqrt(def2). Delta_h = sqrt(dx/m_x * dy/m_y), WRF's mlen_h.
99  *
100  * @param[in] nu Cs^2 Delta_h^2 |D_h| (m^2/s)
101  * @param[in] strain |D_h| (1/s)
102  * @param[in] DeltaH horizontal filter width (m)
103  * @param[in] alpha slope factor from TerrainSlopeFactor (>= 1)
104  * @param[in] kh_cap cap speed (m/s); <= 0 leaves nu uncapped
105  * @param[in] use_slope apply the slope limiter
106  */
107 AMREX_GPU_HOST_DEVICE
108 AMREX_FORCE_INLINE
111  amrex::Real alpha, amrex::Real kh_cap, bool use_slope) noexcept
112 {
113  if (kh_cap > zero) {
114  const amrex::Real nu_max = kh_cap * DeltaH;
115  nu = (nu < nu_max) ? nu : nu_max;
116  }
117  if (use_slope) {
118  const amrex::Real def_limit = amrex::max(amrex::Real(smag2d_def_limit_speed) / DeltaH,
120  nu = (strain > def_limit) ? nu / (alpha*alpha) : nu / alpha;
121  }
122  return nu;
123 }
124 
125 /**
126  * Explicit diffusion rates of one cell, for the diffusive time-step estimate
127  * dt * rate <= Fourier limit (1/2 for forward Euler in 3-D; the three-stage
128  * Runge-Kutta scheme's real-axis bound is about 2.5 / 4 = 0.63).
129  *
130  * Momentum: the largest of the three component rows,
131  * u: mu_h (2 a + b) + e_uv mu_v / dz^2 + mu_v sqrt(a c)
132  * v: mu_h (a + 2 b) + e_uv mu_v / dz^2 + mu_v sqrt(b c)
133  * w: mu_v (a + b) + 2 e_w mu_v / dz^2 + mu_v (sqrt(a c) + sqrt(b c)),
134  * with c = 1/dz^2, plus 2 mu_p h^2 / dz^2 for the terrain-metric part. The horizontal
135  * diffusion of w uses mu_v: tau31 and tau32 carry the same edge-averaged mu_v as tau13 and
136  * tau23. The sqrt terms are the u-w and v-w cross derivatives (dw/dx in tau13, du/dz in
137  * tau31, ...), which stay explicit whether or not the implicit solve takes the second
138  * vertical derivative; they are always counted, since with dz > dx/m they exceed the
139  * vertical term (dx = 100 m, dz = 500 m: five times). (The expansion
140  * rate in tau11 also couples u to dw/dz, with mu_h; that is covered by "an estimate when
141  * mu_h != mu_v" below.) The metric term is an upper bound: the projected horizontal
142  * stresses of the u and v fluxes carry mu_h (ComputeStressVarVisc_T), the w flux mu_v, hence
143  * mu_p = max(w_metric mu_h, mu_v).
144  *
145  * Scalar: K_h (a + b) + w_metric K_h h^2 / dz^2 + e K_v / dz^2 (the K_h h^2 part is
146  * TerrainDiffusionGz).
147  *
148  * w_metric weights the K_h metric term: 1 when it is explicit, and with
149  * erf.implicit_terrain_metric the component's explicit fraction e, since its compact form
150  * K_h M d2/dz2 is then in the implicit solve (u, v and the scalars; w is not). The difference
151  * between the averaged and the compact forms stays explicit and is not counted, so with the
152  * option the rate is an estimate.
153  *
154  * a = (m_x / dx)^2, b = (m_y / dy)^2 and h^2 = (m_x dx_drop / dx)^2 +
155  * (m_y dy_drop / dy)^2 is the squared physical slope; on a mesh without
156  * terrain pass h2 = 0. e is the explicit fraction of the vertical diffusion
157  * (ExplicitVerticalFraction): 0 when the implicit solve keeps every stage bounded,
158  * 1 otherwise. All diffusivities are dynamic (rho * nu); rates are in 1/s.
159  * The caller passes the largest diffusivities and the smallest density around the
160  * cell (NeighbourhoodMax, NeighbourhoodMinPositive), which bounds the row whatever
161  * face or edge averaging the operator uses.
162  */
163 AMREX_GPU_HOST_DEVICE
164 AMREX_FORCE_INLINE
168  amrex::Real e_uv, amrex::Real e_w, amrex::Real w_metric = one) noexcept
169 {
170  const amrex::Real xa = std::sqrt(a * dzinv2);
171  const amrex::Real xb = std::sqrt(b * dzinv2);
172  const amrex::Real r_u = mu_h * (two*a + b) + e_uv * mu_v * dzinv2 + mu_v * xa;
173  const amrex::Real r_v = mu_h * (a + two*b) + e_uv * mu_v * dzinv2 + mu_v * xb;
174  const amrex::Real r_w = mu_v * (a + b) + two * e_w * mu_v * dzinv2 + mu_v * (xa + xb);
175  const amrex::Real r_uv = (r_u > r_v) ? r_u : r_v;
176  const amrex::Real row = (r_uv > r_w) ? r_uv : r_w;
177  const amrex::Real mu_hm = w_metric * mu_h;
178  const amrex::Real mu_p = (mu_hm > mu_v) ? mu_hm : mu_v;
179  return ( row + two * mu_p * h2 * dzinv2 ) / rho;
180 }
181 
182 /**
183  * Largest value of component n over cell (i,j,k) and its 26 neighbours. The diffusion
184  * operators average the cell diffusivities to faces and edges, so a row of the operator
185  * never carries more than this. With NeighbourhoodMinPositive for the density and the
186  * coefficients frozen, the scalar rate is a Gershgorin bound on the centred interior stencil
187  * of the Cartesian operator (the higher-order one-sided gradients next to Dirichlet
188  * boundaries, ERF_ScalarDiffusion.H, whose row is about 4/3 larger, are not covered); for
189  * momentum it is a bound for
190  * uniform coefficients when mu_h = mu_v (tight on
191  * cubic cells) and an estimate otherwise, since the operator is then not symmetric.
192  * Needs one ghost cell.
193  */
194 AMREX_GPU_HOST_DEVICE
195 AMREX_FORCE_INLINE
197 NeighbourhoodMax (int i, int j, int k, int n, const amrex::Array4<const amrex::Real>& a) noexcept
198 {
199  amrex::Real m = a(i,j,k,n);
200  for (int kk = -1; kk <= 1; ++kk) {
201  for (int jj = -1; jj <= 1; ++jj) {
202  for (int ii = -1; ii <= 1; ++ii) {
203  const amrex::Real v = a(i+ii,j+jj,k+kk,n);
204  m = (v > m) ? v : m;
205  }}}
206  return m;
207 }
208 
209 /**
210  * Smallest positive value of component n over cell (i,j,k) and its 26 neighbours; ghost
211  * cells that hold no density (<= 0) are skipped. Returns `fallback` if none is positive.
212  */
213 AMREX_GPU_HOST_DEVICE
214 AMREX_FORCE_INLINE
216 NeighbourhoodMinPositive (int i, int j, int k, int n, const amrex::Array4<const amrex::Real>& a,
217  amrex::Real fallback) noexcept
218 {
219  amrex::Real m = fallback;
220  bool found = false;
221  for (int kk = -1; kk <= 1; ++kk) {
222  for (int jj = -1; jj <= 1; ++jj) {
223  for (int ii = -1; ii <= 1; ++ii) {
224  const amrex::Real v = a(i+ii,j+jj,k+kk,n);
225  if (v > zero && (!found || v < m)) { m = v; found = true; }
226  }}}
227  return m;
228 }
229 
230 /** Scalar counterpart of MomentumDiffusiveRate (see there). */
231 AMREX_GPU_HOST_DEVICE
232 AMREX_FORCE_INLINE
236  amrex::Real e_vert, amrex::Real w_metric = one) noexcept
237 {
238  return ( K_h * (a + b) + w_metric * K_h * h2 * dzinv2 + e_vert * K_v * dzinv2 ) / rho;
239 }
240 
241 /** Which components carry diffusion, and their explicit vertical fractions, for CellDiffusiveRates. */
243 {
244  bool variable_dz = false; // terrain-fitted or stretched mesh: dz and slope from z_nd
245  bool has_q = false; // moisture carried
246  bool has_ke = false; // turbulent kinetic energy carried
247  bool has_scalar = false; // advected scalar carried
248  bool implicit_metric = false; // erf.implicit_terrain_metric: K_h metric term weighted by e
250 };
251 
252 /**
253  * Explicit eddy-diffusion rates of cell (i,j,k), momentum and scalars (1/s), as the
254  * diffusive time-step check reduces them: MomentumDiffusiveRate and ScalarDiffusiveRate with
255  * the largest diffusivities and the smallest positive density over the cell and its 26
256  * neighbours. Both are zero in a cell without density (covered).
257  *
258  * @param[in] s_arr conserved state (Rho_comp), one ghost cell
259  * @param[in] k_arr eddy diffusivities (EddyDiff components), one ghost cell
260  * @param[in] z_nd nodal heights (read only when set.variable_dz)
261  * @param[in] mf_mx, mf_my map factors of the cell
262  * @param[in] dxinv inverse cell sizes
263  */
264 AMREX_GPU_HOST_DEVICE
265 AMREX_FORCE_INLINE
266 void
267 CellDiffusiveRates (int i, int j, int k,
268  const amrex::Array4<const amrex::Real>& s_arr,
269  const amrex::Array4<const amrex::Real>& k_arr,
270  const amrex::Array4<const amrex::Real>& z_nd,
271  amrex::Real mf_mx, amrex::Real mf_my,
272  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxinv,
273  const DiffusiveRateSettings& set,
274  amrex::Real& rate_mom, amrex::Real& rate_scal) noexcept
275 {
276  const amrex::Real ax = mf_mx * dxinv[0];
277  const amrex::Real ay = mf_my * dxinv[1];
278  amrex::Real dzinv = dxinv[2];
279  amrex::Real h2 = zero;
280  if (set.variable_dz) {
281  const TerrainCellDrops d = ComputeTerrainCellDrops(i,j,k,z_nd);
282  dzinv = one / d.dz;
283  const amrex::Real hx = ax * d.dx_drop;
284  const amrex::Real hy = ay * d.dy_drop;
285  h2 = hx*hx + hy*hy;
286  }
287  const amrex::Real rho = s_arr(i,j,k,Rho_comp);
288  if (!(rho > zero)) { rate_mom = zero; rate_scal = zero; return; }
289  const amrex::Real rdiv = NeighbourhoodMinPositive(i,j,k,Rho_comp,s_arr,rho);
290  const amrex::Real a2 = ax*ax;
291  const amrex::Real b2 = ay*ay;
292  const amrex::Real dzinv2 = dzinv*dzinv;
293  // with erf.implicit_terrain_metric the K_h metric term counts with the explicit fraction
294  rate_mom = MomentumDiffusiveRate(rdiv, NeighbourhoodMax(i,j,k,EddyDiff::Mom_h,k_arr),
295  NeighbourhoodMax(i,j,k,EddyDiff::Mom_v,k_arr),
296  a2, b2, h2, dzinv2, set.e_uv, set.e_w, (set.implicit_metric ? set.e_uv : one));
298  NeighbourhoodMax(i,j,k,EddyDiff::Theta_v,k_arr),
299  a2, b2, h2, dzinv2, set.e_th, (set.implicit_metric ? set.e_th : one));
300  if (set.has_q) {
301  rs = amrex::max(rs, ScalarDiffusiveRate(rdiv, NeighbourhoodMax(i,j,k,EddyDiff::Q_h,k_arr),
302  NeighbourhoodMax(i,j,k,EddyDiff::Q_v,k_arr),
303  a2, b2, h2, dzinv2, set.e_q, (set.implicit_metric ? set.e_q : one)));
304  }
305  if (set.has_ke) {
306  rs = amrex::max(rs, ScalarDiffusiveRate(rdiv, NeighbourhoodMax(i,j,k,EddyDiff::KE_h,k_arr),
307  NeighbourhoodMax(i,j,k,EddyDiff::KE_v,k_arr),
308  a2, b2, h2, dzinv2, set.e_ke, (set.implicit_metric ? set.e_ke : one)));
309  }
310  if (set.has_scalar) {
311  rs = amrex::max(rs, ScalarDiffusiveRate(rdiv, NeighbourhoodMax(i,j,k,EddyDiff::Scalar_h,k_arr),
313  a2, b2, h2, dzinv2, one));
314  }
315  rate_scal = rs;
316 }
317 
318 /**
319  * Whether the terrain slope-factor report is evaluated this coarse step: always on a new set
320  * of grids, and every step on a moving terrain (MovingFittedMesh), where alpha changes with time.
321  */
322 inline bool
323 SlopeReportEvaluate (bool new_grids, bool moving_terrain)
324 {
325  return new_grids || moving_terrain;
326 }
327 
328 /**
329  * Whether an evaluated slope-factor report is printed: always when forced (new grids),
330  * otherwise only if the largest alpha moved by more than 1 % from the last printed value.
331  * alpha >= 1 by construction, so the relative test never fires on changes below 0.01.
332  */
333 inline bool
334 SlopeReportPrint (bool force, amrex::Real alpha_max, amrex::Real alpha_last)
335 {
336  return force || std::abs(alpha_max - alpha_last) > amrex::Real(0.01) * alpha_last;
337 }
338 
339 /**
340  * Explicit fraction of the vertical diffusion for the diffusive time-step check: 0 if every
341  * stage of the partly implicit Runge-Kutta scheme stays bounded for the vertical diffusion,
342  * 1 otherwise (including every pattern for which that has not been shown).
343  *
344  * Each stage k starts from S^n with stage step c_k dt; its explicit part (1 - f_k) acts on
345  * the previous stage's state and its implicit part f_k on its own, so for dS/dt = lambda S
346  * and y = -lambda dt >= 0, S_k = (1 - (1 - f_k) c_k y S_{k-1}) / (1 + f_k c_k y), S_0 = 1.
347  * Each stage's state feeds the next stage's explicit terms, so every |S_k| must stay <= 1,
348  * not only the last. The result is decided analytically:
349  *
350  * - three stages (c = 1/3, 1/2, 1; compressible): bounded for f_1 >= 1/2, f_2 = 1 and any
351  * f_3 in [0,1]. |S_1| <= 1 iff f_1 >= 1/2: |1 - (1-f) x| <= 1 + (1-f) x <= 1 + f x for
352  * f >= 1/2, and for f < 1/2, S_1 -> -(1-f)/f < -1 as x -> infinity;
353  * S_2 = 1 / (1 + y/2); and S_3 = (1 + (f_3 - 1/2) y) / ((1 + y/2)(1 + f_3 y)), whose
354  * numerator is at most 1 + y/2 in size. The default 1 1 0 is Crank-Nicolson, 1 1 1
355  * backward Euler.
356  * - two stages (c = 1/2, 1; anelastic MidPoint): bounded for f_1 = 1 and any f_2 in [0,1]
357  * (the same S_3 form); with f_1 < 1 and f_2 = 0, as MidPoint forces, the second stage
358  * grows without bound.
359  *
360  * Every other pattern returns 1: some are not bounded (0 0 1, 1 0 0, and 0.995 0.1 0.0666,
361  * whose last stage reaches 1.0008 near y = 23.5), and the rest are not shown to be.
362  *
363  * @param[in] nstages 3 for the compressible scheme, 2 for anelastic MidPoint
364  * @param[in] fac implicit factor f_k of each stage (erf.vert_implicit_fac)
365  * @param[in] implicit whether the implicit solve treats this component at all
366  */
367 template <typename V>
369 ExplicitVerticalFraction (int nstages, const V& fac, bool implicit)
370 {
371  if (!implicit || static_cast<int>(fac.size()) < nstages) { return one; }
372  // The proof assumes factors in [0,1]; anything else (the inputs are not range-checked,
373  // and 1 1.5 0 amplifies by 4/3) counts as explicit rather than being clamped.
374  for (int k = 0; k < nstages; ++k) {
375  const double fk = static_cast<double>(fac[k]);
376  if (!(fk >= 0.0 && fk <= 1.0)) { return one; }
377  }
378  auto f = [&] (int k) { return static_cast<double>(fac[k]); };
379  if (nstages == 3) {
380  return (f(0) >= 0.5 && f(1) >= 1.0) ? zero : one;
381  }
382  if (nstages == 2) {
383  return (f(0) >= 1.0) ? zero : one;
384  }
385  return one;
386 }
387 
388 #endif
#define Rho_comp
Definition: ERF_IndexDefines.H:42
Dimensionless numeric literals and pure mathematical constants.
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:38
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real NeighbourhoodMinPositive(int i, int j, int k, int n, const amrex::Array4< const amrex::Real > &a, amrex::Real fallback) noexcept
Definition: ERF_TerrainDiffusionLimits.H:216
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void CellDiffusiveRates(int i, int j, int k, const amrex::Array4< const amrex::Real > &s_arr, const amrex::Array4< const amrex::Real > &k_arr, const amrex::Array4< const amrex::Real > &z_nd, amrex::Real mf_mx, amrex::Real mf_my, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxinv, const DiffusiveRateSettings &set, amrex::Real &rate_mom, amrex::Real &rate_scal) noexcept
Definition: ERF_TerrainDiffusionLimits.H:267
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Smag2DLimitedViscosity(amrex::Real nu, amrex::Real strain, amrex::Real DeltaH, amrex::Real alpha, amrex::Real kh_cap, bool use_slope) noexcept
Definition: ERF_TerrainDiffusionLimits.H:110
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusiveRate(amrex::Real rho, amrex::Real K_h, amrex::Real K_v, amrex::Real a, amrex::Real b, amrex::Real h2, amrex::Real dzinv2, amrex::Real e_vert, amrex::Real w_metric=one) noexcept
Definition: ERF_TerrainDiffusionLimits.H:234
amrex::Real ExplicitVerticalFraction(int nstages, const V &fac, bool implicit)
Definition: ERF_TerrainDiffusionLimits.H:369
constexpr amrex::Real smag2d_def_limit_speed
Definition: ERF_TerrainDiffusionLimits.H:85
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainSlopeFactor(const TerrainCellDrops &d) noexcept
Definition: ERF_TerrainDiffusionLimits.H:78
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE TerrainCellDrops ComputeTerrainCellDrops(int i, int j, int k, const amrex::Array4< const amrex::Real > &z_nd) noexcept
Definition: ERF_TerrainDiffusionLimits.H:44
constexpr amrex::Real smag2d_def_limit_min
Definition: ERF_TerrainDiffusionLimits.H:87
bool SlopeReportEvaluate(bool new_grids, bool moving_terrain)
Definition: ERF_TerrainDiffusionLimits.H:323
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real NeighbourhoodMax(int i, int j, int k, int n, const amrex::Array4< const amrex::Real > &a) noexcept
Definition: ERF_TerrainDiffusionLimits.H:197
bool SlopeReportPrint(bool force, amrex::Real alpha_max, amrex::Real alpha_last)
Definition: ERF_TerrainDiffusionLimits.H:334
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real MomentumDiffusiveRate(amrex::Real rho, amrex::Real mu_h, amrex::Real mu_v, amrex::Real a, amrex::Real b, amrex::Real h2, amrex::Real dzinv2, amrex::Real e_uv, amrex::Real e_w, amrex::Real w_metric=one) noexcept
Definition: ERF_TerrainDiffusionLimits.H:166
@ Theta_v
Definition: ERF_IndexDefines.H:253
@ Scalar_v
Definition: ERF_IndexDefines.H:255
@ Mom_h
Definition: ERF_IndexDefines.H:247
@ Q_v
Definition: ERF_IndexDefines.H:256
@ Q_h
Definition: ERF_IndexDefines.H:251
@ Mom_v
Definition: ERF_IndexDefines.H:252
@ Scalar_h
Definition: ERF_IndexDefines.H:250
@ KE_v
Definition: ERF_IndexDefines.H:254
@ Theta_h
Definition: ERF_IndexDefines.H:248
@ KE_h
Definition: ERF_IndexDefines.H:249
@ rho
Definition: ERF_Kessler.H:25
@ V
Definition: ERF_IndexDefines.H:130
@ alpha
Definition: ERF_SLM.H:151
real(c_double), parameter a2
Definition: ERF_module_model_constants.F90:95
real(c_double), parameter r_v
Definition: ERF_module_model_constants.F90:24
Definition: ERF_TerrainDiffusionLimits.H:243
amrex::Real e_uv
Definition: ERF_TerrainDiffusionLimits.H:249
bool has_scalar
Definition: ERF_TerrainDiffusionLimits.H:247
bool implicit_metric
Definition: ERF_TerrainDiffusionLimits.H:248
amrex::Real e_ke
Definition: ERF_TerrainDiffusionLimits.H:249
bool variable_dz
Definition: ERF_TerrainDiffusionLimits.H:244
bool has_q
Definition: ERF_TerrainDiffusionLimits.H:245
amrex::Real e_w
Definition: ERF_TerrainDiffusionLimits.H:249
amrex::Real e_th
Definition: ERF_TerrainDiffusionLimits.H:249
bool has_ke
Definition: ERF_TerrainDiffusionLimits.H:246
amrex::Real e_q
Definition: ERF_TerrainDiffusionLimits.H:249
Definition: ERF_TerrainDiffusionLimits.H:29
amrex::Real dz
Definition: ERF_TerrainDiffusionLimits.H:32
amrex::Real dy_drop
Definition: ERF_TerrainDiffusionLimits.H:31
amrex::Real dx_drop
Definition: ERF_TerrainDiffusionLimits.H:30