ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ResolvedWallFlux.H
Go to the documentation of this file.
1 #ifndef ERF_RESOLVED_WALL_FLUX_H_
2 #define ERF_RESOLVED_WALL_FLUX_H_
3 
4 #include <AMReX_Box.H>
5 #include <AMReX_GpuContainers.H>
6 #include <AMReX_MultiFab.H>
7 
8 #include "ERF_Constants.H"
9 #include "ERF_EOS.H"
10 #include "ERF_MicrophysicsUtils.H"
11 #include "ERF_IndexDefines.H"
12 #include "ERF_DataStruct.H"
14 
16 
17 template <int DIR, bool HIGH>
18 AMREX_FORCE_INLINE
19 void apply_face (const amrex::Box& bx,
20  const amrex::Box& domain,
21  const int quantity,
22  const int flux_comp,
23  const amrex::Array4<const amrex::Real>& state,
24  const amrex::Array4<const amrex::Real>& prim,
25  const amrex::Array4<const amrex::Real>& base_state,
26  const amrex::Array4<amrex::Real>& rhs,
27  const amrex::Array4<amrex::Real>& xflux,
28  const amrex::Array4<amrex::Real>& yflux,
29  const amrex::Array4<amrex::Real>& zflux,
30  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dx_inv,
32  const amrex::Real alpha_T,
33  const amrex::Real alpha_C,
34  const amrex::Real rdOcp)
35 {
36  // A tile may belong to an interior BoxArray box. Do not relocate that
37  // tile to a global boundary: its Array4 views do not own data there.
38  if constexpr (HIGH) {
39  if (bx.bigEnd(DIR) != domain.bigEnd(DIR)) { return; }
40  } else {
41  if (bx.smallEnd(DIR) != domain.smallEnd(DIR)) { return; }
42  }
43 
44  const int cell_face = HIGH ? domain.bigEnd(DIR) : domain.smallEnd(DIR);
45  amrex::Box face_cells = bx;
46  face_cells.setSmall(DIR, cell_face);
47  face_cells.setBig(DIR, cell_face);
48  face_cells &= domain;
49  if (face_cells.isEmpty()) { return; }
50  AMREX_ALWAYS_ASSERT(bx.contains(face_cells));
51 
52  const auto wall = walls[2*DIR + (HIGH ? 1 : 0)];
53  const bool is_theta = quantity == RhoTheta_comp;
54  const bool is_qv = quantity == RhoQ1_comp;
55  const bool is_qc = quantity == RhoQ2_comp;
56  if (!((is_theta && wall.thermal_mode == erf_wall_thermodynamics::ThermalMode::FixedPhysicalTemperature) ||
57  (is_qv && wall.moisture_mode != erf_wall_thermodynamics::MoistureMode::LegacyNumerical) ||
58  (is_qc && wall.moisture_mode != erf_wall_thermodynamics::MoistureMode::LegacyNumerical))) {
59  return;
60  }
61 
62  const auto& flux = (DIR == 0) ? xflux : ((DIR == 1) ? yflux : zflux);
63  const amrex::Real alpha = is_theta ? alpha_T : alpha_C;
64  const amrex::Real inv_half_cell = amrex::Real(2.0) * dx_inv[DIR];
65 
66  amrex::ParallelFor(face_cells, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
67  {
68  const int fi = HIGH && DIR == 0 ? i + 1 : i;
69  const int fj = HIGH && DIR == 1 ? j + 1 : j;
70  const int fk = HIGH && DIR == 2 ? k + 1 : k;
71  const amrex::Real rho = state(i,j,k,Rho_comp);
72  const amrex::Real p0 = base_state(i,j,k,BaseState::p0_comp);
73  const amrex::Real wall_temperature = wall.physical_temperature_K;
74  amrex::Real wall_value = amrex::Real(0.0);
75  amrex::Real cell_value = prim(i,j,k,quantity-1);
76 
77  if (is_theta) {
78  wall_value = wall_temperature * std::pow(p_0 / p0, rdOcp);
79  } else if (is_qv && wall.moisture_mode == erf_wall_thermodynamics::MoistureMode::WetEquilibrium) {
80  amrex::Real qsat = amrex::Real(0.0);
81  erf_qsatw(wall_temperature, p0 * amrex::Real(0.01), qsat);
82  wall_value = qsat;
83  } else if (is_qc || (is_qv && wall.moisture_mode == erf_wall_thermodynamics::MoistureMode::DryImpermeable)) {
84  wall_value = amrex::Real(0.0);
85  }
86 
87  const amrex::Real old_flux = flux(fi,fj,fk,flux_comp);
88  amrex::Real new_flux = amrex::Real(0.0);
89  if (!(is_qc || (is_qv && wall.moisture_mode == erf_wall_thermodynamics::MoistureMode::DryImpermeable))) {
90  amrex::ignore_unused(alpha, inv_half_cell);
91  if constexpr (HIGH) {
92  new_flux = -rho * alpha * (wall_value - cell_value) * inv_half_cell;
93  } else {
94  new_flux = -rho * alpha * (cell_value - wall_value) * inv_half_cell;
95  }
96  }
97  flux(fi,fj,fk,flux_comp) = new_flux;
98 
99  // DiffusionSrcForState_N has already applied the old boundary flux to
100  // the RHS. Add only the boundary correction so the state update and
101  // the retained flux array use exactly the same physical flux.
102  const amrex::Real correction = (new_flux - old_flux) * dx_inv[DIR];
103  amrex::ignore_unused(rhs);
104  if constexpr (HIGH) {
105  rhs(i,j,k,quantity) -= correction;
106  } else {
107  rhs(i,j,k,quantity) += correction;
108  }
109  });
110 }
111 
112 inline void apply (const amrex::Box& bx,
113  const amrex::Box& domain,
114  const int quantity,
115  const int flux_comp,
116  const amrex::Array4<const amrex::Real>& state,
117  const amrex::Array4<const amrex::Real>& prim,
118  const amrex::Array4<const amrex::Real>& base_state,
119  const amrex::Array4<amrex::Real>& rhs,
120  const amrex::Array4<amrex::Real>& xflux,
121  const amrex::Array4<amrex::Real>& yflux,
122  const amrex::Array4<amrex::Real>& zflux,
123  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dx_inv,
125  const amrex::Real alpha_T,
126  const amrex::Real alpha_C,
127  const amrex::Real rdOcp)
128 {
129  apply_face<0,false>(bx,domain,quantity,flux_comp,state,prim,base_state,rhs,xflux,yflux,zflux,dx_inv,walls,alpha_T,alpha_C,rdOcp);
130  apply_face<0,true >(bx,domain,quantity,flux_comp,state,prim,base_state,rhs,xflux,yflux,zflux,dx_inv,walls,alpha_T,alpha_C,rdOcp);
131  apply_face<1,false>(bx,domain,quantity,flux_comp,state,prim,base_state,rhs,xflux,yflux,zflux,dx_inv,walls,alpha_T,alpha_C,rdOcp);
132  apply_face<1,true >(bx,domain,quantity,flux_comp,state,prim,base_state,rhs,xflux,yflux,zflux,dx_inv,walls,alpha_T,alpha_C,rdOcp);
133  apply_face<2,false>(bx,domain,quantity,flux_comp,state,prim,base_state,rhs,xflux,yflux,zflux,dx_inv,walls,alpha_T,alpha_C,rdOcp);
134  apply_face<2,true >(bx,domain,quantity,flux_comp,state,prim,base_state,rhs,xflux,yflux,zflux,dx_inv,walls,alpha_T,alpha_C,rdOcp);
135 }
136 
137 } // namespace erf_resolved_wall_flux
138 
139 #endif
constexpr amrex::Real p_0
Definition: ERF_Constants.H:61
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:43
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42
const Real rdOcp
Definition: ERF_InitCustomPert_Bomex.H:16
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
rho
Definition: ERF_InitCustomPert_Bubble.H:107
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsatw(amrex::Real t, amrex::Real p, amrex::Real &qsatw)
Definition: ERF_MicrophysicsUtils.H:228
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);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ p0_comp
Definition: ERF_IndexDefines.H:74
@ fi
Definition: ERF_AdvanceMorrison.cpp:107
Definition: ERF_ResolvedWallFlux.H:15
AMREX_FORCE_INLINE void apply_face(const amrex::Box &bx, const amrex::Box &domain, const int quantity, const int flux_comp, const amrex::Array4< const amrex::Real > &state, const amrex::Array4< const amrex::Real > &prim, const amrex::Array4< const amrex::Real > &base_state, const amrex::Array4< amrex::Real > &rhs, const amrex::Array4< amrex::Real > &xflux, const amrex::Array4< amrex::Real > &yflux, const amrex::Array4< amrex::Real > &zflux, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dx_inv, const erf_wall_thermodynamics::Boundary &walls, const amrex::Real alpha_T, const amrex::Real alpha_C, const amrex::Real rdOcp)
Definition: ERF_ResolvedWallFlux.H:19
void apply(const amrex::Box &bx, const amrex::Box &domain, const int quantity, const int flux_comp, const amrex::Array4< const amrex::Real > &state, const amrex::Array4< const amrex::Real > &prim, const amrex::Array4< const amrex::Real > &base_state, const amrex::Array4< amrex::Real > &rhs, const amrex::Array4< amrex::Real > &xflux, const amrex::Array4< amrex::Real > &yflux, const amrex::Array4< amrex::Real > &zflux, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dx_inv, const erf_wall_thermodynamics::Boundary &walls, const amrex::Real alpha_T, const amrex::Real alpha_C, const amrex::Real rdOcp)
Definition: ERF_ResolvedWallFlux.H:112
amrex::GpuArray< Face, 2 *AMREX_SPACEDIM > Boundary
Definition: ERF_WallThermodynamics.H:34
real(c_double), parameter p0
Definition: ERF_module_model_constants.F90:40
real(kind=kind_phys), parameter, public alpha
Definition: ERF_module_mp_wsm6.F90:44