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::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::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::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.

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]dxinvinverse cell spacing of the computational mesh
[in]l_terrain_awaretrue to include the metric terms
Returns
1/dt for this cell
162 {
163  amrex::Real idz = dxinv[2];
164  if (l_terrain_aware) {
165  idz /= Compute_h_zeta_AtCellCenter(i,j,k,dxinv,z_nd);
166  }
167 
168  return amrex::max(amrex::Math::abs(u)*dxinv[0],
169  amrex::Math::abs(v)*dxinv[1],
170  amrex::Math::abs(w)*idz );
171 }
Real w
Definition: ERF_Plotfile2DInterpolator.cpp:22
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:179

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::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.

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]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
59 {
60  amrex::Real h_xi = zero;
61  amrex::Real h_eta = zero;
62  amrex::Real idz = dxinv[2];
63  if (l_terrain_aware) {
64  h_xi = Compute_h_xi_AtCellCenter(i,j,k,dxinv,z_nd);
65  h_eta = Compute_h_eta_AtCellCenter(i,j,k,dxinv,z_nd);
66  idz /= Compute_h_zeta_AtCellCenter(i,j,k,dxinv,z_nd);
67  }
68 
69  const amrex::Real abs_u = amrex::Math::abs(u);
70  const amrex::Real abs_v = amrex::Math::abs(v);
71  const amrex::Real abs_w = amrex::Math::abs(w);
72 
74 
75  // If we are doing implicit acoustic substepping, then the z-direction is not constrained
76  // by the speed of sound for the computation of the time step
77  if (l_substepping) {
78  // Implicit substepping removes the g33 metric
79  // Acoustic contribution limits dtau, whose max is in the first RK stage (1/3 dt)
80  const amrex::Real Uacoustic = third * c * std::sqrt( dxinv[0] * (dxinv[0] + two * idz * amrex::Math::abs(h_xi )) );
81  const amrex::Real Vacoustic = third * c * std::sqrt( dxinv[1] * (dxinv[1] + two * idz * amrex::Math::abs(h_eta)) );
82  if ((nxc > 1) && (nyc == 1)) {
83  // 2-D in x-z
84  inv_dt = amrex::max(abs_u*dxinv[0] + Uacoustic,
85  abs_w*idz );
86  } else if ((nyc > 1) && (nxc == 1)) {
87  // 2-D in y-z
88  inv_dt = amrex::max(abs_v*dxinv[1] + Vacoustic,
89  abs_w*idz );
90  } else {
91  // 3-D
92  inv_dt = amrex::max(abs_u*dxinv[0] + Uacoustic,
93  abs_v*dxinv[1] + Vacoustic,
94  abs_w*idz );
95  }
96 
97  // If we are not doing implicit acoustic substepping, then the z-direction is constrained
98  // by the speed of sound for the computation of the time step
99  } else {
100  // All the metric terms
101  const amrex::Real Uacoustic = c * amrex::Math::abs(dxinv[0] + idz * h_xi );
102  const amrex::Real Vacoustic = c * amrex::Math::abs(dxinv[1] + idz * h_eta);
103  const amrex::Real Oacoustic = c * amrex::Math::abs(idz);
104  if (nxc > 1 && nyc > 1) {
105  // 3-D
106  inv_dt = amrex::max(abs_u*dxinv[0] + Uacoustic,
107  abs_v*dxinv[1] + Vacoustic,
108  abs_w*idz + Oacoustic);
109  } else if (nxc > 1) {
110  // 2-D in x-z
111  inv_dt = amrex::max(abs_u*dxinv[0] + Uacoustic,
112  abs_w*idz + Oacoustic);
113  } else if (nyc > 1) {
114  // 2-D in y-z
115  inv_dt = amrex::max(abs_v*dxinv[1] + Vacoustic,
116  abs_w*idz + Oacoustic);
117  } else {
118  // 1-D in z
119  inv_dt = abs_w*idz + Oacoustic;
120  }
121  }
122 
123  return inv_dt;
124 }
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real bogus_large_value
Definition: ERF_Constants.H:26
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real third
Definition: ERF_Constants.H:15
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:204
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:229

Referenced by ERF::estTimeStep().

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