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

Functions

void erf_substep_NS (int step, int nrk, int level, int finest_level, Vector< MultiFab > &S_slow_rhs, const Vector< MultiFab > &S_prev, Vector< MultiFab > &S_stage_data, const MultiFab &S_stage_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, amrex::Gpu::DeviceVector< amrex::Real > &stretched_dz_d, 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 l_real_bc, const amrex::Real *sinesq_stag_d, const Real l_damp_coef, const Real beta_d, const CFFaceFluxes &cf_fluxes)
 

Function Documentation

◆ erf_substep_NS()

void erf_substep_NS ( int  step,
int  nrk,
int  level,
int  finest_level,
Vector< MultiFab > &  S_slow_rhs,
const Vector< MultiFab > &  S_prev,
Vector< MultiFab > &  S_stage_data,
const MultiFab &  S_stage_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,
amrex::Gpu::DeviceVector< amrex::Real > &  stretched_dz_d,
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  l_real_bc,
const amrex::Real *  sinesq_stag_d,
const Real  l_damp_coef,
const Real  beta_d,
const CFFaceFluxes &  cf_fluxes 
)

Function for computing the fast RHS with no terrain and variable vertical spacing

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_previf step == 0, this is S_old, else the previous fast solution
[in]S_stage_datasolution at previous RK stage
[in]S_stage_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]stretched_dz_d
[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_real_bc
[in,out]cf_fluxescoarse/fine face fluxes: recorded here on a coarse level, imposed on a fine one
78 {
79  //
80  // NOTE: for step > 0, S_data and S_prev point to the same MultiFab data!!
81  //
82 
83  BL_PROFILE_REGION("erf_substep_NS()");
84 
85  Real dtau = static_cast<Real>(dtau_d);
86 
87  const Box& domain = geom.Domain();
88  auto const domlo = lbound(domain);
89  auto const domhi = ubound(domain);
90 
91  int ilo = domlo.x;
92  int ihi = domhi.x + 1;
93  int jlo = domlo.y;
94  int jhi = domhi.y + 1;
95 
96  bool l_rayleigh_impl_for_w = (sinesq_stag_d != nullptr);
97 
98  const Real* dx = geom.CellSize();
99  const GpuArray<Real, AMREX_SPACEDIM> dxInv = geom.InvCellSizeArray();
100 
101  Real dxi = dxInv[0];
102  Real dyi = dxInv[1];
103  Real dzi = dxInv[2];
104 
105  auto dz_ptr = stretched_dz_d.data();
106 
107  const auto& ba = S_stage_data[IntVars::cons].boxArray();
108  const auto& dm = S_stage_data[IntVars::cons].DistributionMap();
109 
110  MultiFab Delta_rho_theta( ba , dm, 1, 1);
111  MultiFab Delta_rho_w (convert(ba,IntVect(0,0,1)), dm, 1, IntVect(1,1,0));
112 
113  MultiFab coeff_A_mf(fast_coeffs, make_alias, 0, 1);
114  MultiFab inv_coeff_B_mf(fast_coeffs, make_alias, 1, 1);
115  MultiFab coeff_C_mf(fast_coeffs, make_alias, 2, 1);
116  MultiFab coeff_P_mf(fast_coeffs, make_alias, 3, 1);
117  MultiFab coeff_Q_mf(fast_coeffs, make_alias, 4, 1);
118 
119  // beta_s on the w-faces, from which
120  // beta_1 = myhalf * (one - beta_s) multiplies explicit terms
121  // beta_2 = myhalf * (one + beta_s) multiplies implicit terms
122  MultiFab beta_s_mf(fast_coeffs, make_alias, 5, 1);
123 
124  // *************************************************************************
125  // Set gravity as a vector
126  const Array<Real,AMREX_SPACEDIM> grav{zero, zero, -gravity};
127  const GpuArray<Real,AMREX_SPACEDIM> grav_gpu{grav[0], grav[1], grav[2]};
128 
129  // This will hold theta extrapolated forward in time
130  MultiFab extrap(S_data[IntVars::cons].boxArray(),S_data[IntVars::cons].DistributionMap(),1,1);
131 
132  // This will hold the update for (rho) and (rho theta)
133  MultiFab temp_rhs(S_stage_data[IntVars::zmom].boxArray(),S_stage_data[IntVars::zmom].DistributionMap(),2,0);
134 
135  // This will hold the new x- and y-momenta temporarily (so that we don't overwrite values we need when tiling)
136  MultiFab temp_cur_xmom(S_stage_data[IntVars::xmom].boxArray(),S_stage_data[IntVars::xmom].DistributionMap(),1,0);
137  MultiFab temp_cur_ymom(S_stage_data[IntVars::ymom].boxArray(),S_stage_data[IntVars::ymom].DistributionMap(),1,0);
138 
139  // We assume that in the first step (nrk == 0) we are only doing one substep.
140  AMREX_ALWAYS_ASSERT(nrk > 0 || step == 0);
141 
142  // *************************************************************************
143  // First set up some arrays we'll need
144  // *************************************************************************
145 
146 #ifdef _OPENMP
147 #pragma omp parallel if (Gpu::notInLaunchRegion())
148 #endif
149  for ( MFIter mfi(S_stage_data[IntVars::cons],TilingIfNotGPU()); mfi.isValid(); ++mfi)
150  {
151  const Array4<const Real>& prev_cons = S_prev[IntVars::cons].const_array(mfi);
152  const Array4<const Real>& prev_zmom = S_prev[IntVars::zmom].const_array(mfi);
153 
154  const Array4<const Real>& stage_cons = S_stage_data[IntVars::cons].const_array(mfi);
155  const Array4<const Real>& stage_zmom = S_stage_data[IntVars::zmom].const_array(mfi);
156 
157  const Array4<Real>& prev_drho_w = Delta_rho_w.array(mfi);
158  const Array4<Real>& prev_drho_theta = Delta_rho_theta.array(mfi);
159  const Array4<Real>& lagged_arr = lagged_delta_rt.array(mfi);
160  const Array4<Real>& theta_extrap = extrap.array(mfi);
161  const Array4<const Real>& prim = S_stage_prim.const_array(mfi);
162 
163  Box gbx = mfi.growntilebox(1);
164  ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
165  {
166  prev_drho_theta(i,j,k) = prev_cons(i,j,k,RhoTheta_comp) - stage_cons(i,j,k,RhoTheta_comp);
167 
168  if (step == 0) {
169  theta_extrap(i,j,k) = prev_drho_theta(i,j,k);
170  } else {
171  theta_extrap(i,j,k) = prev_drho_theta(i,j,k) + beta_d *
172  ( prev_drho_theta(i,j,k) - lagged_arr(i,j,k) );
173  }
174 
175  // NOTE: qv is not changing over the fast steps so we use the stage data
176  Real qv = (l_use_moisture) ? prim(i,j,k,PrimQ1_comp) : zero;
177  theta_extrap(i,j,k) *= (one + RvoRd*qv);
178 
179  // We define lagged_delta_rt for our next step as the current delta_rt
180  // (after using it above to extrapolate theta for this step)
181  lagged_arr(i,j,k) = prev_drho_theta(i,j,k);
182  });
183 
184  // NOTE: We must do this here because for step > 0, prev_zmom and cur_zmom both point to the same data,
185  // so by the time we would use prev_zmom to define zflux, it would have already been over-written.
186  //
187  // NOTE: grownnodaltilebox, not nodaltilebox(2) grown by hand. Growing by hand pushes
188  // every tile one cell past its own share of the grid in x and y, so once the grid
189  // is tiled two tiles write the same Delta_rho_w cells -- a data race under OpenMP,
190  // even though both store the same value. This is identical to the old expression
191  // when there is one tile per grid.
192  //
193  Box gtbz = mfi.grownnodaltilebox(2,IntVect(1,1,0));
194  ParallelFor(gtbz, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
195  prev_drho_w(i,j,k) = prev_zmom(i,j,k) - stage_zmom(i,j,k);
196  });
197  } // mfi
198 
199  // *************************************************************************
200  // Define updates in the current RK stage
201  // *************************************************************************
202 
203 #ifdef _OPENMP
204 #pragma omp parallel if (Gpu::notInLaunchRegion())
205 #endif
206  for ( MFIter mfi(S_stage_data[IntVars::cons],TilingIfNotGPU()); mfi.isValid(); ++mfi)
207  {
208  Box tbx = mfi.nodaltilebox(0);
209  Box tby = mfi.nodaltilebox(1);
210 
211  const Array4<Real const>& xmom_src_arr = xmom_src.const_array(mfi);
212  const Array4<Real const>& ymom_src_arr = ymom_src.const_array(mfi);
213 
214  const Array4<const Real> & stage_xmom = S_stage_data[IntVars::xmom].const_array(mfi);
215  const Array4<const Real> & stage_ymom = S_stage_data[IntVars::ymom].const_array(mfi);
216  const Array4<const Real> & qt_arr = qt.const_array(mfi);
217 
218  const Array4<const Real>& slow_rhs_rho_u = S_slow_rhs[IntVars::xmom].const_array(mfi);
219  const Array4<const Real>& slow_rhs_rho_v = S_slow_rhs[IntVars::ymom].const_array(mfi);
220 
221  const Array4<Real>& temp_cur_xmom_arr = temp_cur_xmom.array(mfi);
222  const Array4<Real>& temp_cur_ymom_arr = temp_cur_ymom.array(mfi);
223 
224  const Array4<const Real>& prev_xmom = S_prev[IntVars::xmom].const_array(mfi);
225  const Array4<const Real>& prev_ymom = S_prev[IntVars::ymom].const_array(mfi);
226 
227  // These store the advection momenta which we will use to update the slow variables
228  const Array4< Real>& avg_xmom_arr = avg_xmom.array(mfi);
229  const Array4< Real>& avg_ymom_arr = avg_ymom.array(mfi);
230 
231  const Array4<const Real>& pi_stage_ca = pi_stage.const_array(mfi);
232 
233  const Array4<Real>& theta_extrap = extrap.array(mfi);
234 
235  // Map factors
236  const Array4<const Real>& mf_ux = mapfac[MapFacType::u_x]->const_array(mfi);
237  const Array4<const Real>& mf_uy = mapfac[MapFacType::u_y]->const_array(mfi);
238  const Array4<const Real>& mf_vx = mapfac[MapFacType::v_x]->const_array(mfi);
239  const Array4<const Real>& mf_vy = mapfac[MapFacType::v_y]->const_array(mfi);
240 
241  // *********************************************************************
242  // Define updates in the RHS of {x, y, z}-momentum equations
243  //
244  // NOTE: avg_{x,y}mom is a *flux* that is later handed to the scalar
245  // advection in erf_slow_rhs_post, which applies (mfsq/detJ) to its
246  // divergence. So what we accumulate here must be in the same
247  // convention as the base value set in AdvectionSrcForRho, namely
248  // ax*rho_u/mf_uy (and ay*rho_v/mf_vx). Two weightings are needed:
249  //
250  // (1) the map factor, matching the density fluxes formed below;
251  //
252  // (2) h_zeta = ax = detJ, which for this (laterally homogeneous)
253  // mesh is just dz_ptr[k]/dz. Note this factor cancels out of
254  // the rho update we do here -- temp_rhs uses a bare dxi and no
255  // 1/detJ -- but it does NOT cancel for avg_{x,y}mom, because
256  // the consumer downstream re-applies the 1/detJ that we never
257  // applied. It is identically 1 for MeshType::ConstantDz.
258  // *********************************************************************
259  if (nrk == 0 and step == 0) { // prev == stage
260  ParallelFor(tbx, tby,
261  [=] AMREX_GPU_DEVICE (int i, int j, int k)
262  {
263  Real h_zeta = dz_ptr[k] * dzi;
264  Real new_drho_u = dtau * slow_rhs_rho_u(i,j,k) + dtau * xmom_src_arr(i,j,k);;
265  avg_xmom_arr(i,j,k) += facinv * new_drho_u * h_zeta / mf_uy(i,j,0);
266  temp_cur_xmom_arr(i,j,k) = stage_xmom(i,j,k) + new_drho_u;
267  },
268  [=] AMREX_GPU_DEVICE (int i, int j, int k)
269  {
270  Real h_zeta = dz_ptr[k] * dzi;
271  Real new_drho_v = dtau * slow_rhs_rho_v(i,j,k) + dtau * ymom_src_arr(i,j,k);
272  avg_ymom_arr(i,j,k) += facinv * new_drho_v * h_zeta / mf_vx(i,j,0);
273  temp_cur_ymom_arr(i,j,k) = stage_ymom(i,j,k) + new_drho_v;
274  });
275  } else {
276  ParallelFor(tbx, tby,
277  [=] AMREX_GPU_DEVICE (int i, int j, int k)
278  {
279  // Add (negative) gradient of (rho theta) multiplied by lagged "pi"
280  Real gpx = (l_real_bc && (level==0) && (i==ilo || i==ihi)) ? Real(0.) :
281  (theta_extrap(i,j,k) - theta_extrap(i-1,j,k))*dxi;
282  gpx *= mf_ux(i,j,0);
283 
284  Real q = (l_use_moisture) ? myhalf * (qt_arr(i,j,k) + qt_arr(i-1,j,k)) : zero;
285 
286  Real pi_c = myhalf * (pi_stage_ca(i-1,j,k,0) + pi_stage_ca(i,j,k,0));
287  Real fast_rhs_rho_u = -Gamma * R_d * pi_c * gpx / (one + q);
288 
289  Real new_drho_u = prev_xmom(i,j,k) - stage_xmom(i,j,k)
290  + dtau * fast_rhs_rho_u + dtau * slow_rhs_rho_u(i,j,k)
291  + dtau * xmom_src_arr(i,j,k);
292 
293  Real h_zeta = dz_ptr[k] * dzi;
294  avg_xmom_arr(i,j,k) += facinv * new_drho_u * h_zeta / mf_uy(i,j,0);
295 
296  temp_cur_xmom_arr(i,j,k) = stage_xmom(i,j,k) + new_drho_u;
297  },
298  [=] AMREX_GPU_DEVICE (int i, int j, int k)
299  {
300  // Add (negative) gradient of (rho theta) multiplied by lagged "pi"
301  Real gpy = (l_real_bc && (level==0) && (j==jlo || j==jhi)) ? Real(0.) :
302  (theta_extrap(i,j,k) - theta_extrap(i,j-1,k))*dyi;
303  gpy *= mf_vy(i,j,0);
304 
305  Real q = (l_use_moisture) ? myhalf * (qt_arr(i,j,k) + qt_arr(i,j-1,k)) : zero;
306 
307  Real pi_c = myhalf * (pi_stage_ca(i,j-1,k,0) + pi_stage_ca(i,j,k,0));
308  Real fast_rhs_rho_v = -Gamma * R_d * pi_c * gpy / (one + q);
309 
310  Real new_drho_v = prev_ymom(i,j,k) - stage_ymom(i,j,k)
311  + dtau * fast_rhs_rho_v + dtau * slow_rhs_rho_v(i,j,k)
312  + dtau * ymom_src_arr(i,j,k);
313 
314  Real h_zeta = dz_ptr[k] * dzi;
315  avg_ymom_arr(i,j,k) += facinv * new_drho_v * h_zeta / mf_vx(i,j,0);
316 
317  temp_cur_ymom_arr(i,j,k) = stage_ymom(i,j,k) + new_drho_v;
318  });
319  } // nrk > 0 and/or step > 0
320 
321  // On the coarse/fine faces of a fine level, the coarse level's flux over this substep
322  // (CFFaceFluxes) in place of the level's own
323  for (int dir = 0; dir < 2; ++dir) {
324  if (!cf_fluxes.tgt[dir]) { continue; }
325  const Box& fbx = (dir == 0) ? tbx : tby;
326  const Array4<const Real>& tgt = cf_fluxes.tgt[dir]->const_array(mfi);
327  const Array4<Real>& cur = (dir == 0) ? temp_cur_xmom_arr : temp_cur_ymom_arr;
328  const Array4<Real>& avg = (dir == 0) ? avg_xmom_arr : avg_ymom_arr;
329  const Array4<const Real>& mf = (dir == 0) ? mf_uy : mf_vx;
330  ParallelFor(fbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
331  {
332  if (tgt(i,j,k,1) > myhalf) {
333  Real new_mom = tgt(i,j,k,0) * mf(i,j,0);
334  Real h_zeta = dz_ptr[k] * dzi;
335  avg(i,j,k) += facinv * (new_mom - cur(i,j,k)) * h_zeta / mf(i,j,0);
336  cur(i,j,k) = new_mom;
337  }
338  });
339  }
340 
341  // On a coarse level, the flux each face applied over this substep
342  for (int dir = 0; dir < 2; ++dir) {
343  if (!cf_fluxes.rec[dir]) { continue; }
344  const Box& fbx = (dir == 0) ? tbx : tby;
345  const Array4<Real>& rec = cf_fluxes.rec[dir]->array(mfi);
346  const Array4<const Real>& cur = (dir == 0) ? temp_cur_xmom_arr : temp_cur_ymom_arr;
347  const Array4<const Real>& mf = (dir == 0) ? mf_uy : mf_vx;
348  ParallelFor(fbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
349  {
350  rec(i,j,k) = cur(i,j,k) / mf(i,j,0);
351  });
352  }
353  } //mfi
354 
355 #ifdef _OPENMP
356 #pragma omp parallel if (Gpu::notInLaunchRegion())
357 #endif
358  {
359  std::array<FArrayBox,AMREX_SPACEDIM> flux;
360  for ( MFIter mfi(S_stage_data[IntVars::cons],TileNoZ()); mfi.isValid(); ++mfi)
361  {
362  Box bx = mfi.tilebox();
363  Box tbz = surroundingNodes(bx,2);
364 
365  Box vbx = mfi.validbox();
366  const auto& vbx_hi = ubound(vbx);
367 
368  const Array4<Real const>& zmom_src_arr = zmom_src.const_array(mfi);
369 
370  const Array4<const Real>& stage_xmom = S_stage_data[IntVars::xmom].const_array(mfi);
371  const Array4<const Real>& stage_ymom = S_stage_data[IntVars::ymom].const_array(mfi);
372  const Array4<const Real>& stage_zmom = S_stage_data[IntVars::zmom].const_array(mfi);
373  const Array4<const Real> & prim = S_stage_prim.const_array(mfi);
374 
375  const Array4<const Real>& prev_drho_theta = Delta_rho_theta.array(mfi);
376 
377  const Array4<const Real>& prev_cons = S_prev[IntVars::cons].const_array(mfi);
378  const Array4<const Real>& stage_cons = S_stage_data[IntVars::cons].const_array(mfi);
379 
380  const Array4<const Real>& slow_rhs_cons = S_slow_rhs[IntVars::cons].const_array(mfi);
381  const Array4<const Real>& slow_rhs_rho_w = S_slow_rhs[IntVars::zmom].const_array(mfi);
382 
383  const Array4<const Real>& prev_zmom = S_prev[IntVars::zmom].const_array(mfi);
384  const Array4< Real>& cur_zmom = S_data[IntVars::zmom].array(mfi);
385 
386  const Array4<Real>& temp_cur_xmom_arr = temp_cur_xmom.array(mfi);
387  const Array4<Real>& temp_cur_ymom_arr = temp_cur_ymom.array(mfi);
388 
389  // These store the advection momenta which we will use to update the slow variables
390  const Array4< Real>& avg_zmom_arr = avg_zmom.array(mfi);
391 
392  // Map factors
393  const Array4<const Real>& mf_mx = mapfac[MapFacType::m_x]->const_array(mfi);
394  const Array4<const Real>& mf_my = mapfac[MapFacType::m_y]->const_array(mfi);
395  const Array4<const Real>& mf_uy = mapfac[MapFacType::u_y]->const_array(mfi);
396  const Array4<const Real>& mf_vx = mapfac[MapFacType::v_x]->const_array(mfi);
397 
398  FArrayBox RHS_fab;
399  RHS_fab.resize(tbz,1, The_Async_Arena());
400 
401  FArrayBox soln_fab;
402  soln_fab.resize(tbz,1, The_Async_Arena());
403 
404  auto const& RHS_a = RHS_fab.array();
405  auto const& soln_a = soln_fab.array();
406 
407  auto const& temp_rhs_arr = temp_rhs.array(mfi);
408 
409  auto const& coeffA_a = coeff_A_mf.array(mfi);
410  auto const& inv_coeffB_a = inv_coeff_B_mf.array(mfi);
411  auto const& coeffC_a = coeff_C_mf.array(mfi);
412  auto const& coeffP_a = coeff_P_mf.array(mfi);
413  auto const& coeffQ_a = coeff_Q_mf.array(mfi);
414  auto const& beta_s_a = beta_s_mf.const_array(mfi);
415 
416  // *************************************************************************
417  // Define flux arrays for use in advection
418  // *************************************************************************
419  for (int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
420  flux[dir].resize(surroundingNodes(bx,dir),2,The_Async_Arena());
421  flux[dir].setVal<RunOn::Device>(0);
422  }
423  const GpuArray<const Array4<Real>, AMREX_SPACEDIM>
424  flx_arr{{AMREX_D_DECL(flux[0].array(), flux[1].array(), flux[2].array())}};
425 
426  // *********************************************************************
427  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
428  Real xflux_lo = (temp_cur_xmom_arr(i ,j,k) - stage_xmom(i ,j,k)) / mf_uy(i ,j,0);
429  Real xflux_hi = (temp_cur_xmom_arr(i+1,j,k) - stage_xmom(i+1,j,k)) / mf_uy(i+1,j,0);
430  Real yflux_lo = (temp_cur_ymom_arr(i,j ,k) - stage_ymom(i,j ,k)) / mf_vx(i,j ,0);
431  Real yflux_hi = (temp_cur_ymom_arr(i,j+1,k) - stage_ymom(i,j+1,k)) / mf_vx(i,j+1,0);
432 
433  Real mfsq = mf_mx(i,j,0) * mf_my(i,j,0);
434 
435  temp_rhs_arr(i,j,k,Rho_comp ) = ( xflux_hi - xflux_lo ) * dxi * mfsq
436  + ( yflux_hi - yflux_lo ) * dyi * mfsq;
437  temp_rhs_arr(i,j,k,RhoTheta_comp) = (( xflux_hi * (prim(i,j,k,0) + prim(i+1,j,k,0)) -
438  xflux_lo * (prim(i,j,k,0) + prim(i-1,j,k,0)) ) * dxi * mfsq +
439  ( yflux_hi * (prim(i,j,k,0) + prim(i,j+1,k,0)) -
440  yflux_lo * (prim(i,j,k,0) + prim(i,j-1,k,0)) ) * dyi * mfsq) * myhalf;
441 
442  if (l_reflux) {
443  (flx_arr[0])(i,j,k,0) = xflux_lo;
444  (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));
445 
446  (flx_arr[1])(i,j,k,0) = yflux_lo;
447  (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));
448 
449  if (i == vbx_hi.x) {
450  (flx_arr[0])(i+1,j,k,0) = xflux_hi;
451  (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));
452  }
453  if (j == vbx_hi.y) {
454  (flx_arr[1])(i,j+1,k,0) = yflux_hi;
455  (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));
456  }
457  }
458  });
459 
460  Box bx_shrunk_in_k = bx;
461  int klo = tbz.smallEnd(2);
462  int khi = tbz.bigEnd(2);
463  bx_shrunk_in_k.setSmall(2,klo+1);
464  bx_shrunk_in_k.setBig(2,khi-1);
465 
466  // Note that the notes use "g" to mean the magnitude of gravity, so it is positive
467  // We set grav_gpu[2] to be the vector component which is negative
468  // We define halfg to match the notes (which is why we take the absolute value)
469  Real halfg = std::abs(myhalf * grav_gpu[2]);
470 
471  // *********************************************************************
472  // fast_loop_on_shrunk
473  // *********************************************************************
474  //Note we don't act on the bottom or top boundaries of the domain
475  ParallelFor(bx_shrunk_in_k, [=] AMREX_GPU_DEVICE (int i, int j, int k)
476  {
477  Real coeff_P = coeffP_a(i,j,k);
478  Real coeff_Q = coeffQ_a(i,j,k);
479 
480  Real theta_t_lo = myhalf * ( prim(i,j,k-2,PrimTheta_comp) + prim(i,j,k-1,PrimTheta_comp) );
481  Real theta_t_mid = myhalf * ( prim(i,j,k-1,PrimTheta_comp) + prim(i,j,k ,PrimTheta_comp) );
482  Real theta_t_hi = myhalf * ( prim(i,j,k ,PrimTheta_comp) + prim(i,j,k+1,PrimTheta_comp) );
483 
484  Real Omega_kp1 = prev_zmom(i,j,k+1) - stage_zmom(i,j,k+1);
485  Real Omega_k = prev_zmom(i,j,k ) - stage_zmom(i,j,k );
486  Real Omega_km1 = prev_zmom(i,j,k-1) - stage_zmom(i,j,k-1);
487 
488  // line 2 last two terms (order dtau)
489  Real old_drho_k = prev_cons(i,j,k ,Rho_comp) - stage_cons(i,j,k ,Rho_comp);
490  Real old_drho_km1 = prev_cons(i,j,k-1,Rho_comp) - stage_cons(i,j,k-1,Rho_comp);
491  Real R0_tmp = coeff_P * prev_drho_theta(i,j,k) + coeff_Q * prev_drho_theta(i,j,k-1)
492  - halfg * ( old_drho_k + old_drho_km1 );
493 
494  // lines 3-5 residuals (order dtau^2) one <-> beta_2
495  Real R1_tmp = halfg * (-slow_rhs_cons(i,j,k ,Rho_comp) - slow_rhs_cons(i,j,k-1,Rho_comp)
496  + temp_rhs_arr(i,j,k ,Rho_comp) + temp_rhs_arr(i,j,k-1,Rho_comp) )
497  + ( coeff_P * (slow_rhs_cons(i,j,k ,RhoTheta_comp) - temp_rhs_arr(i,j,k ,RhoTheta_comp)) +
498  coeff_Q * (slow_rhs_cons(i,j,k-1,RhoTheta_comp) - temp_rhs_arr(i,j,k-1,RhoTheta_comp)) );
499 
500  // Explicit part of the vertical flux on each face is beta_1 * Omega. beta_1 on face k
501  // is factored out, and dbeta_1 is how much larger beta_1 is on the neighbouring faces,
502  // which is exactly zero (so the roundoff is that of a scalar beta_1) for uniform beta_s
503  Real beta_1 = myhalf * (one - beta_s_a(i,j,k));
504  Real dbeta_1_kp1 = myhalf * (one - beta_s_a(i,j,k+1)) - beta_1;
505  Real dbeta_1_km1 = myhalf * (one - beta_s_a(i,j,k-1)) - beta_1;
506 
507  // lines 6&7 consolidated (reuse Omega & metrics) (order dtau^2)
508  R1_tmp += beta_1 * ( ( (Omega_kp1 - Omega_k) / dz_ptr[k] + (Omega_k - Omega_km1) / dz_ptr[k-1] ) * halfg
509  +(-(Omega_kp1*theta_t_hi - Omega_k *theta_t_mid) * coeff_P / dz_ptr[k]
510  -(Omega_k *theta_t_mid - Omega_km1*theta_t_lo ) * coeff_Q / dz_ptr[k-1]) )
511  + ( ( dbeta_1_kp1*Omega_kp1 / dz_ptr[k] - dbeta_1_km1*Omega_km1 / dz_ptr[k-1] ) * halfg
512  - dbeta_1_kp1*Omega_kp1*theta_t_hi * coeff_P / dz_ptr[k]
513  + dbeta_1_km1*Omega_km1*theta_t_lo * coeff_Q / dz_ptr[k-1] );
514 
515  // line 1
516  Real beta_2 = myhalf * (one + beta_s_a(i,j,k));
517  RHS_a(i,j,k) = Omega_k + dtau * (slow_rhs_rho_w(i,j,k) + R0_tmp + dtau * beta_2 * R1_tmp + zmom_src_arr(i,j,k));
518 
519  }); // bx_shrunk_in_k
520 
521  Box b2d = tbz;
522  b2d.setRange(2,0);
523 
524  auto const lo = lbound(bx);
525  auto const hi = ubound(bx);
526 
527  ParallelFor(b2d, [=] AMREX_GPU_DEVICE (int i, int j, int)
528  {
529  // NOTE: RHS is built on a shrunk box in z, explicitly set
530  // the lo and hi faces here
531  // On a box face inside the domain (a c/f face), w = w_old + dtau * slow_rhs.
532  // At the domain bottom and top the row is zero: W'' = 0 at the ground and at
533  // a wall, and W''_top = W''_top-1 for outflow, the matrix row set in
534  // make_fast_coeffs deciding which
535  RHS_a (i,j,lo.z) = (lo.z == domlo.z)
536  ? zero
537  : prev_zmom(i,j,lo.z) - stage_zmom(i,j,lo.z)
538  + dtau * slow_rhs_rho_w(i,j,lo.z)
539  + dtau * zmom_src_arr(i,j,lo.z);
540 
541  RHS_a (i,j,hi.z+1) = (hi.z == domhi.z)
542  ? zero
543  : prev_zmom(i,j,hi.z+1) - stage_zmom(i,j,hi.z+1)
544  + dtau * slow_rhs_rho_w(i,j,hi.z+1)
545  + dtau * zmom_src_arr(i,j,hi.z+1);
546  }); // b2d
547 
548  // (rho w) on the coarse/fine faces of a fine level at the end of this substep, from the coarse level
549  if (cf_fluxes.tgt_w) {
550  const Array4<const Real>& tgt = cf_fluxes.tgt[2]->const_array(mfi);
551  const Array4<const Real>& tgt_w = cf_fluxes.tgt_w->const_array(mfi);
552  ParallelFor(b2d, [=] AMREX_GPU_DEVICE (int i, int j, int)
553  {
554  if (tgt(i,j,lo.z,1) > myhalf) {
555  RHS_a(i,j,lo.z) = tgt_w(i,j,lo.z) - stage_zmom(i,j,lo.z);
556  }
557  if (tgt(i,j,hi.z+1,1) > myhalf) {
558  RHS_a(i,j,hi.z+1) = tgt_w(i,j,hi.z+1) - stage_zmom(i,j,hi.z+1);
559  }
560  });
561  }
562 
563 #ifdef AMREX_USE_GPU
564  ParallelFor(b2d, [=] AMREX_GPU_DEVICE (int i, int j, int)
565  {
566  // Dirichlet condition at k = lo.z
567  soln_a(i,j,lo.z) = RHS_a(i,j,lo.z) * inv_coeffB_a(i,j,lo.z);
568  cur_zmom(i,j,lo.z) = stage_zmom(i,j,lo.z) + soln_a(i,j,lo.z);
569 
570  for (int k = lo.z+1; k <= hi.z+1; k++) {
571  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);
572  }
573 
574  cur_zmom(i,j,hi.z+1) = stage_zmom(i,j,hi.z+1) + soln_a(i,j,hi.z+1);
575 
576  for (int k = hi.z; k >= lo.z; k--) {
577  soln_a(i,j,k) -= ( coeffC_a(i,j,k) * inv_coeffB_a(i,j,k) ) *soln_a(i,j,k+1);
578  cur_zmom(i,j,k) = stage_zmom(i,j,k) + soln_a(i,j,k);
579  }
580  }); // b2d
581 #else
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,lo.z) = RHS_a(i,j,lo.z) * inv_coeffB_a(i,j,lo.z);
586  }
587  }
588  for (int k = lo.z+1; k <= hi.z+1; ++k) {
589  for (int j = lo.y; j <= hi.y; ++j) {
590  AMREX_PRAGMA_SIMD
591  for (int i = lo.x; i <= hi.x; ++i) {
592  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);
593  }
594  }
595  }
596  for (int j = lo.y; j <= hi.y; ++j) {
597  AMREX_PRAGMA_SIMD
598  for (int i = lo.x; i <= hi.x; ++i) {
599  cur_zmom(i,j,hi.z+1) = stage_zmom(i,j,hi.z+1) + soln_a(i,j,hi.z+1);
600  }
601  }
602  for (int k = hi.z; k >= lo.z; --k) {
603  for (int j = lo.y; j <= hi.y; ++j) {
604  AMREX_PRAGMA_SIMD
605  for (int i = lo.x; i <= hi.x; ++i) {
606  soln_a(i,j,k) -= ( coeffC_a(i,j,k) * inv_coeffB_a(i,j,k) ) * soln_a(i,j,k+1);
607  cur_zmom(i,j,k) = stage_zmom(i,j,k) + soln_a(i,j,k);
608  }
609  }
610  }
611 #endif
612  if (l_rayleigh_impl_for_w) {
613  // Every face but the ground, as in erf_substep_T: the top face is no longer
614  // pinned with an outflow top, and the faces at the ends of the box are solved for.
615  // A coarse/fine face whose (rho w) is imposed from the coarse level's record is not
616  // damped: the coarse level has damped it already, and it must match the record
617  const bool has_tgt_w = (cf_fluxes.tgt_w != nullptr);
618  const Array4<const Real> tgt_flag = (has_tgt_w) ? cf_fluxes.tgt[2]->const_array(mfi) : Array4<const Real>{};
619  ParallelFor(tbz, [=] AMREX_GPU_DEVICE (int i, int j, int k)
620  {
621  const bool imposed = has_tgt_w && (tgt_flag(i,j,k,1) > myhalf);
622  if (k > domlo.z && !imposed) {
623  Real damping_coeff = l_damp_coef * dtau * sinesq_stag_d[k];
624  cur_zmom(i,j,k) /= (one + damping_coeff);
625  }
626  });
627  }
628 
629  // **************************************************************************
630  // Define updates in the RHS of rho and (rho theta)
631  // **************************************************************************
632  const Array4<Real>& prev_drho_w = Delta_rho_w.array(mfi);
633  const bool has_tgt_z = (cf_fluxes.tgt[2] != nullptr);
634  const bool has_rec_z = (cf_fluxes.rec[2] != nullptr);
635  const Array4<const Real> tgt_z = (has_tgt_z) ? cf_fluxes.tgt[2]->const_array(mfi) : Array4<const Real>{};
636  const Array4< Real> rec_z = (has_rec_z) ? cf_fluxes.rec[2]->array(mfi) : Array4<Real>{};
637  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
638  {
639  Real zflux_lo = myhalf * (one + beta_s_a(i,j,k )) * soln_a(i,j,k )
640  + myhalf * (one - beta_s_a(i,j,k )) * prev_drho_w(i,j,k );
641  Real zflux_hi = myhalf * (one + beta_s_a(i,j,k+1)) * soln_a(i,j,k+1)
642  + myhalf * (one - beta_s_a(i,j,k+1)) * prev_drho_w(i,j,k+1);
643 
644  // On the coarse/fine faces of a fine level, the coarse level's flux over this substep
645  if (has_tgt_z) {
646  Real mfsq = mf_mx(i,j,0) * mf_my(i,j,0);
647  if (tgt_z(i,j,k ,1) > myhalf) { zflux_lo = tgt_z(i,j,k ,0) * mfsq - stage_zmom(i,j,k ); }
648  if (tgt_z(i,j,k+1,1) > myhalf) { zflux_hi = tgt_z(i,j,k+1,0) * mfsq - stage_zmom(i,j,k+1); }
649  }
650 
651  // On a coarse level, the flux each face applied over this substep
652  if (has_rec_z) {
653  Real mfsq = mf_mx(i,j,0) * mf_my(i,j,0);
654  rec_z(i,j,k) = (zflux_lo + stage_zmom(i,j,k)) / mfsq;
655  if (k == vbx_hi.z) {
656  rec_z(i,j,k+1) = (zflux_hi + stage_zmom(i,j,k+1)) / mfsq;
657  }
658  }
659 
660  avg_zmom_arr(i,j,k) += facinv*zflux_lo / (mf_mx(i,j,0) * mf_my(i,j,0));
661  if (l_reflux) {
662  (flx_arr[2])(i,j,k,0) = zflux_lo / (mf_mx(i,j,0) * mf_my(i,j,0));
663  (flx_arr[2])(i,j,k,1) = (flx_arr[2])(i,j,k,0) * myhalf * (prim(i,j,k) + prim(i,j,k-1));
664  }
665 
666  if (k == vbx_hi.z) {
667  avg_zmom_arr(i,j,k+1) += facinv * zflux_hi / (mf_mx(i,j,0) * mf_my(i,j,0));
668  if (l_reflux) {
669  (flx_arr[2])(i,j,k+1,0) = zflux_hi / (mf_mx(i,j,0) * mf_my(i,j,0));
670  (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));
671  }
672  }
673 
674  Real dz_inv = one / dz_ptr[k];
675  temp_rhs_arr(i,j,k,Rho_comp ) += dz_inv * ( zflux_hi - zflux_lo );
676  temp_rhs_arr(i,j,k,RhoTheta_comp) += myhalf * dz_inv * ( zflux_hi * (prim(i,j,k) + prim(i,j,k+1))
677  - zflux_lo * (prim(i,j,k) + prim(i,j,k-1)) );
678  });
679 
680  // We only add to the flux registers in the final RK step
681  if (l_reflux) {
682  int strt_comp_reflux = 0;
683  // For now we don't reflux (rho theta) because it seems to create issues at c/f boundaries
684  int num_comp_reflux = 1;
685  if (level < finest_level) {
686  fr_as_crse->CrseAdd(mfi,
687  {{AMREX_D_DECL(&(flux[0]), &(flux[1]), &(flux[2]))}},
688  dx, dtau, strt_comp_reflux, strt_comp_reflux, num_comp_reflux, RunOn::Device);
689  }
690  if (level > 0) {
691  fr_as_fine->FineAdd(mfi,
692  {{AMREX_D_DECL(&(flux[0]), &(flux[1]), &(flux[2]))}},
693  dx, dtau, strt_comp_reflux, strt_comp_reflux, num_comp_reflux, RunOn::Device);
694  }
695 
696  // This is necessary here so we don't go on to the next FArrayBox without
697  // having finished copying the fluxes into the FluxRegisters (since the fluxes
698  // are stored in temporary FArrayBox's)
699  Gpu::streamSynchronize();
700 
701  } // two-way coupling
702  } // mfi
703  } // OMP
704 
705 #ifdef _OPENMP
706 #pragma omp parallel if (Gpu::notInLaunchRegion())
707 #endif
708  for ( MFIter mfi(S_stage_data[IntVars::cons],TilingIfNotGPU()); mfi.isValid(); ++mfi)
709  {
710  const Box& bx = mfi.tilebox();
711 
712  const Array4< Real>& cur_cons = S_data[IntVars::cons].array(mfi);
713  const Array4<const Real>& prev_cons = S_prev[IntVars::cons].const_array(mfi);
714  auto const& temp_rhs_arr = temp_rhs.const_array(mfi);
715  auto const& slow_rhs_cons = S_slow_rhs[IntVars::cons].const_array(mfi);
716  const Array4<Real const>& cc_src_arr = cc_src.const_array(mfi);
717 
718  if (step == 0) {
719  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
720  {
721  cur_cons(i,j,k,Rho_comp) = prev_cons(i,j,k,Rho_comp) +
722  dtau * (slow_rhs_cons(i,j,k,Rho_comp) - temp_rhs_arr(i,j,k,Rho_comp));
723  cur_cons(i,j,k,RhoTheta_comp) = prev_cons(i,j,k,RhoTheta_comp) +
724  dtau * (slow_rhs_cons(i,j,k,RhoTheta_comp) - temp_rhs_arr(i,j,k,RhoTheta_comp));
725 
726  // add in source terms for cell-centered conserved variables
727  cur_cons(i,j,k,Rho_comp) += dtau * cc_src_arr(i,j,k,Rho_comp);
728  cur_cons(i,j,k,RhoTheta_comp) += dtau * cc_src_arr(i,j,k,RhoTheta_comp);
729  });
730  } else {
731  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
732  {
733  //
734  // We didn't need to set cur_cons = prev_cons above because they point to the same data for step > 0
735  //
736  cur_cons(i,j,k,Rho_comp) += dtau * (slow_rhs_cons(i,j,k,Rho_comp) - temp_rhs_arr(i,j,k,Rho_comp));
737  cur_cons(i,j,k,RhoTheta_comp) += dtau * (slow_rhs_cons(i,j,k,RhoTheta_comp) - temp_rhs_arr(i,j,k,RhoTheta_comp));
738 
739  // add in source terms for cell-centered conserved variables
740  cur_cons(i,j,k,Rho_comp) += dtau * cc_src_arr(i,j,k,Rho_comp);
741  cur_cons(i,j,k,RhoTheta_comp) += dtau * cc_src_arr(i,j,k,RhoTheta_comp);
742  });
743  } // step = 0
744 
745  const Array4<Real>& cur_xmom = S_data[IntVars::xmom].array(mfi);
746  const Array4<Real>& cur_ymom = S_data[IntVars::ymom].array(mfi);
747 
748  const Array4<Real const>& temp_cur_xmom_arr = temp_cur_xmom.const_array(mfi);
749  const Array4<Real const>& temp_cur_ymom_arr = temp_cur_ymom.const_array(mfi);
750 
751  Box tbx = surroundingNodes(bx,0);
752  Box tby = surroundingNodes(bx,1);
753 
754  ParallelFor(tbx, tby,
755  [=] AMREX_GPU_DEVICE (int i, int j, int k)
756  {
757  cur_xmom(i,j,k) = temp_cur_xmom_arr(i,j,k);
758  },
759  [=] AMREX_GPU_DEVICE (int i, int j, int k)
760  {
761  cur_ymom(i,j,k) = temp_cur_ymom_arr(i,j,k);
762  });
763 
764  } // mfi
765 }
constexpr amrex::Real RvoRd
Definition: ERF_Constants.H:59
constexpr amrex::Real R_d
Definition: ERF_Constants.H:49
constexpr amrex::Real Gamma
Definition: ERF_Constants.H:70
@ v_x
Definition: ERF_DataStruct.H:38
@ u_y
Definition: ERF_DataStruct.H:39
@ 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
if(KE_decay_height > 0 &&state_pert.nComp() > RhoKE_comp)
Definition: ERF_InitCustomPert_ABL.H:74
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
const int khi
Definition: ERF_InitCustomPert_Bubble.H:25
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
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 zero
Definition: ERF_NumericalConstants.H:36
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ 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
std::array< amrex::MultiFab *, AMREX_SPACEDIM > rec
Definition: ERF_TI_fast_headers.H:29
const amrex::MultiFab * tgt_w
Definition: ERF_TI_fast_headers.H:33
std::array< const amrex::MultiFab *, AMREX_SPACEDIM > tgt
Definition: ERF_TI_fast_headers.H:32
Here is the call graph for this function: