ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_Substep_MT.cpp File Reference
#include <ERF_TI_fast_headers.H>
#include "ERF_Constants.H"
Include dependency graph for ERF_Substep_MT.cpp:

Functions

void erf_substep_MT (int step, int, int level, int finest_level, Vector< MultiFab > &S_slow_rhs, const Vector< MultiFab > &S_prev, Vector< MultiFab > &S_stg_data, const MultiFab &S_stg_prim, const MultiFab &qt, const MultiFab &pi_stage, const MultiFab &fast_coeffs, Vector< MultiFab > &S_data, MultiFab &lagged_delta_rt, MultiFab &avg_xmom, MultiFab &avg_ymom, MultiFab &avg_zmom, const MultiFab &cc_src, const MultiFab &xmom_src, const MultiFab &ymom_src, const MultiFab &zmom_src, const Geometry geom, const Real gravity, const bool use_lagged_delta_rt, std::unique_ptr< MultiFab > &z_t_rk, const MultiFab *z_t_pert, std::unique_ptr< MultiFab > &z_phys_nd_old, std::unique_ptr< MultiFab > &z_phys_nd_new, std::unique_ptr< MultiFab > &z_phys_nd_stg, std::unique_ptr< MultiFab > &detJ_cc_old, std::unique_ptr< MultiFab > &detJ_cc_new, std::unique_ptr< MultiFab > &detJ_cc_stg, const double dtau_d, const Real facinv, Vector< std::unique_ptr< MultiFab >> &mapfac, YAFluxRegister *fr_as_crse, YAFluxRegister *fr_as_fine, bool l_use_moisture, bool l_reflux, bool, const Real *sinesq_stag_d, const Real l_damp_coef, const Real beta_d)
 

Function Documentation

◆ erf_substep_MT()

void erf_substep_MT ( int  step,
int  ,
int  level,
int  finest_level,
Vector< MultiFab > &  S_slow_rhs,
const Vector< MultiFab > &  S_prev,
Vector< MultiFab > &  S_stg_data,
const MultiFab &  S_stg_prim,
const MultiFab &  qt,
const MultiFab &  pi_stage,
const MultiFab &  fast_coeffs,
Vector< MultiFab > &  S_data,
MultiFab &  lagged_delta_rt,
MultiFab &  avg_xmom,
MultiFab &  avg_ymom,
MultiFab &  avg_zmom,
const MultiFab &  cc_src,
const MultiFab &  xmom_src,
const MultiFab &  ymom_src,
const MultiFab &  zmom_src,
const Geometry  geom,
const Real  gravity,
const bool  use_lagged_delta_rt,
std::unique_ptr< MultiFab > &  z_t_rk,
const MultiFab *  z_t_pert,
std::unique_ptr< MultiFab > &  z_phys_nd_old,
std::unique_ptr< MultiFab > &  z_phys_nd_new,
std::unique_ptr< MultiFab > &  z_phys_nd_stg,
std::unique_ptr< MultiFab > &  detJ_cc_old,
std::unique_ptr< MultiFab > &  detJ_cc_new,
std::unique_ptr< MultiFab > &  detJ_cc_stg,
const double  dtau_d,
const Real  facinv,
Vector< std::unique_ptr< MultiFab >> &  mapfac,
YAFluxRegister *  fr_as_crse,
YAFluxRegister *  fr_as_fine,
bool  l_use_moisture,
bool  l_reflux,
bool  ,
const Real *  sinesq_stag_d,
const Real  l_damp_coef,
const Real  beta_d 
)

Function for computing the fast RHS with moving terrain

