1 #ifndef ERF_PBL_HEIGHT_H_
2 #define ERF_PBL_HEIGHT_H_
4 #include <AMReX_MultiFabUtil.H>
26 const amrex::MultiFab* z_phys_cc,
27 amrex::MultiFab* pblh,
28 const amrex::MultiFab&
cons,
29 const amrex::iMultiFab* lmask,
36 auto const& cons_arrs =
cons.const_arrays();
37 auto thetav_min = amrex::ReduceToPlane<amrex::ReduceOpMin,amrex::Real>(dir, bxlow,
cons,
38 [=] AMREX_GPU_DEVICE (
int box_no,
int i,
int j,
int k) ->
amrex::Real
40 return GetThetav(i,j,k,cons_arrs[box_no],moisture_indices);
45 auto const& ba = pblh->boxArray();
46 auto const& dm = pblh->DistributionMap();
47 auto const&
ng = pblh->nGrowVect();
49 amrex::MultiFab min_thetav(ba,dm,1,
ng);
52 amrex::MultiFab pblh_tke(ba,dm,1,
ng);
53 pblh_tke.setVal(
zero);
58 for (amrex::MFIter mfi(
cons,
TileNoZ()); mfi.isValid(); ++mfi)
60 const amrex::Box& domain = geom.Domain();
66 amrex::Box gtbx = mfi.growntilebox(
ng);
67 gtbx.setSmall(2,domain.smallEnd(2));
68 gtbx.setBig(2,domain.bigEnd(2));
75 amrex::Box gtbx2d = gtbx; gtbx2d.setRange(2,0);
76 const int klo = gtbx.smallEnd(2);
77 const int khi = gtbx.bigEnd(2);
79 auto min_thv_arr = min_thetav.array(mfi);
80 auto pblh_arr = pblh->array(mfi);
81 auto pblh_tke_arr = pblh_tke.array(mfi);
83 const auto cons_arr =
cons.const_array(mfi);
84 const auto lmask_arr = (lmask) ? lmask->const_array(mfi) : amrex::Array4<int> {};
91 const auto zphys_arr = z_phys_cc->const_array(mfi);
94 int imin = lbound(zphys_arr).x;
95 int jmin = lbound(zphys_arr).y;
96 int imax = ubound(zphys_arr).x;
97 int jmax = ubound(zphys_arr).y;
101 ParallelFor(gtbx2d, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
103 int ii = amrex::max(amrex::min(i,imax),imin);
104 int jj = amrex::max(amrex::min(j,jmax),jmin);
107 for (
int k(klo); k <=
khi; ++k) {
110 min_thv = amrex::min(min_thv, thv);
113 min_thv_arr(i,j,0) = min_thv;
117 ParallelFor(gtbx2d, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
119 int ii = amrex::max(amrex::min(i,imax),imin);
120 int jj = amrex::max(amrex::min(j,jmax),jmin);
123 const int is_land = (lmask_arr) ? lmask_arr(i,j,0) : 1;
128 for (
int k(klo); k <=
khi; ++k)
142 zi = zphys_arr(ii,jj,k)
143 + (zphys_arr(ii,jj,k+1)-zphys_arr(ii,jj,k))/(thv1-thv)
150 zi = zphys_arr(ii,jj,k)
151 + (zphys_arr(ii,jj,k+1)-zphys_arr(ii,jj,k))/(thv1-thv)
167 if ((tke1 <= TKEeps) && (tke > TKEeps))
170 zi_tke = zphys_arr(ii,jj,k)
171 + (zphys_arr(ii,jj,k+1)-zphys_arr(ii,jj,k))/(tke1-tke)
176 if ((
zi != 0) && (zi_tke != 0)) {
break; }
179 pblh_arr(i,j,0) =
zi;
180 pblh_tke_arr(i,j,0) = zi_tke;
188 const amrex::Real dz_no_terrain = geom.CellSize(2);
194 AMREX_ASSERT(kmax > 0);
195 const int khi_low = amrex::min(kmax,
khi);
197 ParallelFor(gtbx2d, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
200 for (
int k(klo); k <= khi_low; ++k) {
202 min_thv = amrex::min(min_thv, thv);
204 min_thv_arr(i,j,0) = min_thv;
208 ParallelFor(gtbx2d, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
211 const int is_land = (lmask_arr) ? lmask_arr(i,j,0) : 1;
216 for (
int k(klo); k <=
khi; ++k)
231 + dz_no_terrain/(thv1-thv)
239 + dz_no_terrain/(thv1-thv)
255 if ((tke1 <= TKEeps) && (tke > TKEeps))
258 zi_tke = (k+
myhalf)*dz_no_terrain
259 + dz_no_terrain/(tke1-tke) * (TKEeps - tke);
263 if ((
zi != 0) && (zi_tke != 0)) {
break; }
266 pblh_arr(i,j,0) =
zi;
267 pblh_tke_arr(i,j,0) = zi_tke;
275 for (amrex::MFIter mfi(*pblh); mfi.isValid(); ++mfi)
277 const auto cons_arr =
cons.const_array(mfi);
278 auto pblh_tke_arr = pblh_tke.array(mfi);
279 auto pblh_arr = pblh->array(mfi);
281 amrex::Box gtbx = mfi.growntilebox();
282 ParallelFor(gtbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
294 pblh_tke_arr(i,j,0) = amrex::max(
304 pblh_arr(i,j,0) = (
one-wt)*pblh_tke_arr(i,j,0) + wt*pblh_arr(i,j,0);
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real bogus_large_value
Definition: ERF_Constants.H:26
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
#define Rho_comp
Definition: ERF_IndexDefines.H:39
#define RhoKE_comp
Definition: ERF_IndexDefines.H:41
const int khi
Definition: ERF_InitCustomPert_Bubble.H:21
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetav(const int &i, const int &j, const int &k, const amrex::Array4< amrex::Real const > &cell_data, const MoistureComponentIndices &moisture_indices)
Definition: ERF_MoistUtils.H:72
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
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ ng
Definition: ERF_Morrison.H:49
@ cons
Definition: ERF_IndexDefines.H:214
@ zi
Definition: ERF_AdvanceWDM6.cpp:274
Diagnostic utility for the planetary boundary layer height.
Definition: ERF_PBLHeight.H:11
static constexpr amrex::Real sbl_lim
Upper limit of the stable boundary layer height [m].
Definition: ERF_PBLHeight.H:325
AMREX_GPU_HOST AMREX_FORCE_INLINE void compute_pblh(const amrex::Geometry &geom, const amrex::MultiFab *z_phys_cc, amrex::MultiFab *pblh, const amrex::MultiFab &cons, const amrex::iMultiFab *lmask, const MoistureComponentIndices &moisture_indices) const
Definition: ERF_PBLHeight.H:25
static constexpr amrex::Real sbl_damp
Transition length for blending [m].
Definition: ERF_PBLHeight.H:326
static constexpr amrex::Real theta_incr_water
Theta increase determining the capping inversion height over water [K].
Definition: ERF_PBLHeight.H:324
static constexpr amrex::Real thetamin_height
Height below which minimum theta-v is determined [m].
Definition: ERF_PBLHeight.H:322
static constexpr amrex::Real theta_incr_land
Theta increase determining the capping inversion height over land [K].
Definition: ERF_PBLHeight.H:323
The moisture data carried by the active microphysics scheme.
Definition: ERF_DataStruct.H:195