ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TimestepUtils.H
Go to the documentation of this file.
1 #ifndef ERF_TIMESTEP_UTILS_H_
2 #define ERF_TIMESTEP_UTILS_H_
3 
4 #include <ERF_Constants.H>
5 #include <ERF_TerrainMetrics.H>
6 #include <AMReX.H>
7 #include <AMReX_REAL.H>
8 #include <AMReX_Array.H>
9 #include <AMReX_Array4.H>
10 #include <AMReX_Algorithm.H>
11 #include <AMReX_Math.H>
12 #include <cmath>
13 
14 /**
15  * Pointwise inverse time step (1/dt, before the CFL is applied) for the
16  * compressible solver.
17  *
18  * The terrain metric terms are computed here from z_nd, so the same routine
19  * returns either the terrain aware or the terrain unaware estimate:
20  *
21  * terrain aware : h_xi and h_eta are retained and the vertical spacing is
22  * the local dxinv[2]/h_zeta -- w should be the contravariant
23  * (Omega) vertical velocity
24  * terrain unaware : h_xi = h_eta = 0 and the vertical spacing is dxinv[2]
25  * -- w should be the Cartesian vertical velocity
26  *
27  * Note that dxinv[2]*(h_xi/h_zeta) == h_xi*idz, which is why h_zeta only ever
28  * enters through idz.
29  *
30  * The physical horizontal cell widths are dx/mf_x and dy/mf_y, so every
31  * horizontal term (advective and acoustic, including the h_xi and h_eta slope
32  * contributions) is scaled by the map factor in that direction. The map
33  * factors do not touch the vertical.
34  *
35  * @param[in] i x-index
36  * @param[in] j y-index
37  * @param[in] k z-index
38  * @param[in] c sound speed
39  * @param[in] u cell-centered x-velocity
40  * @param[in] v cell-centered y-velocity
41  * @param[in] w cell-centered vertical velocity (Omega if terrain aware)
42  * @param[in] z_nd nodal physical height field (not accessed if terrain unaware)
43  * @param[in] mf_x x map factor at the cell center
44  * @param[in] mf_y y map factor at the cell center
45  * @param[in] dxinv inverse cell spacing of the computational mesh
46  * @param[in] l_terrain_aware true to include the metric terms
47  * @param[in] l_substepping true if implicit acoustic substepping is used
48  * @param[in] nxc number of cells in x on the level 0 domain
49  * @param[in] nyc number of cells in y on the level 0 domain
50  * @return 1/dt for this cell
51  */
52 AMREX_GPU_HOST_DEVICE
53 AMREX_FORCE_INLINE
55 Compute_InvDt_Compressible (const int i, const int j, const int k,
56  const amrex::Real c,
57  const amrex::Real u,
58  const amrex::Real v,
59  const amrex::Real w,
60  const amrex::Array4<const amrex::Real>& z_nd,
61  const amrex::Real mf_x,
62  const amrex::Real mf_y,
63  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxinv,
64  const bool l_terrain_aware,
65  const bool l_substepping,
66  const int nxc=2,
67  const int nyc=2)
68 {
69  amrex::Real h_xi = zero;
70  amrex::Real h_eta = zero;
71  amrex::Real idz = dxinv[2];
72 
73  // Inverse physical horizontal spacing
74  const amrex::Real idx = mf_x * dxinv[0];
75  const amrex::Real idy = mf_y * dxinv[1];
76 
77  if (l_terrain_aware) {
78  h_xi = Compute_h_xi_AtCellCenter(i,j,k,dxinv,z_nd);
79  h_eta = Compute_h_eta_AtCellCenter(i,j,k,dxinv,z_nd);
80  idz /= Compute_h_zeta_AtCellCenter(i,j,k,dxinv,z_nd);
81  }
82 
83  const amrex::Real abs_u = amrex::Math::abs(u);
84  const amrex::Real abs_v = amrex::Math::abs(v);
85  const amrex::Real abs_w = amrex::Math::abs(w);
86 
88 
89  // If we are doing implicit acoustic substepping, then the z-direction is not constrained
90  // by the speed of sound for the computation of the time step
91  if (l_substepping) {
92  // Implicit substepping removes the g33 metric
93  // Acoustic contribution limits dtau, whose max is in the first RK stage (1/3 dt)
94  const amrex::Real Uacoustic = third * c * idx;
95  const amrex::Real Vacoustic = third * c * idy;
96  if ((nxc > 1) && (nyc == 1)) {
97  // 2-D in x-z
98  inv_dt = abs_u*idx + Uacoustic
99  + abs_w*idz;
100  } else if ((nyc > 1) && (nxc == 1)) {
101  // 2-D in y-z
102  inv_dt = abs_v*idy + Vacoustic
103  + abs_w*idz;
104  } else {
105  // 3-D
106  inv_dt = abs_u*idx + Uacoustic
107  + abs_v*idy + Vacoustic
108  + abs_w*idz;
109  }
110 
111  // If we are not doing implicit acoustic substepping, then the z-direction is constrained
112  // by the speed of sound for the computation of the time step
113  } else {
114  // All the metric terms
115  const amrex::Real Uacoustic = c * amrex::Math::abs(mf_x * (dxinv[0] + idz * h_xi ));
116  const amrex::Real Vacoustic = c * amrex::Math::abs(mf_y * (dxinv[1] + idz * h_eta));
117  const amrex::Real Oacoustic = c * amrex::Math::abs(idz);
118  if (nxc > 1 && nyc > 1) {
119  // 3-D
120  inv_dt = abs_u*idx + Uacoustic
121  + abs_v*idy + Vacoustic
122  + abs_w*idz + Oacoustic;
123  } else if (nxc > 1) {
124  // 2-D in x-z
125  inv_dt = abs_u*idx + Uacoustic
126  + abs_w*idz + Oacoustic;
127  } else if (nyc > 1) {
128  // 2-D in y-z
129  inv_dt = abs_v*idy + Vacoustic
130  + abs_w*idz + Oacoustic;
131  } else {
132  // 1-D in z
133  inv_dt = abs_w*idz + Oacoustic;
134  }
135  }
136 
137  return inv_dt;
138 }
139 
140 /**
141  * Pointwise inverse time step (1/dt, before the CFL is applied) for the
142  * anelastic (low Mach) solver -- this is a purely advective constraint.
143  *
144  * As above, the metric terms are computed here from z_nd:
145  *
146  * terrain aware : the vertical spacing is the local dxinv[2]/h_zeta and w
147  * should be the contravariant (Omega) vertical velocity
148  * terrain unaware : the vertical spacing is dxinv[2] and w should be the
149  * Cartesian vertical velocity
150  *
151  * The slope metrics h_xi and h_eta do not appear explicitly: for the advective
152  * constraint their effect is already carried by Omega, which is the vertical
153  * velocity relative to the terrain-following surfaces.
154  *
155  * As in the compressible estimate, the horizontal terms use the physical cell
156  * widths dx/mf_x and dy/mf_y.
157  *
158  * @param[in] i x-index
159  * @param[in] j y-index
160  * @param[in] k z-index
161  * @param[in] u cell-centered x-velocity
162  * @param[in] v cell-centered y-velocity
163  * @param[in] w cell-centered vertical velocity (Omega if terrain aware)
164  * @param[in] z_nd nodal physical height field (not accessed if terrain unaware)
165  * @param[in] mf_x x map factor at the cell center
166  * @param[in] mf_y y map factor at the cell center
167  * @param[in] dxinv inverse cell spacing of the computational mesh
168  * @param[in] l_terrain_aware true to include the metric terms
169  * @return 1/dt for this cell
170  */
171 AMREX_GPU_HOST_DEVICE
172 AMREX_FORCE_INLINE
174 Compute_InvDt_Anelastic (const int i, const int j, const int k,
175  const amrex::Real u,
176  const amrex::Real v,
177  const amrex::Real w,
178  const amrex::Array4<const amrex::Real>& z_nd,
179  const amrex::Real mf_x,
180  const amrex::Real mf_y,
181  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxinv,
182  const bool l_terrain_aware)
183 {
184  amrex::Real idz = dxinv[2];
185  if (l_terrain_aware) {
186  idz /= Compute_h_zeta_AtCellCenter(i,j,k,dxinv,z_nd);
187  }
188 
189  return ( amrex::Math::abs(u)*mf_x*dxinv[0]
190  + amrex::Math::abs(v)*mf_y*dxinv[1]
191  + amrex::Math::abs(w)*idz );
192 }
193 
194 #endif
constexpr amrex::Real bogus_large_value
Definition: ERF_Constants.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idx(int i, int j, int k, int nx, int ny)
Definition: ERF_InitForEnsemble.cpp:404
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
constexpr amrex::Real third
Definition: ERF_NumericalConstants.H:43
Real w
Definition: ERF_Plotfile2DInterpolator.cpp:23
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtCellCenter(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:226
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtCellCenter(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:251
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtCellCenter(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:201
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_InvDt_Compressible(const int i, const int j, const int k, const amrex::Real c, const amrex::Real u, const amrex::Real v, const amrex::Real w, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Real mf_x, const amrex::Real mf_y, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxinv, const bool l_terrain_aware, const bool l_substepping, const int nxc=2, const int nyc=2)
Definition: ERF_TimestepUtils.H:55
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_InvDt_Anelastic(const int i, const int j, const int k, const amrex::Real u, const amrex::Real v, const amrex::Real w, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Real mf_x, const amrex::Real mf_y, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxinv, const bool l_terrain_aware)
Definition: ERF_TimestepUtils.H:174