ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TI_substep_fun.H
Go to the documentation of this file.
1 /**
2  * Wrapper for calling the routine that creates the fast RHS
3  */
4 auto fast_rhs_fun = [&](int fast_step, int /*n_sub*/, int nrk,
5  Vector<MultiFab>& S_slow_rhs,
6  const Vector<MultiFab>& S_old,
7  Vector<MultiFab>& S_stage,
8  Vector<MultiFab>& S_data,
9  Vector<MultiFab>& S_scratch,
10  const Real dtau,
11  const Real inv_fac,
12  const Real old_substep_time,
13  const Real new_substep_time)
14  {
15  BL_PROFILE("fast_rhs_fun");
16  if (verbose) amrex::Print() << "Fast time integration at level " << level
17  << " from " << old_substep_time << " to " << new_substep_time
18  << " with dt = " << dtau << std::endl;
19 
20  // Define beta_s here so that it is consistent between where we make the fast coefficients
21  // and where we use them
22  // Per p2902 of Klemp-Skamarock-Dudhia-2007
23  // beta_s = -1.0 : fully explicit
24  // beta_s = 1.0 : fully implicit
25  Real beta_s;
26  if (solverChoice.substepping_type[level] == SubsteppingType::Implicit)
27  {
28  beta_s = 0.1;
29  } else { // Fully explicit
30  beta_s = -1.0;
31  }
32 
33  // *************************************************************************
34  // Set up flux registers if using two_way coupling
35  // *************************************************************************
36  const bool l_reflux = (solverChoice.coupling_type == CouplingType::TwoWay);
37 
38  YAFluxRegister* fr_as_crse = nullptr;
39  YAFluxRegister* fr_as_fine = nullptr;
40  if (l_reflux) {
41  if (level < finest_level) {
42  fr_as_crse = getAdvFluxReg(level+1);
43  }
44  if (level > 0) {
45  fr_as_fine = getAdvFluxReg(level);
46  }
47  }
48 
49  // Moving terrain
50  std::unique_ptr<MultiFab> z_t_pert;
51  if ( solverChoice.terrain_type == TerrainType::MovingFittedMesh )
52  {
53  // Make "old" fast geom -- store in z_phys_nd for convenience
54  Box terrain_bx(surroundingNodes(Geom(0).Domain())); terrain_bx.grow(z_phys_nd[level]->nGrow());
55 
56  if (verbose) Print() << "Making geometry at start of substep time: " << old_substep_time << std::endl;
57  FArrayBox terrain_fab_old(makeSlab(terrain_bx,2,0),1);
58  prob->init_terrain_surface(fine_geom,terrain_fab_old,old_substep_time);
59 
60  // Make "new" fast geom
61  if (verbose) Print() << "Making geometry for end of substep time :" << new_substep_time << std::endl;
62  FArrayBox terrain_fab_new(makeSlab(terrain_bx,2,0),1);
63  prob->init_terrain_surface(fine_geom,terrain_fab_new,new_substep_time);
64 
65  // Copy on intersection
66  for (MFIter mfi(*z_phys_nd[level],false); mfi.isValid(); ++mfi)
67  {
68  Box isect = terrain_fab_old.box() & (*z_phys_nd[level])[mfi].box();
69  ( *z_phys_nd[level])[mfi].template copy<RunOn::Device>(terrain_fab_old,isect,0,isect,0,1);
70  (*z_phys_nd_new[level])[mfi].template copy<RunOn::Device>(terrain_fab_new,isect,0,isect,0,1);
71  }
72 
73  make_terrain_fitted_coords(level,fine_geom,*z_phys_nd[level], zlevels_stag[level], phys_bc_type);
74  make_J (fine_geom,*z_phys_nd[level], *detJ_cc[level]);
75 
76  make_terrain_fitted_coords(level,fine_geom,*z_phys_nd_new[level], zlevels_stag[level], phys_bc_type);
77  make_J (fine_geom,*z_phys_nd_new[level], *detJ_cc_new[level]);
78  make_areas (fine_geom,*z_phys_nd_new[level], *ax_new[level], *ay_new[level], *az_new[level]);
79 
80  Real inv_dt = 1./dtau;
81 
82  z_t_pert = std::make_unique<MultiFab>(S_data[IntVars::zmom].boxArray(), S_data[IntVars::zmom].DistributionMap(), 1, 1);
83 
84  for (MFIter mfi(*z_t_rk[level],TilingIfNotGPU()); mfi.isValid(); ++mfi)
85  {
86  Box gbx = mfi.growntilebox(IntVect(1,1,0));
87 
88  const Array4<Real >& z_t_arr = z_t_rk[level]->array(mfi);
89  const Array4<Real >& zp_t_arr = z_t_pert->array(mfi);
90 
91  const Array4<Real const>& z_nd_new_arr = z_phys_nd_new[level]->const_array(mfi);
92  const Array4<Real const>& z_nd_old_arr = z_phys_nd[level]->const_array(mfi);
93 
94  // Loop over horizontal plane
95  amrex::ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
96  {
97  // Evaluate between RK stages assuming the geometry is linear between old and new time
98  zp_t_arr(i,j,k) = 0.25 * inv_dt * (z_nd_new_arr(i+1,j+1,k) - z_nd_old_arr(i+1,j+1,k)
99  +z_nd_new_arr(i ,j+1,k) - z_nd_old_arr( i,j+1,k)
100  +z_nd_new_arr(i+1,j ,k) - z_nd_old_arr(i+1,j ,k)
101  +z_nd_new_arr(i ,j ,k) - z_nd_old_arr(i ,j ,k));
102  // Convert to perturbation: z"_t(t) = z_t(t) - z_t^{RK}
103  zp_t_arr(i,j,k) -= z_t_arr(i,j,k);
104  });
105  } // mfi
106 
107  // We have to call this each step since it depends on the substep time now
108  // Note we pass in the *old* detJ here
109  make_fast_coeffs(level, fast_coeffs, S_stage, S_prim, pi_stage, fine_geom,
110  l_use_moisture, SolverChoice::mesh_type, solverChoice.gravity, solverChoice.c_p,
111  detJ_cc[level], r0, pi0, dtau, beta_s, phys_bc_type);
112 
113  if (fast_step == 0) {
114  // If this is the first substep we pass in S_old as the previous step's solution
115  erf_fast_rhs_MT(fast_step, nrk, level, finest_level,
116  S_slow_rhs, S_old, S_stage, S_prim, pi_stage, fast_coeffs,
117  S_data, S_scratch, fine_geom,
118  solverChoice.gravity, solverChoice.use_lagged_delta_rt,
119  z_t_rk[level], z_t_pert.get(),
120  z_phys_nd[level], z_phys_nd_new[level], z_phys_nd_src[level],
121  detJ_cc[level], detJ_cc_new[level], detJ_cc_src[level],
122  dtau, beta_s, inv_fac,
123  mapfac_m[level], mapfac_u[level], mapfac_v[level],
124  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
125  } else {
126  // If this is not the first substep we pass in S_data as the previous step's solution
127  erf_fast_rhs_MT(fast_step, nrk, level, finest_level,
128  S_slow_rhs, S_data, S_stage, S_prim, pi_stage, fast_coeffs,
129  S_data, S_scratch, fine_geom,
130  solverChoice.gravity, solverChoice.use_lagged_delta_rt,
131  z_t_rk[level], z_t_pert.get(),
132  z_phys_nd[level], z_phys_nd_new[level], z_phys_nd_src[level],
133  detJ_cc[level], detJ_cc_new[level], detJ_cc_src[level],
134  dtau, beta_s, inv_fac,
135  mapfac_m[level], mapfac_u[level], mapfac_v[level],
136  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
137  }
138  } else if (solverChoice.mesh_type != MeshType::ConstantDz) {
139  if (fast_step == 0) {
140 
141  // If this is the first substep we make the coefficients since they are based only on stage data
142  make_fast_coeffs(level, fast_coeffs, S_stage, S_prim, pi_stage, fine_geom,
143  l_use_moisture, SolverChoice::mesh_type, solverChoice.gravity, solverChoice.c_p,
144  detJ_cc[level], r0, pi0, dtau, beta_s, phys_bc_type);
145 
146  // If this is the first substep we pass in S_old as the previous step's solution
147  // and S_data is the new-time solution to be defined here
148  erf_fast_rhs_T(fast_step, nrk, level, finest_level,
149  S_slow_rhs, S_old, S_stage, S_prim, pi_stage, fast_coeffs,
150  S_data, S_scratch, fine_geom, solverChoice.gravity,
151  z_phys_nd[level], detJ_cc[level], dtau, beta_s, inv_fac,
152  mapfac_m[level], mapfac_u[level], mapfac_v[level],
153  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
154  } else {
155  // If this is not the first substep we pass in S_data as both the previous step's solution
156  // and as the new-time solution to be defined here
157  erf_fast_rhs_T(fast_step, nrk, level, finest_level,
158  S_slow_rhs, S_data, S_stage, S_prim, pi_stage, fast_coeffs,
159  S_data, S_scratch, fine_geom, solverChoice.gravity,
160  z_phys_nd[level], detJ_cc[level], dtau, beta_s, inv_fac,
161  mapfac_m[level], mapfac_u[level], mapfac_v[level],
162  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
163  }
164  } else {
165  if (fast_step == 0) {
166 
167  // If this is the first substep we make the coefficients since they are based only on stage data
168  make_fast_coeffs(level, fast_coeffs, S_stage, S_prim, pi_stage, fine_geom,
169  l_use_moisture, SolverChoice::mesh_type, solverChoice.gravity, solverChoice.c_p,
170  detJ_cc[level], r0, pi0, dtau, beta_s, phys_bc_type);
171 
172  // If this is the first substep we pass in S_old as the previous step's solution
173  // and S_data is the new-time solution to be defined here
174  erf_fast_rhs_N(fast_step, nrk, level, finest_level,
175  S_slow_rhs, S_old, S_stage, S_prim, pi_stage, fast_coeffs,
176  S_data, S_scratch, fine_geom, solverChoice.gravity,
177  dtau, beta_s, inv_fac,
178  mapfac_m[level], mapfac_u[level], mapfac_v[level],
179  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
180  } else {
181  // If this is not the first substep we pass in S_data as both the previous step's solution
182  // and as the new-time solution to be defined here
183  erf_fast_rhs_N(fast_step, nrk, level, finest_level,
184  S_slow_rhs, S_data, S_stage, S_prim, pi_stage, fast_coeffs,
185  S_data, S_scratch, fine_geom, solverChoice.gravity,
186  dtau, beta_s, inv_fac,
187  mapfac_m[level], mapfac_u[level], mapfac_v[level],
188  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
189  }
190  }
191 
192  // Even if we update all the conserved variables we don't need
193  // to fillpatch the slow ones every acoustic substep
194 
195  // NOTE: Numerical diffusion is tested on in FillPatchIntermediate and dictates the size of the
196  // box over which VelocityToMomentum is computed. V2M requires one more ghost cell be
197  // filled for rho than velocity. This logical condition ensures we fill enough ghost cells
198  // when use_num_diff is true.
199  int ng_cons = S_data[IntVars::cons].nGrowVect().max() - 1;
200  int ng_vel = S_data[IntVars::xmom].nGrowVect().max();
201  if (!solverChoice.use_num_diff) {
202  ng_cons = 1;
203  ng_vel = 1;
204  }
205  apply_bcs(S_data, new_substep_time, ng_cons, ng_vel, fast_only=true, vel_and_mom_synced=false);
206  };
void erf_fast_rhs_MT(int step, int nrk, 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 &pi_stage, const MultiFab &fast_coeffs, Vector< MultiFab > &S_data, Vector< MultiFab > &S_scratch, 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 Real dtau, const Real beta_s, const Real facinv, std::unique_ptr< MultiFab > &mapfac_m, std::unique_ptr< MultiFab > &mapfac_u, std::unique_ptr< MultiFab > &mapfac_v, YAFluxRegister *fr_as_crse, YAFluxRegister *fr_as_fine, bool l_use_moisture, bool l_reflux, bool)
Definition: ERF_FastRhs_MT.cpp:45
void erf_fast_rhs_N(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 &pi_stage, const MultiFab &fast_coeffs, Vector< MultiFab > &S_data, Vector< MultiFab > &S_scratch, const Geometry geom, const Real gravity, const Real dtau, const Real beta_s, const Real facinv, std::unique_ptr< MultiFab > &mapfac_m, std::unique_ptr< MultiFab > &mapfac_u, std::unique_ptr< MultiFab > &mapfac_v, YAFluxRegister *fr_as_crse, YAFluxRegister *fr_as_fine, bool l_use_moisture, bool l_reflux, bool l_implicit_substepping)
Definition: ERF_FastRhs_N.cpp:36
void erf_fast_rhs_T(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 &pi_stage, const MultiFab &fast_coeffs, Vector< MultiFab > &S_data, Vector< MultiFab > &S_scratch, const Geometry geom, const Real gravity, std::unique_ptr< MultiFab > &z_phys_nd, std::unique_ptr< MultiFab > &detJ_cc, const Real dtau, const Real beta_s, const Real facinv, std::unique_ptr< MultiFab > &mapfac_m, std::unique_ptr< MultiFab > &mapfac_u, std::unique_ptr< MultiFab > &mapfac_v, YAFluxRegister *fr_as_crse, YAFluxRegister *fr_as_fine, bool l_use_moisture, bool l_reflux, bool)
Definition: ERF_FastRhs_T.cpp:38
void make_fast_coeffs(int, MultiFab &fast_coeffs, Vector< MultiFab > &S_stage_data, const MultiFab &S_stage_prim, const MultiFab &pi_stage, const amrex::Geometry geom, bool l_use_moisture, MeshType mesh_type, Real gravity, Real c_p, std::unique_ptr< MultiFab > &detJ_cc, const MultiFab *r0, const MultiFab *pi0, Real dtau, Real beta_s, amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 > &phys_bc_type)
Definition: ERF_MakeFastCoeffs.cpp:26
auto fast_rhs_fun
Definition: ERF_TI_substep_fun.H:4
auto apply_bcs
Definition: ERF_TI_utils.H:50
void make_areas(const Geometry &geom, MultiFab &z_phys_nd, MultiFab &ax, MultiFab &ay, MultiFab &az)
Definition: ERF_TerrainMetrics.cpp:629
void make_terrain_fitted_coords(int lev, const Geometry &geom, MultiFab &z_phys_nd, Vector< Real > const &z_levels_h, GpuArray< ERF_BC, AMREX_SPACEDIM *2 > &phys_bc_type)
Definition: ERF_TerrainMetrics.cpp:118
void make_J(const Geometry &geom, MultiFab &z_phys_nd, MultiFab &detJ_cc)
Definition: ERF_TerrainMetrics.cpp:591
@ cons
Definition: ERF_IndexDefines.H:139
@ zmom
Definition: ERF_IndexDefines.H:142
@ xmom
Definition: ERF_IndexDefines.H:140
static MeshType mesh_type
Definition: ERF_DataStruct.H:583