ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ImplicitPre.H
Go to the documentation of this file.
1  // *****************************************************************************
2  // Do semi-implicit solve for diffusion: theta, u, and v
3  // *****************************************************************************
4  {
5  const Real l_vert_implicit_fac = solverChoice.vert_implicit_fac[level][nrk];
6 
8 
9  const bool l_do_implicit_theta = solverChoice.implicit_thermal_diffusion;
10  const bool l_do_implicit_mom = solverChoice.implicit_momentum_diffusion;
11 
12  // If we're doing an implicit solve for momenta (u and v only),
13  // then we use the explicit solution at this point to derive
14  // the surface velocity gradient -- to be consistent with the
15  // hoextrap used with the surface layer BC. We then subtract
16  // out the contribution from the gradient of tau_corr times
17  // (1 - implicit_fac) and add in the implicit solution scaled
18  // by implicit_fac.
19  MultiFab* Tau13corr = (l_do_implicit_mom) ? Tau_corr[level][0].get() : nullptr;
20  MultiFab* Tau23corr = (l_do_implicit_mom) ? Tau_corr[level][1].get() : nullptr;
21 
22  // BCs
23  const BCRec* bc_ptr_h = domain_bcs_type.data();
24  GpuArray<Real, AMREX_SPACEDIM*2> l_bc_neumann_vals_d;
25  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
26  l_bc_neumann_vals_d[ori] = m_bc_neumann_vals[RhoTheta_comp][ori];
27  }
28  const bool l_use_SurfLayer = (m_SurfaceLayer[Orientation(Direction::z, Orientation::low)] != nullptr);
29 
30  const bool l_use_turb = solverChoice.turbChoice[level].use_kturb;
31 
32  const bool l_use_stretched_dz = (solverChoice.mesh_type == MeshType::StretchedDz);
33 
34  for ( MFIter mfi(S_old[IntVars::cons],TileNoZ()); mfi.isValid(); ++mfi)
35  {
36  Box bx = mfi.tilebox();
37  Box tbx = mfi.nodaltilebox(0);
38  Box tby = mfi.nodaltilebox(1);
39 
40  const Array4< Real>& cell_data = scratch.array(mfi);
41 
42  const Array4< Real>& rho_u = (l_do_implicit_mom) ? scratch_xmom.array(mfi) : Array4<Real>{};
43  const Array4< Real>& rho_v = (l_do_implicit_mom) ? scratch_ymom.array(mfi) : Array4<Real>{};
44  const Array4<const Real>& tau13_corr = (l_do_implicit_mom) ? Tau13corr->array(mfi) : Array4<Real>{};
45  const Array4<const Real>& tau23_corr = (l_do_implicit_mom) ? Tau23corr->array(mfi) : Array4<Real>{};
46 
47 
48  const Array4<const Real>& z_nd_arr = z_phys_nd[level]->const_array(mfi);
49  const Array4<const Real>& detJ_arr = detJ_cc[level]->const_array(mfi);
50 
51  // erf.implicit_terrain_metric (terrain-fitted meshes): the map factors the
52  // terrain-metric coefficient needs at the cells and at the u and v faces
53  const bool l_implicit_metric = solverChoice.implicit_terrain_metric &&
54  l_use_terrain_fitted_coords;
55  const Array4<const Real> mf_mx = mapfac[level][MapFacType::m_x]->const_array(mfi);
56  const Array4<const Real> mf_my = mapfac[level][MapFacType::m_y]->const_array(mfi);
57  const Array4<const Real> mf_ux = mapfac[level][MapFacType::u_x]->const_array(mfi);
58  const Array4<const Real> mf_uy = mapfac[level][MapFacType::u_y]->const_array(mfi);
59  const Array4<const Real> mf_vx = mapfac[level][MapFacType::v_x]->const_array(mfi);
60  const Array4<const Real> mf_vy = mapfac[level][MapFacType::v_y]->const_array(mfi);
61 
62  const Array4<const Real>& mu_turb = l_use_turb ? eddyDiffs->const_array(mfi) : Array4<const Real>{};
63 
64  // Vertical extent of the grid column over each (i,j), with a one-cell halo
65  // so a box can also see the column on the other side of each of its faces
66  const Array4<const int>& col_kext = column_kextent[level]->const_array(mfi);
67 
68  const Array4<const Real> tau13 = Tau[level][TauType::tau13]->array(mfi);
69  const Array4<const Real> tau23 = Tau[level][TauType::tau23]->array(mfi);
70  [[maybe_unused]] const Array4<const Real> tau33 = Tau[level][TauType::tau33]->array(mfi);
71  const Array4<const Real>& hfx_z = Hfx3->const_array(mfi);
72  const bool l_use_mrf_cg = solverChoice.turbChoice[level].enable_mrf_countergradient
73  && (solverChoice.turbChoice[level].pbl_type == PBLType::MRF);
74  // NOTE: Only ComputeDiffusivityYSUNew fills EddyDiff::HGAMU_v/HGAMV_v;
75  // the legacy PBLType::YSU never writes them. Gating on YSU
76  // therefore both disabled the term where it is produced and read
77  // an unwritten component where it was not.
78  const bool l_use_ysu_mom_cg = solverChoice.turbChoice[level].enable_ysu_countergradient
79  && (solverChoice.turbChoice[level].pbl_type == PBLType::YSUNew);
80  if (l_use_stretched_dz) {
81  if (l_do_implicit_theta) {
82 
83  ImplicitDiffForStateLU_S(bx, fine_geom.Domain(), level, RhoTheta_comp,
84  stage_dt, l_bc_neumann_vals_d, cell_data,
85  stretched_dz_d[level], hfx_z,
86  mu_turb, solverChoice,
87  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
88  l_use_mrf_cg);
89  }
90  if (l_do_implicit_mom) {
91  ImplicitDiffForMomLU_S<0>(tbx, fine_geom.Domain(), level, stage_dt,
92  col_kext,
93  cell_data, rho_u, tau13, tau13_corr,
94  stretched_dz_d[level],
95  mu_turb, solverChoice,
96  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
97  l_use_ysu_mom_cg);
98 
99  ImplicitDiffForMomLU_S<1>(tby, fine_geom.Domain(), level, stage_dt,
100  col_kext,
101  cell_data, rho_v, tau23, tau23_corr,
102  stretched_dz_d[level],
103  mu_turb, solverChoice,
104  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
105  l_use_ysu_mom_cg);
106  }
107  } else if (l_use_terrain_fitted_coords) {
108  if (l_do_implicit_theta) {
109  ImplicitDiffForStateLU_T(bx, fine_geom.Domain(), level, RhoTheta_comp,
110  stage_dt, l_bc_neumann_vals_d, cell_data,
111  z_nd_arr, detJ_arr, dxInv, hfx_z,
112  mu_turb, solverChoice,
113  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
114  l_use_mrf_cg,
115  mf_mx, mf_my, l_implicit_metric);
116  }
117  if (l_do_implicit_mom) {
118  ImplicitDiffForMomLU_T<0>(tbx, fine_geom.Domain(), level, stage_dt,
119  col_kext,
120  cell_data, rho_u, tau13, tau13_corr,
121  z_nd_arr, detJ_arr, dxInv,
122  mu_turb, solverChoice,
123  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
124  l_use_ysu_mom_cg,
125  mf_ux, mf_uy, l_implicit_metric);
126 
127  ImplicitDiffForMomLU_T<1>(tby, fine_geom.Domain(), level, stage_dt,
128  col_kext,
129  cell_data, rho_v, tau23, tau23_corr,
130  z_nd_arr, detJ_arr, dxInv,
131  mu_turb, solverChoice,
132  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
133  l_use_ysu_mom_cg,
134  mf_vx, mf_vy, l_implicit_metric);
135  }
136  } else { // no terrain
137  if (l_do_implicit_theta) {
138  ImplicitDiffForStateLU_N(bx, fine_geom.Domain(), level, RhoTheta_comp,
139  stage_dt, l_bc_neumann_vals_d, cell_data,
140  dxInv, hfx_z, mu_turb, solverChoice,
141  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
142  l_use_mrf_cg,
143  (ib_wall_face33[level]) ? ib_wall_face33[level]->const_array(mfi)
144  : Array4<const Real>{});
145  }
146  if (l_do_implicit_mom) {
147  // Fraction-stress immersed wall law: no coupling through the wall face
148  const Array4<const Real> wall13 = (ib_wall_face13[level])
149  ? ib_wall_face13[level]->const_array(mfi) : Array4<const Real>{};
150  const Array4<const Real> wall23 = (ib_wall_face23[level])
151  ? ib_wall_face23[level]->const_array(mfi) : Array4<const Real>{};
152  ImplicitDiffForMomLU_N<0>(tbx, fine_geom.Domain(), level, stage_dt,
153  col_kext,
154  cell_data, rho_u, tau13, tau13_corr,
155  dxInv,
156  mu_turb, solverChoice,
157  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
158  l_use_ysu_mom_cg, wall13);
159 
160  ImplicitDiffForMomLU_N<1>(tby, fine_geom.Domain(), level, stage_dt,
161  col_kext,
162  cell_data, rho_v, tau23, tau23_corr,
163  dxInv,
164  mu_turb, solverChoice,
165  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
166  l_use_ysu_mom_cg, wall23);
167  }
168  }
169  } // mfi
170 
171  } // if do implicit solve for diffusive contribution to (rho theta) update
172  } // wrapper
@ tau23
Definition: ERF_DataStruct.H:49
@ tau33
Definition: ERF_DataStruct.H:49
@ tau13
Definition: ERF_DataStruct.H:49
@ 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
void ImplicitDiffForStateLU_N(const amrex::Box &bx, const amrex::Box &domain, const int level, const int n, const double dt, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM *2 > &bc_neumann_vals, const amrex::Array4< amrex::Real > &cell_data, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &hfx_z, const amrex::Array4< const amrex::Real > &mu_turb, const SolverChoice &solverChoice, const amrex::BCRec *bc_ptr, const bool use_SurfLayer, const amrex::Real implicit_fac, const bool use_mrf_countergradient=false, const amrex::Array4< const amrex::Real > &wall_face=amrex::Array4< const amrex::Real >{}, const amrex::Array4< const amrex::Real > &wall_pin=amrex::Array4< const amrex::Real >{})
Apply implicit vertical state diffusion on a uniform grid without terrain.
void ImplicitDiffForStateLU_T(const amrex::Box &bx, const amrex::Box &domain, const int level, const int n, const double dt, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM *2 > &bc_neumann_vals, const amrex::Array4< amrex::Real > &cell_data, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &detJ, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &hfx_z, const amrex::Array4< const amrex::Real > &mu_turb, const SolverChoice &solverChoice, const amrex::BCRec *bc_ptr, const bool use_SurfLayer, const amrex::Real implicit_fac, const bool use_mrf_countergradient=false, const amrex::Array4< const amrex::Real > &mf_mx={}, const amrex::Array4< const amrex::Real > &mf_my={}, const bool implicit_metric=false)
Apply implicit vertical state diffusion on terrain-following coordinates.
void ImplicitDiffForStateLU_S(const amrex::Box &bx, const amrex::Box &domain, const int level, const int n, const double dt, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM *2 > &bc_neumann_vals, const amrex::Array4< amrex::Real > &cell_data, const amrex::Gpu::DeviceVector< amrex::Real > &stretched_dz_d, const amrex::Array4< const amrex::Real > &hfx_z, const amrex::Array4< const amrex::Real > &mu_turb, const SolverChoice &solverChoice, const amrex::BCRec *bc_ptr, const bool use_SurfLayer, const amrex::Real implicit_fac, const bool use_mrf_countergradient=false)
Apply implicit vertical state diffusion on a vertically stretched grid.
const Real l_vert_implicit_fac
Definition: ERF_ImplicitPost.H:6
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
pp_for_pert_vels get("prob_type", prob_type)
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ cons
Definition: ERF_IndexDefines.H:272