ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ImplicitPost.H
Go to the documentation of this file.
1  // *****************************************************************************
2  // Do semi-implicit solve for vertical diffusion: KE and moisture
3  // *****************************************************************************
4  const bool l_do_implicit_ke = solverChoice.implicit_ke_diffusion;
5  const bool l_do_implicit_moist = solverChoice.implicit_moisture_diffusion;
6  const Real l_vert_implicit_fac = solverChoice.vert_implicit_fac[level][nrk];
8 
9  const bool l_use_turb = solverChoice.turbChoice[level].use_kturb;
10  const bool l_use_stretched_dz = (solverChoice.mesh_type == MeshType::StretchedDz);
11 
12  if ( (l_do_implicit_ke) &&
13  (solverChoice.turbChoice[level].use_tke)) {
14 
15  // BCs for KE
16  const BCRec* bc_ptr_h = domain_bcs_type.data();
17  GpuArray<Real, AMREX_SPACEDIM*2> l_bc_neumann_vals_d;
18  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
19  l_bc_neumann_vals_d[ori] = m_bc_neumann_vals[RhoKE_comp][ori];
20  }
21  const bool l_use_SurfLayer = false;
22 
23  for ( MFIter mfi(S_new[IntVars::cons],TileNoZ()); mfi.isValid(); ++mfi)
24  {
25  Box bx = mfi.tilebox();
26 
27  // NOTE: We have updated the state, use that directly
28  const Array4< Real>& cell_data = S_new[IntVars::cons].array(mfi);
29 
30  const Array4<const Real>& z_nd_arr = z_phys_nd[level]->const_array(mfi);
31  const Array4<const Real>& detJ_arr = detJ_cc[level]->const_array(mfi);
32  const Array4<const Real> mf_mx = mapfac[level][MapFacType::m_x]->const_array(mfi);
33  const Array4<const Real> mf_my = mapfac[level][MapFacType::m_y]->const_array(mfi);
34  const bool l_implicit_metric = solverChoice.implicit_terrain_metric &&
35  l_use_terrain_fitted_coords;
36 
37  const Array4<const Real>& mu_turb = l_use_turb ? eddyDiffs->const_array(mfi) :
38  Array4<const Real>{};
39 
40  if (l_use_stretched_dz) {
41  ImplicitDiffForStateLU_S(bx, fine_geom.Domain(), level, RhoKE_comp,
42  slow_dt, l_bc_neumann_vals_d, cell_data,
43  stretched_dz_d[level], Array4<const Real>{},
44  mu_turb, solverChoice,
45  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac);
46  } else if (l_use_terrain_fitted_coords) {
47  ImplicitDiffForStateLU_T(bx, fine_geom.Domain(), level, RhoKE_comp,
48  slow_dt, l_bc_neumann_vals_d, cell_data,
49  z_nd_arr, detJ_arr, dxInv, Array4<const Real>{},
50  mu_turb, solverChoice,
51  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
52  false, mf_mx, mf_my, l_implicit_metric);
53  } else { // no terrain
54  ImplicitDiffForStateLU_N(bx, fine_geom.Domain(), level, RhoKE_comp,
55  slow_dt, l_bc_neumann_vals_d, cell_data,
56  dxInv, Array4<const Real>{}, mu_turb, solverChoice,
57  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac, false,
58  (ib_wall_face33[level]) ? ib_wall_face33[level]->const_array(mfi)
59  : Array4<const Real>{},
60  (ib_wall_ktarget[level] && solverChoice.if_wall_tke_time_factor <= one)
61  ? ib_wall_ktarget[level]->const_array(mfi) : Array4<const Real>{});
62  }
63  } // mfi
64  } // do implicit tke and evolve tke
65 
66  if ( (l_do_implicit_moist) &&
67  (solverChoice.moisture_type != MoistureType::None) ) {
68 
69  // BCs for moisture (Neumann values are filled per species below)
70  const BCRec* bc_ptr_h = domain_bcs_type.data();
71  const bool l_use_SurfLayer = (m_SurfaceLayer[Orientation(Direction::z, Orientation::low)] != nullptr);
72 
73  const bool l_sbm = (solverChoice.moisture_type == MoistureType::SBM);
74 
75  for ( MFIter mfi(S_new[IntVars::cons],TileNoZ()); mfi.isValid(); ++mfi)
76  {
77  Box bx = mfi.tilebox();
78 
79  // NOTE: We have updated the state, use that directly
80  const Array4< Real>& cell_data = S_new[IntVars::cons].array(mfi);
81 
82  const Array4<const Real>& z_nd_arr = z_phys_nd[level]->const_array(mfi);
83  const Array4<const Real>& detJ_arr = detJ_cc[level]->const_array(mfi);
84  const Array4<const Real> mf_mx = mapfac[level][MapFacType::m_x]->const_array(mfi);
85  const Array4<const Real> mf_my = mapfac[level][MapFacType::m_y]->const_array(mfi);
86  const bool l_implicit_metric = solverChoice.implicit_terrain_metric &&
87  l_use_terrain_fitted_coords;
88 
89  const Array4<const Real>& mu_turb = l_use_turb ? eddyDiffs->const_array(mfi) :
90  Array4<const Real>{};
91  for (int m_comp : implicit_post_comps) {
92  if (m_comp < RhoQ1_comp) { continue; }
93  AMREX_ALWAYS_ASSERT(m_comp < S_new[IntVars::cons].nComp());
96  // Neumann values are stored by BC variable, not by state component
97  const int l_bc_comp =
98  ResolveNativeScalarDiffusionPolicy(m_comp, solverChoice.diffChoice).bc_comp;
99  GpuArray<Real, AMREX_SPACEDIM*2> l_bc_neumann_vals_d;
100  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
101  l_bc_neumann_vals_d[ori] = m_bc_neumann_vals[l_bc_comp][ori];
102  }
103 
104  const bool is_q1 = (m_comp == RhoQ1_comp);
105  const Array4<const Real>& mfx_z = (is_q1 && Q1fx3) ? Q1fx3->const_array(mfi)
106  : Array4<const Real> {};
107  const bool l_use_mrf_cg = solverChoice.turbChoice[level].enable_mrf_countergradient
108  && (solverChoice.turbChoice[level].pbl_type == PBLType::MRF)
109  && is_q1;
110  if (l_use_stretched_dz) {
111  ImplicitDiffForStateLU_S(bx, fine_geom.Domain(), level, m_comp,
112  slow_dt, l_bc_neumann_vals_d, cell_data,
113  stretched_dz_d[level], mfx_z,
114  mu_turb, solverChoice,
115  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
116  l_use_mrf_cg);
117  } else if (l_use_terrain_fitted_coords) {
118  ImplicitDiffForStateLU_T(bx, fine_geom.Domain(), level, m_comp,
119  slow_dt, l_bc_neumann_vals_d, cell_data,
120  z_nd_arr, detJ_arr, dxInv, mfx_z,
121  mu_turb, solverChoice,
122  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
123  l_use_mrf_cg,
124  mf_mx, mf_my, l_implicit_metric);
125  } else { // no terrain
126  ImplicitDiffForStateLU_N(bx, fine_geom.Domain(), level, m_comp,
127  slow_dt, l_bc_neumann_vals_d, cell_data,
128  dxInv, mfx_z, mu_turb, solverChoice,
129  bc_ptr_h, l_use_SurfLayer, l_vert_implicit_fac,
130  l_use_mrf_cg);
131  }
132  } // m_comp
133  } // mfi
134  } // if moist model and do implicit diff
135  } // implicit vertical factor > 0
@ m_y
Definition: ERF_DataStruct.H:39
@ 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 bool l_do_implicit_ke
Definition: ERF_ImplicitPost.H:4
const bool l_do_implicit_moist
Definition: ERF_ImplicitPost.H:5
const Real l_vert_implicit_fac
Definition: ERF_ImplicitPost.H:6
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:66
#define RhoKE_comp
Definition: ERF_IndexDefines.H:55
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
NativeScalarDiffusionPolicy ResolveNativeScalarDiffusionPolicy(const int qty_comp, const DiffChoice &choice)
Definition: ERF_NativeScalarDiffusion.H:26
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
const bool l_sbm
Definition: ERF_ScalarLimitPost.H:16
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
@ None
Definition: ERF_LSM_Types.H:6
void require_host_write_range_allowed(const bool sbm_active, const int start_component, const int num_components, const HostWritePath path)
Definition: ERF_SBMOwnership.cpp:47
int bc_comp
Definition: ERF_NativeScalarDiffusion.H:16