Parameters
[in]stepwhich fast time step within each Runge-Kutta step
[in]nrkwhich Runge-Kutta step
[in]levellevel of resolution
[in]finest_levelfinest level of resolution
[in]S_slow_rhsslow RHS computed in erf_slow_rhs_pre
[in]S_prevprevious solution
[in]S_stg_datasolution at previous RK stage
[in]S_stg_primprimitive variables at previous RK stage
[in]pi_stageExner function at previous RK stage
[in]fast_coeffscoefficients for the tridiagonal solve used in the fast integrator, and beta_s on the w-faces (component 5)
[out]S_datacurrent solution
[in,out]lagged_delta_rt
[in,out]avg_xmomtime-averaged x-momentum to be used for updating slow variables
[in,out]avg_ymomtime-averaged y-momentum to be used for updating slow variables
[in,out]avg_zmomtime-averaged z-momentum to be used for updating slow variables
[in]cc_srcsource terms for conserved variables
[in]xmom_srcsource terms for x-momentum
[in]ymom_srcsource terms for y-momentum
[in]zmom_srcsource terms for z-momentum
[in]geomcontainer for geometric information
[in]gravityMagnitude of gravity
[in]use_lagged_delta_rtdefine lagged_delta_rt for our next step
[in]z_t_rkrate of change of grid height – only relevant for moving terrain
[in]z_t_pertrate of change of grid height – interpolated between RK stages
[in]z_phys_nd_oldheight coordinate at nodes at old time
[in]z_phys_nd_newheight coordinate at nodes at new time
[in]z_phys_nd_stgheight coordinate at nodes at previous stage
[in]detJ_cc_oldJacobian of the metric transformation at old time
[in]detJ_cc_newJacobian of the metric transformation at new time
[in]detJ_cc_stgJacobian of the metric transformation at previous stage
[in]dtaufast time step
[in]facinvinverse factor for time-averaging the momenta
[in]mapfacvector of map factors
[in,out]fr_as_crseYAFluxRegister at level l at level l / l+1 interface
[in,out]fr_as_fineYAFluxRegister at level l at level l-1 / l interface
[in]l_use_moisture
[in]l_refluxshould we add fluxes to the FluxRegisters?
[in]l_damp_coef
[in]beta_ddivergence damping coefficient: how far (rho theta) is projected forward
92 {
93  BL_PROFILE_REGION("erf_substep_MT()");
94 
95  Real dtau = static_cast<Real>(dtau_d);
96 
97  Real RvOverRd = R_v / R_d;
98 
99  bool l_rayleigh_impl_for_w = (sinesq_stag_d != nullptr);
100 
101  const Real* dx = geom.CellSize();
102  const GpuArray<Real, AMREX_SPACEDIM> dxInv = geom.InvCellSizeArray();
103  const int domlo_z = geom.Domain().smallEnd(2);
104  const int domhi_z = geom.Domain().bigEnd(2);
105 
106  Real dxi = dxInv[0];
107  Real dyi = dxInv[1];
108  Real dzi = dxInv[2];
109 
110  MultiFab coeff_A_mf(fast_coeffs, make_alias, 0, 1);
111  MultiFab inv_coeff_B_mf(fast_coeffs, make_alias, 1, 1);
112  MultiFab coeff_C_mf(fast_coeffs, make_alias, 2, 1);
113  MultiFab coeff_P_mf(fast_coeffs, make_alias, 3, 1);
114  MultiFab coeff_Q_mf(fast_coeffs, make_alias, 4, 1);
115 
116  // beta_s on the w-faces, from which
117  // beta_1 = myhalf * (one - beta_s) multiplies explicit terms
118  // beta_2 = myhalf * (one + beta_s) multiplies implicit terms
119  MultiFab beta_s_mf(fast_coeffs, make_alias, 5, 1);
120 
121  // *************************************************************************
122  // Set gravity as a vector
123  const Array<Real,AMREX_SPACEDIM> grav{zero, zero, -gravity};
124  const GpuArray<Real,AMREX_SPACEDIM> grav_gpu{grav[0], grav[1], grav[2]};
125 
126  MultiFab extrap(S_data[IntVars::cons].boxArray(),S_data[IntVars::cons].DistributionMap(),1,1);
127 
128  MultiFab Omega(S_data[IntVars::zmom].boxArray(), S_data[IntVars::zmom].DistributionMap(), 1, 1);
129 
130  // *************************************************************************
131  // Define updates in the current RK stg
132  // *************************************************************************
133 #ifdef _OPENMP
134 #pragma omp parallel if (Gpu::notInLaunchRegion())
135 #endif
136  {
137  FArrayBox temp_rhs_fab;
138 
139  FArrayBox RHS_fab;
140  FArrayBox soln_fab;
141 
142  std::array<FArrayBox,AMREX_SPACEDIM> flux;
143 
144  // NOTE: we leave tiling off here for efficiency -- to make this loop work with tiling
145  // will require additional changes
146  for ( MFIter mfi(S_stg_data[IntVars::cons],false); mfi.isValid(); ++mfi)
147  {
148  Box bx = mfi.tilebox();
149  Box tbx = surroundingNodes(bx,0);
150  Box tby = surroundingNodes(bx,1);
151  Box tbz = surroundingNodes(bx,2);
152 
153  Box vbx = mfi.validbox();
154  const auto& vbx_hi = ubound(vbx);
155 
156  // The vertical solve below takes the bottom of the box as the moving terrain and the
157  // top of the box as the top of the domain, so a grid that is split in z (level 0 with
158  // max_grid_size_z below the domain height) or a refined grid with c/f faces in z
159  // would be solved for with the wrong boundary rows
160  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(vbx.smallEnd(2) == domlo_z && vbx.bigEnd(2) == domhi_z,
161  "erf_substep_MT: MovingFittedMesh requires every grid to span the full height of the domain");
162 
163  const Array4<Real const>& xmom_src_arr = xmom_src.const_array(mfi);
164  const Array4<Real const>& ymom_src_arr = ymom_src.const_array(mfi);
165  const Array4<Real const>& zmom_src_arr = zmom_src.const_array(mfi);
166  const Array4<Real const>& cc_src_arr = cc_src.const_array(mfi);
167 
168  const Array4<const Real> & stg_cons = S_stg_data[IntVars::cons].const_array(mfi);
169  const Array4<const Real> & stg_xmom = S_stg_data[IntVars::xmom].const_array(mfi);
170  const Array4<const Real> & stg_ymom = S_stg_data[IntVars::ymom].const_array(mfi);
171  const Array4<const Real> & stg_zmom = S_stg_data[IntVars::zmom].const_array(mfi);
172  const Array4<const Real> & prim = S_stg_prim.const_array(mfi);
173  const Array4<const Real> & qt_arr = qt.const_array(mfi);
174 
175  const Array4<const Real>& slow_rhs_cons = S_slow_rhs[IntVars::cons].const_array(mfi);
176  const Array4<const Real>& slow_rhs_rho_u = S_slow_rhs[IntVars::xmom].const_array(mfi);
177  const Array4<const Real>& slow_rhs_rho_v = S_slow_rhs[IntVars::ymom].const_array(mfi);
178  const Array4<const Real>& slow_rhs_rho_w = S_slow_rhs[IntVars::zmom].const_array(mfi);
179 
180  const Array4<Real>& cur_cons = S_data[IntVars::cons].array(mfi);
181  const Array4<Real>& cur_xmom = S_data[IntVars::xmom].array(mfi);
182  const Array4<Real>& cur_ymom = S_data[IntVars::ymom].array(mfi);
183  const Array4<Real>& cur_zmom = S_data[IntVars::zmom].array(mfi);
184 
185  const Array4<Real>& lagged = lagged_delta_rt.array(mfi);
186 
187  const Array4<const Real>& prev_cons = S_prev[IntVars::cons].const_array(mfi);
188  const Array4<const Real>& prev_xmom = S_prev[IntVars::xmom].const_array(mfi);
189  const Array4<const Real>& prev_ymom = S_prev[IntVars::ymom].const_array(mfi);
190  const Array4<const Real>& prev_zmom = S_prev[IntVars::zmom].const_array(mfi);
191 
192  // These store the advection momenta which we will use to update the slow variables
193  const Array4<Real>& avg_xmom_arr = avg_xmom.array(mfi);
194  const Array4<Real>& avg_ymom_arr = avg_ymom.array(mfi);
195  const Array4<Real>& avg_zmom_arr = avg_zmom.array(mfi);
196 
197  const Array4<const Real>& z_nd_old = z_phys_nd_old->const_array(mfi);
198  const Array4<const Real>& z_nd_new = z_phys_nd_new->const_array(mfi);
199  const Array4<const Real>& z_nd_stg = z_phys_nd_stg->const_array(mfi);
200  const Array4<const Real>& detJ_old = detJ_cc_old->const_array(mfi);
201  const Array4<const Real>& detJ_new = detJ_cc_new->const_array(mfi);
202  const Array4<const Real>& detJ_stg = detJ_cc_stg->const_array(mfi);
203 
204  const Array4<const Real>& z_t_arr = z_t_rk->const_array(mfi);
205  const Array4<const Real>& zp_t_arr = z_t_pert->const_array(mfi);
206 
207  const Array4< Real>& omega_arr = Omega.array(mfi);
208 
209  // Map factors
210  const Array4<const Real>& mf_mx = mapfac[MapFacType::m_x]->const_array(mfi);
211  const Array4<const Real>& mf_my = mapfac[MapFacType::m_y]->const_array(mfi);
212  const Array4<const Real>& mf_ux = mapfac[MapFacType::u_x]->const_array(mfi);
213  const Array4<const Real>& mf_vy = mapfac[MapFacType::v_y]->const_array(mfi);
214 
215  // *********************************************************************
216  // This must be done before we set cur_xmom and cur_ymom, since those
217  // in fact point to the same array as prev_xmom and prev_ymom
218  // *********************************************************************
219  Box gbxo = mfi.nodaltilebox(2);
220  {
221  BL_PROFILE("fast_MT_making_omega");
222  Box gbxo_lo = gbxo; gbxo_lo.setBig(2,0);
223  ParallelFor(gbxo_lo, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
224  omega_arr(i,j,k) = zero;
225  });
226  Box gbxo_hi = gbxo; gbxo_hi.setSmall(2,gbxo.bigEnd(2));
227  ParallelFor(gbxo_hi, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
228  omega_arr(i,j,k) = prev_zmom(i,j,k) - stg_zmom(i,j,k) - zp_t_arr(i,j,k);
229  });
230 
231  // gbxo_lo covers k<=0 and gbxo_hi covers the box's top face, so the mid box is
232  // [max(smallEnd,1), bigEnd-1]. Using max() never EXPANDS the box past the FAB,
233  // which is what setSmall(2,1) does for a box that starts above k=1.
234  Box gbxo_mid = gbxo;
235  gbxo_mid.setSmall(2, std::max(gbxo.smallEnd(2), 1));
236  gbxo_mid.setBig (2, gbxo.bigEnd(2)-1);
237 
238  ParallelFor(gbxo_mid, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
239  omega_arr(i,j,k) =
240  ( OmegaFromW(i,j,k,prev_zmom(i,j,k),prev_xmom,prev_ymom,mf_ux,mf_vy,z_nd_old,dxInv)
241  -OmegaFromW(i,j,k, stg_zmom(i,j,k), stg_xmom, stg_ymom,mf_ux,mf_vy,z_nd_old,dxInv) )
242  - zp_t_arr(i,j,k);
243  });
244  } // end profile
245  // *********************************************************************
246 
247  const Array4<const Real>& pi_stage_ca = pi_stage.const_array(mfi);
248 
249  const Array4<Real>& theta_extrap = extrap.array(mfi);
250 
251  // Note: it is important to grow the tilebox rather than use growntilebox because
252  // we need to fill the ghost cells of the tilebox so we can use them below
253  Box gbx = mfi.tilebox(); gbx.grow(1);
254  Box gtbx = mfi.nodaltilebox(0); gtbx.grow(1); gtbx.setSmall(2,0);
255  Box gtby = mfi.nodaltilebox(1); gtby.grow(1); gtby.setSmall(2,0);
256 
257  if (step == 0) {
258  ParallelFor(gbx,
259  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
260  cur_cons(i,j,k,Rho_comp) = prev_cons(i,j,k,Rho_comp);
261  cur_cons(i,j,k,RhoTheta_comp) = prev_cons(i,j,k,RhoTheta_comp);
262 
263  Real delta_rt = cur_cons(i,j,k,RhoTheta_comp) - stg_cons(i,j,k,RhoTheta_comp);
264  theta_extrap(i,j,k) = delta_rt;
265 
266  // NOTE: qv is not changing over the fast steps so we use the stage data
267  Real qv = (l_use_moisture) ? prim(i,j,k,PrimQ1_comp) : zero;
268  theta_extrap(i,j,k) *= (one + RvOverRd*qv);
269 
270  // We define lagged_delta_rt for our next step as the current delta_rt
271  lagged(i,j,k) = delta_rt;
272  });
273  } else if (use_lagged_delta_rt) {
274  // This is the default for cases with no or static terrain
275  ParallelFor(gbx,
276  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
277  Real delta_rt = cur_cons(i,j,k,RhoTheta_comp) - stg_cons(i,j,k,RhoTheta_comp);
278  theta_extrap(i,j,k) = delta_rt + beta_d * (delta_rt - lagged(i,j,k));
279 
280  // NOTE: qv is not changing over the fast steps so we use the stage data
281  Real qv = (l_use_moisture) ? prim(i,j,k,PrimQ1_comp) : zero;
282  theta_extrap(i,j,k) *= (one + RvOverRd*qv);
283 
284  // We define lagged_delta_rt for our next step as the current delta_rt
285  lagged(i,j,k) = delta_rt;
286  });
287  } else {
288  // For the moving wave problem, this choice seems more robust
289  ParallelFor(gbx,
290  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
291  theta_extrap(i,j,k) = cur_cons(i,j,k,RhoTheta_comp) - stg_cons(i,j,k,RhoTheta_comp);
292 
293  // NOTE: qv is not changing over the fast steps so we use the stage data
294  Real qv = (l_use_moisture) ? prim(i,j,k,PrimQ1_comp) : zero;
295  theta_extrap(i,j,k) *= (one + RvOverRd*qv);
296  });
297  } // if step
298 
299  RHS_fab.resize (tbz,1, The_Async_Arena());
300  soln_fab.resize (tbz,1, The_Async_Arena());
301  temp_rhs_fab.resize(tbz,2, The_Async_Arena());
302 
303  auto const& RHS_a = RHS_fab.array();
304  auto const& soln_a = soln_fab.array();
305  auto const& temp_rhs_arr = temp_rhs_fab.array();
306 
307  auto const& coeffA_a = coeff_A_mf.array(mfi);
308  auto const& inv_coeffB_a = inv_coeff_B_mf.array(mfi);
309  auto const& coeffC_a = coeff_C_mf.array(mfi);
310  auto const& coeffP_a = coeff_P_mf.array(mfi);
311  auto const& coeffQ_a = coeff_Q_mf.array(mfi);
312  auto const& beta_s_a = beta_s_mf.const_array(mfi);
313 
314  // *********************************************************************
315  // Define updates in the RHS of {x, y, z}-momentum equations
316  // *********************************************************************
317  {
318  BL_PROFILE("substep_xymom_T");
319  ParallelFor(tbx, tby,
320  [=] AMREX_GPU_DEVICE (int i, int j, int k)
321  {
322  // Add (negative) gradient of (rho theta) multiplied by lagged "pi"
323  Real h_xi_old = Compute_h_xi_AtIface(i, j, k, dxInv, z_nd_old);
324  Real h_zeta_old = Compute_h_zeta_AtIface(i, j, k, dxInv, z_nd_old);
325  Real gp_xi = (theta_extrap(i,j,k) - theta_extrap(i-1,j,k)) * dxi;
326  Real gp_zeta_on_iface = (k == 0) ?
327  myhalf * dzi * ( theta_extrap(i-1,j,k+1) + theta_extrap(i,j,k+1)
328  - theta_extrap(i-1,j,k ) - theta_extrap(i,j,k ) ) :
329  fourth * dzi * ( theta_extrap(i-1,j,k+1) + theta_extrap(i,j,k+1)
330  - theta_extrap(i-1,j,k-1) - theta_extrap(i,j,k-1) );
331  Real gpx = h_zeta_old * gp_xi - h_xi_old * gp_zeta_on_iface;
332  gpx *= mf_ux(i,j,0);
333 
334  Real q = (l_use_moisture) ? myhalf * (qt_arr(i-1,j,k) + qt_arr(i,j,k)) : zero;
335 
336  Real pi_c = myhalf * (pi_stage_ca(i-1,j,k) + pi_stage_ca(i ,j,k));
337  Real fast_rhs_rho_u = -Gamma * R_d * pi_c * gpx / (one + q);
338 
339  // We have already scaled the source terms to have the extra factor of dJ
340  cur_xmom(i,j,k) = h_zeta_old * prev_xmom(i,j,k) + dtau * fast_rhs_rho_u
341  + dtau * slow_rhs_rho_u(i,j,k)
342  + dtau * xmom_src_arr(i,j,k);
343  },
344  [=] AMREX_GPU_DEVICE (int i, int j, int k)
345  {
346  // Add (negative) gradient of (rho theta) multiplied by lagged "pi"
347  Real h_eta_old = Compute_h_eta_AtJface(i, j, k, dxInv, z_nd_old);
348  Real h_zeta_old = Compute_h_zeta_AtJface(i, j, k, dxInv, z_nd_old);
349  Real gp_eta = (theta_extrap(i,j,k) -theta_extrap(i,j-1,k)) * dyi;
350  Real gp_zeta_on_jface = (k == 0) ?
351  myhalf * dzi * ( theta_extrap(i,j,k+1) + theta_extrap(i,j-1,k+1)
352  - theta_extrap(i,j,k ) - theta_extrap(i,j-1,k ) ) :
353  fourth * dzi * ( theta_extrap(i,j,k+1) + theta_extrap(i,j-1,k+1)
354  - theta_extrap(i,j,k-1) - theta_extrap(i,j-1,k-1) );
355  Real gpy = h_zeta_old * gp_eta - h_eta_old * gp_zeta_on_jface;
356  gpy *= mf_vy(i,j,0);
357 
358  Real q = (l_use_moisture) ? myhalf * (qt_arr(i,j-1,k) + qt_arr(i,j,k)) : zero;
359 
360  Real pi_c = myhalf * (pi_stage_ca(i,j-1,k) + pi_stage_ca(i,j ,k));
361  Real fast_rhs_rho_v = -Gamma * R_d * pi_c * gpy / (one + q);
362 
363  // We have already scaled the source terms to have the extra factor of dJ
364  cur_ymom(i, j, k) = h_zeta_old * prev_ymom(i,j,k) + dtau * fast_rhs_rho_v
365  + dtau * slow_rhs_rho_v(i,j,k)
366  + dtau * ymom_src_arr(i,j,k);
367  });
368  } // end profile
369 
370  // *************************************************************************
371  // Define flux arrays for use in advection
372  // *************************************************************************
373  for (int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
374  flux[dir].resize(surroundingNodes(bx,dir),2,The_Async_Arena());
375  flux[dir].setVal<RunOn::Device>(0);
376  }
377  const GpuArray<const Array4<Real>, AMREX_SPACEDIM>
378  flx_arr{{AMREX_D_DECL(flux[0].array(), flux[1].array(), flux[2].array())}};
379 
380  // *********************************************************************
381  {
382  BL_PROFILE("fast_T_making_rho_rhs");
383  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
384  {
385  Real h_zeta_stg_xlo = Compute_h_zeta_AtIface(i, j , k, dxInv, z_nd_stg);
386  Real h_zeta_stg_xhi = Compute_h_zeta_AtIface(i+1,j , k, dxInv, z_nd_stg);
387  Real xflux_lo = cur_xmom(i ,j,k) - stg_xmom(i ,j,k)*h_zeta_stg_xlo;
388  Real xflux_hi = cur_xmom(i+1,j,k) - stg_xmom(i+1,j,k)*h_zeta_stg_xhi;
389 
390  Real h_zeta_stg_yhi = Compute_h_zeta_AtJface(i, j+1, k, dxInv, z_nd_stg);
391  Real h_zeta_stg_ylo = Compute_h_zeta_AtJface(i, j , k, dxInv, z_nd_stg);
392  Real yflux_lo = cur_ymom(i,j ,k) - stg_ymom(i,j ,k)*h_zeta_stg_ylo;
393  Real yflux_hi = cur_ymom(i,j+1,k) - stg_ymom(i,j+1,k)*h_zeta_stg_yhi;
394 
395  // NOTE: we are saving the (1/J) weighting for later when we add this to rho and theta
396  temp_rhs_arr(i,j,k,0) = ( xflux_hi - xflux_lo ) * dxi + ( yflux_hi - yflux_lo ) * dyi;
397  temp_rhs_arr(i,j,k,1) = (( xflux_hi * (prim(i,j,k,0) + prim(i+1,j,k,0)) -
398  xflux_lo * (prim(i,j,k,0) + prim(i-1,j,k,0)) ) * dxi +
399  ( yflux_hi * (prim(i,j,k,0) + prim(i,j+1,k,0)) -
400  yflux_lo * (prim(i,j,k,0) + prim(i,j-1,k,0)) ) * dyi) * myhalf;
401 
402  if (l_reflux) {
403  (flx_arr[0])(i,j,k,0) = xflux_lo;
404  (flx_arr[0])(i,j,k,1) = (flx_arr[0])(i ,j,k,0) * myhalf * (prim(i,j,k,0) + prim(i-1,j,k,0));
405 
406  (flx_arr[1])(i,j,k,0) = yflux_lo;
407  (flx_arr[1])(i,j,k,1) = (flx_arr[1])(i,j ,k,0) * myhalf * (prim(i,j,k,0) + prim(i,j-1,k,0));
408 
409  if (i == vbx_hi.x) {
410  (flx_arr[0])(i+1,j,k,0) = xflux_hi;
411  (flx_arr[0])(i+1,j,k,1) = (flx_arr[0])(i+1,j,k,0) * myhalf * (prim(i,j,k,0) + prim(i+1,j,k,0));
412  }
413  if (j == vbx_hi.y) {
414  (flx_arr[1])(i,j+1,k,0) = yflux_hi;
415  (flx_arr[1])(i,j+1,k,1) = (flx_arr[1])(i,j+1,k,0) * myhalf * (prim(i,j,k,0) + prim(i,j+1,k,0));
416  }
417  }
418  });
419  } // end profile
420 
421  ParallelFor(tbx, tby,
422  [=] AMREX_GPU_DEVICE (int i, int j, int k)
423  {
424  Real h_zeta_new = Compute_h_zeta_AtIface(i, j, k, dxInv, z_nd_new);
425  cur_xmom(i, j, k) /= h_zeta_new;
426  avg_xmom_arr(i,j,k) += facinv*(cur_xmom(i,j,k) - stg_xmom(i,j,k));
427  },
428  [=] AMREX_GPU_DEVICE (int i, int j, int k)
429  {
430  Real h_zeta_new = Compute_h_zeta_AtJface(i, j, k, dxInv, z_nd_new);
431  cur_ymom(i, j, k) /= h_zeta_new;
432  avg_ymom_arr(i,j,k) += facinv*(cur_ymom(i,j,k) - stg_ymom(i,j,k));
433  });
434 
435  Box bx_shrunk_in_k = bx;
436  int klo = tbz.smallEnd(2);
437  int khi = tbz.bigEnd(2);
438  bx_shrunk_in_k.setSmall(2,klo+1);
439  bx_shrunk_in_k.setBig(2,khi-1);
440 
441  // Note that the notes use "g" to mean the magnitude of gravity, so it is positive
442  // We set grav_gpu[2] to be the vector component which is negative
443  // We define halfg to match the notes (which is why we take the absolute value)
444  Real halfg = std::abs(myhalf * grav_gpu[2]);
445 
446  {
447  BL_PROFILE("fast_loop_on_shrunk_t");
448  //Note we don't act on the bottom or top boundaries of the domain
449  ParallelFor(bx_shrunk_in_k, [=] AMREX_GPU_DEVICE (int i, int j, int k)
450  {
451  Real dJ_old_kface = myhalf * (detJ_old(i,j,k) + detJ_old(i,j,k-1));
452  Real dJ_new_kface = myhalf * (detJ_new(i,j,k) + detJ_new(i,j,k-1));
453  Real dJ_stg_kface = myhalf * (detJ_stg(i,j,k) + detJ_stg(i,j,k-1));
454 
455  Real coeff_P = coeffP_a(i,j,k);
456  Real coeff_Q = coeffQ_a(i,j,k);
457 
458  Real theta_t_lo = myhalf * ( prim(i,j,k-2,PrimTheta_comp) + prim(i,j,k-1,PrimTheta_comp) );
459  Real theta_t_mid = myhalf * ( prim(i,j,k-1,PrimTheta_comp) + prim(i,j,k ,PrimTheta_comp) );
460  Real theta_t_hi = myhalf * ( prim(i,j,k ,PrimTheta_comp) + prim(i,j,k+1,PrimTheta_comp) );
461 
462  // line 2 last two terms (order dtau)
463  Real R0_tmp = coeff_P * cur_cons(i,j,k ,RhoTheta_comp)
464  + coeff_Q * cur_cons(i,j,k-1,RhoTheta_comp)
465  - coeff_P * stg_cons(i,j,k ,RhoTheta_comp) * (dJ_stg_kface/dJ_old_kface)
466  - coeff_Q * stg_cons(i,j,k-1,RhoTheta_comp) * (dJ_stg_kface/dJ_old_kface)
467  - halfg * ( cur_cons(i,j,k,Rho_comp) + cur_cons(i,j,k-1,Rho_comp) )
468  + halfg * ( stg_cons(i,j,k,Rho_comp) + stg_cons(i,j,k-1,Rho_comp) ) * (dJ_stg_kface/dJ_old_kface);
469 
470  // line 3 residuals (order dtau^2) one <-> beta_2
471  Real R1_tmp = - halfg * ( slow_rhs_cons(i,j,k ,Rho_comp) + slow_rhs_cons(i,j,k-1,Rho_comp))
472  + coeff_P * slow_rhs_cons(i,j,k ,RhoTheta_comp) + coeff_Q * slow_rhs_cons(i,j,k-1,RhoTheta_comp);
473 
474  Real Omega_kp1 = omega_arr(i,j,k+1);
475  Real Omega_k = omega_arr(i,j,k );
476  Real Omega_km1 = omega_arr(i,j,k-1);
477 
478  // Explicit part of the vertical flux on each face is beta_1 * Omega. beta_1 on face k
479  // is factored out, and dbeta_1 is how much larger beta_1 is on the neighbouring faces,
480  // which is exactly zero (so the roundoff is that of a scalar beta_1) for uniform beta_s
481  Real beta_1 = myhalf * (one - beta_s_a(i,j,k));
482  Real dbeta_1_kp1 = myhalf * (one - beta_s_a(i,j,k+1)) - beta_1;
483  Real dbeta_1_km1 = myhalf * (one - beta_s_a(i,j,k-1)) - beta_1;
484 
485  Real detJdiff = (detJ_old(i,j,k) - detJ_old(i,j,k-1)) / (detJ_old(i,j,k)*detJ_old(i,j,k-1));
486 
487  // consolidate lines 4&5 (order dtau^2)
488  R1_tmp += halfg * ( beta_1 * dzi * (Omega_kp1/detJ_old(i,j,k) + detJdiff*Omega_k - Omega_km1/detJ_old(i,j,k-1))
489  + dzi * (dbeta_1_kp1*Omega_kp1/detJ_old(i,j,k) - dbeta_1_km1*Omega_km1/detJ_old(i,j,k-1))
490  + temp_rhs_arr(i,j,k,Rho_comp)/detJ_old(i,j,k) + temp_rhs_arr(i,j,k-1,Rho_comp)/detJ_old(i,j,k-1) );
491 
492  // consolidate lines 6&7 (order dtau^2)
493  R1_tmp += -(
494  coeff_P/detJ_old(i,j,k ) * ( beta_1 * dzi * (Omega_kp1*theta_t_hi - Omega_k*theta_t_mid) + dzi * dbeta_1_kp1*Omega_kp1*theta_t_hi
495  +temp_rhs_arr(i,j,k ,RhoTheta_comp) ) +
496  coeff_Q/detJ_old(i,j,k-1) * ( beta_1 * dzi * (Omega_k*theta_t_mid - Omega_km1*theta_t_lo) - dzi * dbeta_1_km1*Omega_km1*theta_t_lo
497  +temp_rhs_arr(i,j,k-1,RhoTheta_comp) ) );
498 
499  // line 1
500  RHS_a(i,j,k) = prev_zmom(i,j,k) - (dJ_stg_kface/dJ_old_kface) * stg_zmom(i,j,k)
501  + dtau * slow_rhs_rho_w(i,j,k) / dJ_stg_kface
502  + dtau * zmom_src_arr(i,j,k);
503 
504  RHS_a(i,j,k) += dtau * R0_tmp;
505 
506  Real beta_2 = myhalf * (one + beta_s_a(i,j,k));
507  RHS_a(i,j,k) += dtau * dtau*beta_2*R1_tmp;
508 
509  // We cannot use omega_arr here since that was built with old_rho_u and old_rho_v ...
510  Real UppVpp = (dJ_new_kface/dJ_old_kface) * OmegaFromW(i,j,k,0.,cur_xmom,cur_ymom,mf_ux,mf_vy,z_nd_new,dxInv)
511  -(dJ_stg_kface/dJ_old_kface) * OmegaFromW(i,j,k,0.,stg_xmom,stg_ymom,mf_ux,mf_vy,z_nd_stg,dxInv);
512  RHS_a(i,j,k) += UppVpp;
513  });
514  } // end profile
515 
516  Box b2d = tbz; // Copy constructor
517  b2d.setRange(2,0);
518 
519  auto const lo = lbound(bx);
520  auto const hi = ubound(bx);
521 
522  {
523  BL_PROFILE("substep_b2d_loop_t");
524 
525 #ifdef AMREX_USE_GPU
526  ParallelFor(b2d, [=] AMREX_GPU_DEVICE (int i, int j, int)
527  {
528  // Moving terrain
529  Real rho_on_bdy = myhalf * ( prev_cons(i,j,lo.z) + prev_cons(i,j,lo.z-1) );
530  RHS_a(i,j,lo.z) = rho_on_bdy * zp_t_arr(i,j,lo.z);
531 
532  soln_a(i,j,lo.z) = RHS_a(i,j,lo.z) * inv_coeffB_a(i,j,lo.z);
533 
534  // Zero at the domain top: Omega'' = 0 at a wall, and Omega''_top = Omega''_top-1
535  // for outflow, the matrix row set in make_fast_coeffs deciding which
536  RHS_a(i,j,hi.z+1) = (hi.z == domhi_z)
537  ? zero
538  : dtau * (slow_rhs_rho_w(i,j,hi.z+1) + zmom_src_arr(i,j,hi.z+1));
539 
540  for (int k = lo.z+1; k <= hi.z+1; k++) {
541  soln_a(i,j,k) = (RHS_a(i,j,k)-coeffA_a(i,j,k)*soln_a(i,j,k-1)) * inv_coeffB_a(i,j,k);
542  }
543 
544  for (int k = hi.z; k >= lo.z; k--) {
545  soln_a(i,j,k) -= ( coeffC_a(i,j,k) * inv_coeffB_a(i,j,k) ) * soln_a(i,j,k+1);
546  }
547 
548  // We assume that Omega == w at the top boundary and that changes in J there are irrelevant
549  cur_zmom(i,j,hi.z+1) = stg_zmom(i,j,hi.z+1) + soln_a(i,j,hi.z+1);
550  });
551 #else
552  for (int j = lo.y; j <= hi.y; ++j) {
553  AMREX_PRAGMA_SIMD
554  for (int i = lo.x; i <= hi.x; ++i) {
555 
556  Real rho_on_bdy = myhalf * ( prev_cons(i,j,lo.z) + prev_cons(i,j,lo.z-1) );
557  RHS_a(i,j,lo.z) = rho_on_bdy * zp_t_arr(i,j,lo.z);
558 
559  soln_a(i,j,lo.z) = RHS_a(i,j,lo.z) * inv_coeffB_a(i,j,lo.z);
560  }
561  }
562 
563  for (int j = lo.y; j <= hi.y; ++j) {
564  AMREX_PRAGMA_SIMD
565  for (int i = lo.x; i <= hi.x; ++i) {
566  // Zero at the domain top: Omega'' = 0 at a wall, and Omega''_top = Omega''_top-1
567  // for outflow, the matrix row set in make_fast_coeffs deciding which
568  RHS_a(i,j,hi.z+1) = (hi.z == domhi_z)
569  ? zero
570  : dtau * (slow_rhs_rho_w(i,j,hi.z+1) + zmom_src_arr(i,j,hi.z+1));
571  }
572  }
573  for (int k = lo.z+1; k <= hi.z+1; ++k) {
574  for (int j = lo.y; j <= hi.y; ++j) {
575  AMREX_PRAGMA_SIMD
576  for (int i = lo.x; i <= hi.x; ++i) {
577  soln_a(i,j,k) = (RHS_a(i,j,k)-coeffA_a(i,j,k)*soln_a(i,j,k-1)) * inv_coeffB_a(i,j,k);
578  }
579  }
580  }
581  for (int k = hi.z; k >= lo.z; --k) {
582  for (int j = lo.y; j <= hi.y; ++j) {
583  AMREX_PRAGMA_SIMD
584  for (int i = lo.x; i <= hi.x; ++i) {
585  soln_a(i,j,k) -= ( coeffC_a(i,j,k) * inv_coeffB_a(i,j,k) ) * soln_a(i,j,k+1);
586  }
587  }
588  }
589 
590  // We assume that Omega == w at the top boundary and that changes in J there are irrelevant
591  for (int j = lo.y; j <= hi.y; ++j) {
592  AMREX_PRAGMA_SIMD
593  for (int i = lo.x; i <= hi.x; ++i) {
594  cur_zmom(i,j,hi.z+1) = stg_zmom(i,j,hi.z+1) + soln_a(i,j,hi.z+1);
595  }
596  }
597 #endif
598  } // end profile
599 
600  {
601  BL_PROFILE("substep_new_drhow");
602  tbz.setBig(2,hi.z);
603  ParallelFor(tbz, [=] AMREX_GPU_DEVICE (int i, int j, int k)
604  {
605  Real rho_on_face = myhalf * (cur_cons(i,j,k,Rho_comp) + cur_cons(i,j,k-1,Rho_comp));
606 
607  if (k == lo.z) {
608  cur_zmom(i,j,k) = WFromOmega(i,j,k,rho_on_face*(z_t_arr(i,j,k)+zp_t_arr(i,j,k)),
609  cur_xmom,cur_ymom,mf_ux,mf_vy,z_nd_new,dxInv);
610 
611  // We need to set this here because it is used to define zflux_lo below
612  soln_a(i,j,k) = zero;
613 
614  } else {
615 
616  Real UppVpp = WFromOmega(i,j,k,zero,cur_xmom,cur_ymom,mf_ux,mf_vy,z_nd_new,dxInv)
617  - WFromOmega(i,j,k,zero,stg_xmom,stg_ymom,mf_ux,mf_vy,z_nd_stg,dxInv);
618  Real wpp = soln_a(i,j,k) + UppVpp;
619  Real dJ_old_kface = myhalf * (detJ_old(i,j,k) + detJ_old(i,j,k-1));
620  Real dJ_new_kface = myhalf * (detJ_new(i,j,k) + detJ_new(i,j,k-1));
621 
622  cur_zmom(i,j,k) = dJ_old_kface * (stg_zmom(i,j,k) + wpp);
623  cur_zmom(i,j,k) /= dJ_new_kface;
624 
625  soln_a(i,j,k) = OmegaFromW(i,j,k,cur_zmom(i,j,k),cur_xmom,cur_ymom,mf_ux,mf_vy,z_nd_new,dxInv)
626  - OmegaFromW(i,j,k,stg_zmom(i,j,k),stg_xmom,stg_ymom,mf_ux,mf_vy,z_nd_stg,dxInv);
627  soln_a(i,j,k) -= rho_on_face * zp_t_arr(i,j,k);
628  }
629 
630  if (l_rayleigh_impl_for_w && k > 0) {
631  Real damping_coeff = l_damp_coef * dtau * sinesq_stag_d[k];
632  cur_zmom(i,j,k) /= (one + damping_coeff);
633  }
634  });
635  } // end profile
636 
637  // **************************************************************************
638  // Define updates in the RHS of rho and (rho theta)
639  // **************************************************************************
640  {
641  BL_PROFILE("fast_rho_final_update");
642  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
643  {
644  Real zflux_lo = myhalf * (one + beta_s_a(i,j,k )) * soln_a(i,j,k )
645  + myhalf * (one - beta_s_a(i,j,k )) * omega_arr(i,j,k );
646  Real zflux_hi = myhalf * (one + beta_s_a(i,j,k+1)) * soln_a(i,j,k+1)
647  + myhalf * (one - beta_s_a(i,j,k+1)) * omega_arr(i,j,k+1);
648 
649  // Note that in the solve we effectively impose new_drho_w(i,j,vbx_hi.z+1)=0
650  // so we don't update avg_zmom at k=vbx_hi.z+1
651  avg_zmom_arr(i,j,k) += facinv*zflux_lo / (mf_mx(i,j,0) * mf_my(i,j,0));
652  if (l_reflux) {
653  (flx_arr[2])(i,j,k,0) = zflux_lo / (mf_mx(i,j,0) * mf_my(i,j,0));
654  }
655 
656  // Note that the factor of (1/J) in the fast source term is canceled
657  // when we multiply old and new by detJ_old and detJ_new , respectively
658  // We have already scaled the slow source term to have the extra factor of dJ
659  Real fast_rhs_rho = -(temp_rhs_arr(i,j,k,0) + ( zflux_hi - zflux_lo ) * dzi);
660  Real fast_rhs_rhotheta = -( temp_rhs_arr(i,j,k,1) + myhalf *
661  ( zflux_hi * (prim(i,j,k) + prim(i,j,k+1))
662  - zflux_lo * (prim(i,j,k) + prim(i,j,k-1)) ) * dzi );
663 
664  cur_cons(i,j,k,0) *= (detJ_old(i,j,k)/detJ_new(i,j,k));
665  cur_cons(i,j,k,1) *= (detJ_old(i,j,k)/detJ_new(i,j,k));
666 
667  cur_cons(i,j,k,0) += dtau * ( slow_rhs_cons(i,j,k,0) + fast_rhs_rho / detJ_new(i,j,k));
668  cur_cons(i,j,k,1) += dtau * ( slow_rhs_cons(i,j,k,1) + fast_rhs_rhotheta / detJ_new(i,j,k));
669 
670  if (l_reflux) {
671  (flx_arr[2])(i,j,k,1) = (flx_arr[2])(i,j,k,0) * myhalf * (prim(i,j,k) + prim(i,j,k-1));
672  }
673 
674  if (k == vbx_hi.z) {
675  avg_zmom_arr(i,j,k+1) += facinv * zflux_hi / (mf_mx(i,j,0) * mf_my(i,j,0));
676  if (l_reflux) {
677  (flx_arr[2])(i,j,k+1,0) = zflux_hi / (mf_mx(i,j,0) * mf_my(i,j,0));
678  (flx_arr[2])(i,j,k+1,1) = (flx_arr[2])(i,j,k+1,0) * myhalf * (prim(i,j,k) + prim(i,j,k+1));
679  }
680  }
681 
682  // add in source terms for cell-centered conserved variables
683  cur_cons(i,j,k,Rho_comp) += dtau * cc_src_arr(i,j,k,Rho_comp);
684  cur_cons(i,j,k,RhoTheta_comp) += dtau * cc_src_arr(i,j,k,RhoTheta_comp);
685  });
686  } // end profile
687 
688  // We only add to the flux registers in the final RK step
689  if (l_reflux) {
690  int strt_comp_reflux = 0;
691  // For now we don't reflux (rho theta) because it seems to create issues at c/f boundaries
692  int num_comp_reflux = 1;
693  if (level < finest_level) {
694  fr_as_crse->CrseAdd(mfi,
695  {{AMREX_D_DECL(&(flux[0]), &(flux[1]), &(flux[2]))}},
696  dx, dtau, strt_comp_reflux, strt_comp_reflux, num_comp_reflux, RunOn::Device);
697  }
698  if (level > 0) {
699  fr_as_fine->FineAdd(mfi,
700  {{AMREX_D_DECL(&(flux[0]), &(flux[1]), &(flux[2]))}},
701  dx, dtau, strt_comp_reflux, strt_comp_reflux, num_comp_reflux, RunOn::Device);
702  }
703 
704  // This is necessary here so we don't go on to the next FArrayBox without
705  // having finished copying the fluxes into the FluxRegisters (since the fluxes
706  // are stored in temporary FArrayBox's)
707  Gpu::streamSynchronize();
708 
709  } // two-way coupling
710 
711  } // mfi
712  } // OMP
713 }
constexpr amrex::Real R_v
Definition: ERF_Constants.H:50
constexpr amrex::Real R_d
Definition: ERF_Constants.H:49
constexpr amrex::Real Gamma
Definition: ERF_Constants.H:70
@ v_y
Definition: ERF_DataStruct.H:39
@ m_y
Definition: ERF_DataStruct.H:39
@ u_x
Definition: ERF_DataStruct.H:38
@ m_x
Definition: ERF_DataStruct.H:38
#define PrimQ1_comp
Definition: ERF_IndexDefines.H:82
#define Rho_comp
Definition: ERF_IndexDefines.H:53
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
#define PrimTheta_comp
Definition: ERF_IndexDefines.H:79
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
const int khi
Definition: ERF_InitCustomPert_Bubble.H:25
const int klo
Definition: ERF_InitCustomPert_KE.H:9
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
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
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real OmegaFromW(int &i, int &j, int &k, amrex::Real w, const amrex::Array4< const amrex::Real > &u_arr, const amrex::Array4< const amrex::Real > &v_arr, const amrex::Array4< const amrex::Real > &mf_u, const amrex::Array4< const amrex::Real > &mf_v, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv)
Definition: ERF_TerrainMetrics.H:802
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtJface(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:396
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtIface(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:280
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtJface(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:350
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtIface(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:303
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real WFromOmega(int &i, int &j, int &k, amrex::Real omega, const amrex::Array4< const amrex::Real > &u_arr, const amrex::Array4< const amrex::Real > &v_arr, const amrex::Array4< const amrex::Real > &mf_u, const amrex::Array4< const amrex::Real > &mf_v, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv)
Definition: ERF_TerrainMetrics.H:867
@ gpy
Definition: ERF_IndexDefines.H:265
@ gpx
Definition: ERF_IndexDefines.H:264
@ ymom
Definition: ERF_IndexDefines.H:274
@ cons
Definition: ERF_IndexDefines.H:272
@ zmom
Definition: ERF_IndexDefines.H:275
@ xmom
Definition: ERF_IndexDefines.H:273
@ qt
Definition: ERF_Kessler.H:30
@ qv
Definition: ERF_Kessler.H:31
@ q
Definition: ERF_WSM6.H:294
Here is the call graph for this function: