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::Moving )
52  {
53  // Make "old" fast geom -- store in z_phys_nd for convenience
54  if (verbose) Print() << "Making geometry at start of substep time: " << old_substep_time << std::endl;
55  prob->init_custom_terrain(fine_geom,*z_phys_nd[level],old_substep_time);
56  init_terrain_grid (level,fine_geom,*z_phys_nd[level], zlevels_stag[level], phys_bc_type);
57  make_J (fine_geom,*z_phys_nd[level], *detJ_cc[level]);
58 
59  // Make "new" fast geom
60  if (verbose) Print() << "Making geometry for end of substep time :" << new_substep_time << std::endl;
61  prob->init_custom_terrain(fine_geom,*z_phys_nd_new[level],new_substep_time);
62  init_terrain_grid (level,fine_geom,*z_phys_nd_new[level], zlevels_stag[level], phys_bc_type);
63  make_J (fine_geom,*z_phys_nd_new[level], *detJ_cc_new[level]);
64  make_areas (fine_geom,*z_phys_nd_new[level], *ax_new[level], *ay_new[level], *az_new[level]);
65 
66  Real inv_dt = 1./dtau;
67 
68  z_t_pert = std::make_unique<MultiFab>(S_data[IntVars::zmom].boxArray(), S_data[IntVars::zmom].DistributionMap(), 1, 1);
69 
70  for (MFIter mfi(*z_t_rk[level],TilingIfNotGPU()); mfi.isValid(); ++mfi)
71  {
72  Box gbx = mfi.growntilebox(IntVect(1,1,0));
73 
74  const Array4<Real >& z_t_arr = z_t_rk[level]->array(mfi);
75  const Array4<Real >& zp_t_arr = z_t_pert->array(mfi);
76 
77  const Array4<Real const>& z_nd_new_arr = z_phys_nd_new[level]->const_array(mfi);
78  const Array4<Real const>& z_nd_old_arr = z_phys_nd[level]->const_array(mfi);
79 
80  // Loop over horizontal plane
81  amrex::ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
82  {
83  // Evaluate between RK stages assuming the geometry is linear between old and new time
84  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)
85  +z_nd_new_arr(i ,j+1,k) - z_nd_old_arr( i,j+1,k)
86  +z_nd_new_arr(i+1,j ,k) - z_nd_old_arr(i+1,j ,k)
87  +z_nd_new_arr(i ,j ,k) - z_nd_old_arr(i ,j ,k));
88  // Convert to perturbation: z"_t(t) = z_t(t) - z_t^{RK}
89  zp_t_arr(i,j,k) -= z_t_arr(i,j,k);
90  });
91  } // mfi
92 
93  // We have to call this each step since it depends on the substep time now
94  // Note we pass in the *old* detJ here
95  make_fast_coeffs(level, fast_coeffs, S_stage, S_prim, pi_stage, fine_geom,
96  l_use_moisture, SolverChoice::mesh_type, solverChoice.gravity, solverChoice.c_p,
97  detJ_cc[level], r0, pi0, dtau, beta_s, phys_bc_type);
98 
99  if (fast_step == 0) {
100  // If this is the first substep we pass in S_old as the previous step's solution
101  erf_fast_rhs_MT(fast_step, nrk, level, finest_level,
102  S_slow_rhs, S_old, S_stage, S_prim, pi_stage, fast_coeffs,
103  S_data, S_scratch, fine_geom,
104  solverChoice.gravity, solverChoice.use_lagged_delta_rt,
105  z_t_rk[level], z_t_pert.get(),
106  z_phys_nd[level], z_phys_nd_new[level], z_phys_nd_src[level],
107  detJ_cc[level], detJ_cc_new[level], detJ_cc_src[level],
108  dtau, beta_s, inv_fac,
109  mapfac_m[level], mapfac_u[level], mapfac_v[level],
110  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
111  } else {
112  // If this is not the first substep we pass in S_data as the previous step's solution
113  erf_fast_rhs_MT(fast_step, nrk, level, finest_level,
114  S_slow_rhs, S_data, S_stage, S_prim, pi_stage, fast_coeffs,
115  S_data, S_scratch, fine_geom,
116  solverChoice.gravity, solverChoice.use_lagged_delta_rt,
117  z_t_rk[level], z_t_pert.get(),
118  z_phys_nd[level], z_phys_nd_new[level], z_phys_nd_src[level],
119  detJ_cc[level], detJ_cc_new[level], detJ_cc_src[level],
120  dtau, beta_s, inv_fac,
121  mapfac_m[level], mapfac_u[level], mapfac_v[level],
122  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
123  }
124  } else if (solverChoice.mesh_type != MeshType::ConstantDz) {
125  if (fast_step == 0) {
126 
127  // If this is the first substep we make the coefficients since they are based only on stage data
128  make_fast_coeffs(level, fast_coeffs, S_stage, S_prim, pi_stage, fine_geom,
129  l_use_moisture, SolverChoice::mesh_type, solverChoice.gravity, solverChoice.c_p,
130  detJ_cc[level], r0, pi0, dtau, beta_s, phys_bc_type);
131 
132  // If this is the first substep we pass in S_old as the previous step's solution
133  // and S_data is the new-time solution to be defined here
134  erf_fast_rhs_T(fast_step, nrk, level, finest_level,
135  S_slow_rhs, S_old, S_stage, S_prim, pi_stage, fast_coeffs,
136  S_data, S_scratch, fine_geom, solverChoice.gravity,
137  z_phys_nd[level], detJ_cc[level], dtau, beta_s, inv_fac,
138  mapfac_m[level], mapfac_u[level], mapfac_v[level],
139  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
140  } else {
141  // If this is not the first substep we pass in S_data as both the previous step's solution
142  // and as the new-time solution to be defined here
143  erf_fast_rhs_T(fast_step, nrk, level, finest_level,
144  S_slow_rhs, S_data, S_stage, S_prim, pi_stage, fast_coeffs,
145  S_data, S_scratch, fine_geom, solverChoice.gravity,
146  z_phys_nd[level], detJ_cc[level], dtau, beta_s, inv_fac,
147  mapfac_m[level], mapfac_u[level], mapfac_v[level],
148  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
149  }
150  } else {
151  if (fast_step == 0) {
152 
153  // If this is the first substep we make the coefficients since they are based only on stage data
154  make_fast_coeffs(level, fast_coeffs, S_stage, S_prim, pi_stage, fine_geom,
155  l_use_moisture, SolverChoice::mesh_type, solverChoice.gravity, solverChoice.c_p,
156  detJ_cc[level], r0, pi0, dtau, beta_s, phys_bc_type);
157 
158  // If this is the first substep we pass in S_old as the previous step's solution
159  // and S_data is the new-time solution to be defined here
160  erf_fast_rhs_N(fast_step, nrk, level, finest_level,
161  S_slow_rhs, S_old, S_stage, S_prim, pi_stage, fast_coeffs,
162  S_data, S_scratch, fine_geom, solverChoice.gravity,
163  dtau, beta_s, inv_fac,
164  mapfac_m[level], mapfac_u[level], mapfac_v[level],
165  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
166  } else {
167  // If this is not the first substep we pass in S_data as both the previous step's solution
168  // and as the new-time solution to be defined here
169  erf_fast_rhs_N(fast_step, nrk, level, finest_level,
170  S_slow_rhs, S_data, S_stage, S_prim, pi_stage, fast_coeffs,
171  S_data, S_scratch, fine_geom, solverChoice.gravity,
172  dtau, beta_s, inv_fac,
173  mapfac_m[level], mapfac_u[level], mapfac_v[level],
174  fr_as_crse, fr_as_fine, l_use_moisture, l_reflux, l_implicit_substepping);
175  }
176  }
177 
178  // Even if we update all the conserved variables we don't need
179  // to fillpatch the slow ones every acoustic substep
180 
181  // NOTE: Numerical diffusion is tested on in FillPatchIntermediate and dictates the size of the
182  // box over which VelocityToMomentum is computed. V2M requires one more ghost cell be
183  // filled for rho than velocity. This logical condition ensures we fill enough ghost cells
184  // when use_num_diff is true.
185  int ng_cons = S_data[IntVars::cons].nGrowVect().max() - 1;
186  int ng_vel = S_data[IntVars::xmom].nGrowVect().max();
187  if (!solverChoice.use_num_diff) {
188  ng_cons = 1;
189  ng_vel = 1;
190  }
191  apply_bcs(S_data, new_substep_time, ng_cons, ng_vel, fast_only=true, vel_and_mom_synced=false);
192  };
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 init_terrain_grid(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_areas(const Geometry &geom, MultiFab &z_phys_nd, MultiFab &ax, MultiFab &ay, MultiFab &az)
Definition: ERF_TerrainMetrics.cpp:651
void make_J(const Geometry &geom, MultiFab &z_phys_nd, MultiFab &detJ_cc)
Definition: ERF_TerrainMetrics.cpp:613
@ 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:570