ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TimestepUtils.H File Reference
#include <ERF_Constants.H>
#include <ERF_TerrainMetrics.H>
#include <AMReX.H>
#include <AMReX_REAL.H>
#include <AMReX_Array.H>
#include <AMReX_Array4.H>
#include <AMReX_Algorithm.H>
#include <AMReX_Math.H>
#include <cmath>
Include dependency graph for ERF_TimestepUtils.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

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)
 
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)
 

Function Documentation

◆ Compute_InvDt_Anelastic()

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 
)

Pointwise inverse time step (1/dt, before the CFL is applied) for the anelastic (low Mach) solver – this is a purely advective constraint.

As above, the metric terms are computed here from z_nd:

terrain aware : the vertical spacing is the local dxinv[2]/h_zeta and w should be the contravariant (Omega) vertical velocity terrain unaware : the vertical spacing is dxinv[2] and w should be the Cartesian vertical velocity

The slope metrics h_xi and h_eta do not appear explicitly: for the advective constraint their effect is already carried by Omega, which is the vertical velocity relative to the terrain-following surfaces.

As in the compressible estimate, the horizontal terms use the physical cell widths dx/mf_x and dy/mf_y.

Parameters
[in]ix-index
[in]jy-index
[in]kz-index
[in]ucell-centered x-velocity
[in]vcell-centered y-velocity
[in]wcell-centered vertical velocity (Omega if terrain aware)
[in]z_ndnodal physical height field (not accessed if terrain unaware)
[in]mf_xx map factor at the cell center
[in]mf_yy map factor at the cell center
[in]dxinvinverse cell spacing of the computational mesh
[in]l_terrain_awaretrue to include the metric terms
Returns
1/dt for this cell
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 }
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_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

Referenced by ERF::estTimeStep().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Compute_InvDt_Compressible()

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 
)

Pointwise inverse time step (1/dt, before the CFL is applied) for the compressible solver.

The terrain metric terms are computed here from z_nd, so the same routine returns either the terrain aware or the terrain unaware estimate:

terrain aware : h_xi and h_eta are retained and the vertical spacing is the local dxinv[2]/h_zeta – w should be the contravariant (Omega) vertical velocity terrain unaware : h_xi = h_eta = 0 and the vertical spacing is dxinv[2] – w should be the Cartesian vertical velocity

Note that dxinv[2]*(h_xi/h_zeta) == h_xi*idz, which is why h_zeta only ever enters through idz.

The physical horizontal cell widths are dx/mf_x and dy/mf_y, so every horizontal term (advective and acoustic, including the h_xi and h_eta slope contributions) is scaled by the map factor in that direction. The map factors do not touch the vertical.

Parameters
[in]ix-index
[in]jy-index
[in]kz-index
[in]csound speed
[in]ucell-centered x-velocity
[in]vcell-centered y-velocity
[in]wcell-centered vertical velocity (Omega if terrain aware)
[in]z_ndnodal physical height field (not accessed if terrain unaware)
[in]mf_xx map factor at the cell center
[in]mf_yy map factor at the cell center
[in]dxinvinverse cell spacing of the computational mesh
[in]l_terrain_awaretrue to include the metric terms
[in]l_substeppingtrue if implicit acoustic substepping is used
[in]nxcnumber of cells in x on the level 0 domain
[in]nycnumber of cells in y on the level 0 domain
Returns
1/dt for this cell
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 }
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
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

Referenced by ERF::estTimeStep().

Here is the call graph for this function:
Here is the caller graph for this function: