Compute vertical eddy viscosity coefficients using the Yonsei University (YSU) boundary layer scheme.
127 int klo = geom.Domain().smallEnd(2);
128 int khi = geom.Domain().bigEnd(2);
129 const int izmin =
klo;
130 const int izmax =
khi;
132 const Real dz = geom.CellSize(2);
133 const Real dz_inv = geom.InvCellSize(2);
134 const auto&
dxInv = geom.InvCellSizeArray();
139 MultiFab pblh_mf(eddyViscosity.boxArray(), eddyViscosity.DistributionMap(), 1, 0);
150 const int ng_avail = std::min({cons_in.nGrowVect()[0], cons_in.nGrowVect()[1],
151 xvel.nGrowVect()[0],
xvel.nGrowVect()[1],
152 yvel.nGrowVect()[0],
yvel.nGrowVect()[1],
153 SurfLayer->get_u_star(level)->nGrowVect()[0],
154 SurfLayer->get_u_star(level)->nGrowVect()[1],
155 SurfLayer->get_olen(level)->nGrowVect()[0],
156 SurfLayer->get_olen(level)->nGrowVect()[1],
157 (terrain_blank) ? terrain_blank->nGrowVect()[0] : 1000,
158 (terrain_blank) ? terrain_blank->nGrowVect()[1] : 1000});
159 if (ng_pblh > ng_avail) {
161 +
" needs " + std::to_string(ng_pblh) +
" halo columns, but the state and "
162 "surface-layer arrays carry only " + std::to_string(ng_avail)
163 +
"; reduce erf.pblh_smoothing_passes to at most " + std::to_string(ng_avail));
168 #pragma omp parallel if (Gpu::notInLaunchRegion())
171 for (MFIter mfi(eddyViscosity,
TileNoZ()); mfi.isValid(); ++mfi) {
174 const Box& gbx = mfi.growntilebox(IntVect(1,1,0));
176 gbx.bigEnd(2) ==
khi );
194 const Box xybx = PerpendicularBox<ZDir>(gbx, IntVect{0, 0, 0});
204 ? amrex::grow(mfi.tilebox(), IntVect(ng_pblh,ng_pblh,0)) : gbx;
205 const Box xybx_work = PerpendicularBox<ZDir>(gbx_work, IntVect{0, 0, 0});
206 const Box xybx_tile = PerpendicularBox<ZDir>(mfi.tilebox(), IntVect{0, 0, 0});
207 FArrayBox pbl_height_corrector(xybx_work, 1, The_Async_Arena());
208 IArrayBox pbl_index(xybx_work, 1, The_Async_Arena());
209 IArrayBox pbl_index_zero_ri(xybx_work, 1, The_Async_Arena());
210 FArrayBox hgamt_fab(xybx_work, 1, The_Async_Arena());
211 FArrayBox hgamq_fab(xybx_work, 1, The_Async_Arena());
212 FArrayBox hgamu_fab(xybx_work, 1, The_Async_Arena());
213 FArrayBox hgamv_fab(xybx_work, 1, The_Async_Arena());
214 FArrayBox wstar_fab(xybx_work, 1, The_Async_Arena());
215 FArrayBox vpert_fab(xybx_work, 1, The_Async_Arena());
216 FArrayBox entr_fab(xybx_work, 1, The_Async_Arena());
217 IArrayBox cloud_top_fab(xybx_work, 1, The_Async_Arena());
218 FArrayBox wstar3_down_fab(xybx_work, 1, The_Async_Arena());
219 FArrayBox sflux_fab(xybx_work, 1, The_Async_Arena());
220 FArrayBox wstar3_fab(xybx_work, 1, The_Async_Arena());
221 FArrayBox zol1_fab(xybx_work, 1, The_Async_Arena());
222 FArrayBox sfcflg_fab(xybx_work, 1, The_Async_Arena());
226 vpert_fab.setVal<RunOn::Device>(
zero);
227 sflux_fab.setVal<RunOn::Device>(
zero);
228 wstar3_fab.setVal<RunOn::Device>(
zero);
229 wstar3_down_fab.setVal<RunOn::Device>(
zero);
230 sfcflg_fab.setVal<RunOn::Device>(
zero);
231 hgamt_fab.setVal<RunOn::Device>(
zero);
232 hgamq_fab.setVal<RunOn::Device>(
zero);
233 hgamu_fab.setVal<RunOn::Device>(
zero);
234 hgamv_fab.setVal<RunOn::Device>(
zero);
235 wstar_fab.setVal<RunOn::Device>(
zero);
236 entr_fab.setVal<RunOn::Device>(
zero);
237 pbl_height_corrector.setVal<RunOn::Device>(
zero);
238 const auto& pblh_corr_arr = pbl_height_corrector.array();
239 const auto& pbli_arr = pbl_index.array();
240 const auto& pbli_zero_arr = pbl_index_zero_ri.array();
241 const auto& hgamt_arr = hgamt_fab.array();
242 const auto& hgamq_arr = hgamq_fab.array();
243 const auto& hgamu_arr = hgamu_fab.array();
244 const auto& hgamv_arr = hgamv_fab.array();
245 const auto& wstar_arr = wstar_fab.array();
246 const auto& vpert_arr = vpert_fab.array();
247 const auto& entr_arr = entr_fab.array();
248 const auto& cloud_top_arr = cloud_top_fab.array();
249 const auto& wstar3_down_arr = wstar3_down_fab.array();
250 const auto& sflux_arr = sflux_fab.array();
251 const auto& wstar3_arr = wstar3_fab.array();
252 const auto& zol1_arr = zol1_fab.array();
253 const auto& sfcflg_arr = sfcflg_fab.array();
256 const auto& cell_data = cons_in.const_array(mfi);
257 const auto& uvel =
xvel.const_array(mfi);
258 const auto& vvel =
yvel.const_array(mfi);
262 const auto& u_star_arr = SurfLayer->get_u_star(level)->const_array(mfi);
263 const auto& t_star_arr = SurfLayer->get_t_star(level)->const_array(mfi);
264 const auto& q_star_arr = SurfLayer->get_q_star(level)->const_array(mfi);
265 const auto& l_obuk_arr = SurfLayer->get_olen(level)->const_array(mfi);
266 const auto& t10av_arr = SurfLayer->get_mac_avg(level, 3)->const_array(mfi);
267 const auto& q10av_arr = SurfLayer->get_mac_avg(level, 4)->const_array(mfi);
268 const auto& ws10av_arr = SurfLayer->get_mac_avg(level, 6)->const_array(mfi);
269 const auto& z0_arr = SurfLayer->get_z0(level)->const_array(mfi);
272 const auto& lmask_arr = (SurfLayer->get_lmask(level)) ?
273 SurfLayer->get_lmask(level)->const_array(mfi) :
286 const bool l_ib = turbChoice.
pbl_ib_aware && (terrain_blank !=
nullptr);
288 "erf.pbl_ib_aware is not supported with terrain-fitted coordinates");
289 const Array4<Real const> blank_arr = l_ib ? terrain_blank->const_array(mfi) : Array4<Real const>{};
290 IArrayBox ksurf_fab(xybx_work, 1, The_Async_Arena());
291 FArrayBox zib_fab(xybx_work, 1, The_Async_Arena());
292 FArrayBox pblh_floor_fab(xybx_work, 1, The_Async_Arena());
293 FArrayBox us_eff_fab(xybx_work, 1, The_Async_Arena()), ts_eff_fab(xybx_work, 1, The_Async_Arena());
294 FArrayBox qs_eff_fab(xybx_work, 1, The_Async_Arena()), ol_eff_fab(xybx_work, 1, The_Async_Arena());
295 FArrayBox t10_eff_fab(xybx_work, 1, The_Async_Arena()), q10_eff_fab(xybx_work, 1, The_Async_Arena());
296 FArrayBox ws10_eff_fab(xybx_work, 1, The_Async_Arena()), z0_eff_fab(xybx_work, 1, The_Async_Arena());
297 const auto& ksurf_arr = ksurf_fab.array();
298 const auto& zib_arr = zib_fab.array();
299 const auto& pblh_floor_arr = pblh_floor_fab.array();
300 const auto& us_eff_arr = us_eff_fab.array();
const auto& ts_eff_arr = ts_eff_fab.array();
301 const auto& qs_eff_arr = qs_eff_fab.array();
const auto& ol_eff_arr = ol_eff_fab.array();
302 const auto& t10_eff_arr = t10_eff_fab.array();
const auto& q10_eff_arr = q10_eff_fab.array();
303 const auto& ws10_eff_arr = ws10_eff_fab.array();
const auto& z0_eff_arr = z0_eff_fab.array();
305 const Real dz_ib = geom.CellSize(2);
307 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
311 for (
int kk =
klo; kk <=
khi; ++kk) {
if (blank_arr(i, j, kk) >=
Real(0.5)) {
ks = kk + 1; } }
314 ksurf_arr(i, j, 0) =
ks;
315 zib_arr(i, j, 0) = (
ks -
klo) * dz_ib;
317 const Real u_top =
myhalf * (uvel(i, j,
ks) + uvel(i + 1, j,
ks));
318 const Real v_top =
myhalf * (vvel(i, j,
ks) + vvel(i, j + 1,
ks));
319 const Real ws_top = std::sqrt(u_top * u_top + v_top * v_top);
320 us_eff_arr(i, j, 0) = amrex::max(
KAPPA * ws_top / std::log(
myhalf * dz_ib / z0_ib),
Real(1.0e-3));
321 ts_eff_arr(i, j, 0) =
Real(0);
322 qs_eff_arr(i, j, 0) =
Real(0);
323 ol_eff_arr(i, j, 0) =
Real(1.0e10);
327 ws10_eff_arr(i, j, 0) = ws_top;
328 z0_eff_arr(i, j, 0) = z0_ib;
330 us_eff_arr(i, j, 0) = u_star_arr(i, j, 0);
331 ts_eff_arr(i, j, 0) = t_star_arr(i, j, 0);
332 qs_eff_arr(i, j, 0) = q_star_arr(i, j, 0);
333 ol_eff_arr(i, j, 0) = l_obuk_arr(i, j, 0);
334 t10_eff_arr(i, j, 0) = t10av_arr(i, j, 0);
335 q10_eff_arr(i, j, 0) = q10av_arr(i, j, 0);
336 ws10_eff_arr(i, j, 0) = ws10av_arr(i, j, 0);
337 z0_eff_arr(i, j, 0) = z0_arr(i, j, 0);
341 const Array4<Real const> z_nd_arr = z_phys_nd->array(mfi);
344 const Array4<Real const> qheat_arr = (qheating_rates !=
nullptr)
345 ? qheating_rates->const_array(mfi)
346 : Array4<Real const>{};
347 const bool has_qheating_rates = (qheating_rates !=
nullptr);
359 FArrayBox rib_base_fab(gbx_work, 1, The_Async_Arena());
360 FArrayBox rib_enhan_fab(gbx_work, 1, The_Async_Arena());
361 const auto& rib_base_arr = rib_base_fab.array();
362 const auto& rib_enhan_arr = rib_enhan_fab.array();
364 BL_PROFILE_VAR(
"YSUNew_Rib_Precompute", prof_rib_precomp);
365 ParallelFor(gbx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
367 const int ksrf = ksurf_arr(i, j, 0);
368 const Real zib = zib_arr(i, j, 0);
373 const amrex::Real t_enh = t_layer_v + vpert_arr(i,j,0);
374 const amrex::Real z_sfc = (use_terrain_fitted_coords)
376 const amrex::Real zval = (use_terrain_fitted_coords)
381 ?
GetThetavl(i,j,k,cell_data,moisture_indices)
382 :
GetThetav(i,j,k,cell_data,moisture_indices);
384 ?
GetThetavl(i,j,ksrf,cell_data,moisture_indices)
385 :
GetThetav(i,j,ksrf,cell_data,moisture_indices);
386 const amrex::Real ws2_raw =
fourth * ((uvel(i,j,k)+uvel(i+1,j,k))*(uvel(i,j,k)+uvel(i+1,j,k))
387 + (vvel(i,j,k)+vvel(i,j+1,k))*(vvel(i,j,k)+vvel(i,j+1,k)));
395 rib_base_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_layer_v) / (ws2 * theta_v_klo);
396 rib_enhan_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_enh) / (ws2 * theta_v_klo);
398 BL_PROFILE_VAR_STOP(prof_rib_precomp);
411 BL_PROFILE_VAR(
"YSUNew_SurfFlux_Precompute", prof_sflux_precomp);
412 ParallelFor(xybx_work, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
414 const int ksrf = ksurf_arr(i, j, 0);
416 const Real t_layer = t10_eff_arr(i, j, 0);
419 const Real rhox = rho_sfc;
434 const Real sflux = hfx / (rhox * cp_air) + qfx / rhox * ep1 * t_layer;
435 sflux_arr(i, j, 0) = sflux;
440 const bool sfcflg = (sflux >
zero);
441 sfcflg_arr(i, j, 0) = sfcflg ?
one :
zero;
450 const Real bfx0 = amrex::max(sflux, zero_d);
451 const Real wstar3 = govrth * bfx0 * pblh_guess;
452 wstar3_arr(i, j, 0) = wstar3;
462 wstar_arr(i, j, 0) = wscale;
467 Real obuk_val = ol_eff_arr(i, j, 0);
471 const Real zl1 = (use_terrain_fitted_coords)
474 Real zol1 = zl1 / obuk_val;
481 zol1_arr(i, j, 0) = zol1;
483 BL_PROFILE_VAR_STOP(prof_sflux_precomp);
495 BL_PROFILE_VAR(
"YSUNew_PBLH_Passes", prof_pblh);
496 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
498 const int ksrf = ksurf_arr(i, j, 0);
503 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
507 const Real z0 = z0_eff_arr(i, j, 0);
508 const Real ws_layer = ws10_eff_arr(i, j, 0);
510 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
518 Real Rib = rib_base_arr(i,j,ksrf);
519 bool above_critical = (Rib >= Ribcr);
522 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
523 if (rib_base_arr(i,j,kk) >= Ribcr) {
525 above_critical =
true;
530 pbli_arr(i, j, 0) = kpbl;
532 BL_PROFILE_VAR_STOP(prof_pblh);
617 constexpr
Real GAMCRQ =
Real(2.e-3);
620 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
622 const int ksrf = ksurf_arr(i, j, 0);
623 const Real zib = zib_arr(i, j, 0);
628 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
632 const Real z0 = z0_eff_arr(i, j, 0);
633 const Real ws_layer = ws10_eff_arr(i, j, 0);
635 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
645 const amrex::Real z_sfc_col = (use_terrain_fitted_coords)
653 Real Rib = rib_enhan_arr(i,j,ksrf);
654 zval0 = (use_terrain_fitted_coords)
658 bool above_critical = (Rib >= Ribcr);
661 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
662 if (rib_enhan_arr(i,j,kk) >= Ribcr) { kpbl = kk; above_critical =
true;
break; }
663 zval0 = (use_terrain_fitted_coords)
666 Rib0 = rib_enhan_arr(i,j,kk);
671 const Real z_sfc = (use_terrain_fitted_coords)
674 const Real dz_terrain = (use_terrain_fitted_coords)
677 const Real z_max = (use_terrain_fitted_coords)
680 const Real pblh_max =
Real(0.9) * z_max;
686 pblh_min = amrex::max(z_sfc_col +
Real(0.5)*dz0,
Real(10.0));
688 pblh_min = amrex::max(z_sfc +
Real(0.5) * dz_terrain,
Real(10.0));
692 if (kpbl <
khi && rib_enhan_arr(i,j,kpbl) >= Ribcr) {
693 const Real zval = (use_terrain_fitted_coords)
696 Rib = rib_enhan_arr(i,j,kpbl);
697 Real pblh_interp = zval0 + (zval - zval0) / (Rib - Rib0) * (Ribcr - Rib0);
698 pblh_corr_arr(i, j, 0) = amrex::max(amrex::min(pblh_interp, pblh_max), pblh_min);
700 pblh_corr_arr(i, j, 0) = pblh_min;
702 pbli_arr(i, j, 0) = kpbl;
705 hgamt_arr(i, j, 0) =
zero;
706 hgamq_arr(i, j, 0) =
zero;
707 wstar_arr(i, j, 0) =
zero;
753 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
755 const int ksrf = ksurf_arr(i, j, 0);
756 cloud_top_arr(i, j, 0) = -1;
759 int kpbl = pbli_arr(i, j, 0);
760 for (
int kk = kpbl - 1; kk >= ksrf; --kk) {
762 if (moisture_indices.
qc >= 0)
763 qc_kk = cell_data(i, j, kk, moisture_indices.
qc) / cell_data(i, j, kk,
Rho_comp);
764 if (moisture_indices.
qi >= 0)
765 qi_kk = cell_data(i, j, kk, moisture_indices.
qi) / cell_data(i, j, kk,
Rho_comp);
767 if (qc_kk + qi_kk > ysu_qcloud_threshold) {
768 cloud_top_arr(i, j, 0) = kk;
775 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
777 cloud_top_arr(i, j, 0) = -1;
783 const int ksrf = ksurf_arr(i, j, 0);
784 const Real t_layer = t10_eff_arr(i, j, 0);
785 Real obuk_val = ol_eff_arr(i, j, 0);
794 const Real HOL = sf * pblh_corr_arr(i, j, 0) / obuk_val;
795 const Real HOL_bounded = amrex::max(amrex::min(HOL,
Real(100.0)),
Real(-100.0));
797 const Real phiM = (obuk_val > 0)
798 ? (1 + 5 * HOL_bounded)
800 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
802 const Real phiM_safe = amrex::max(phiM,
Real(0.01));
808 Real wscale = us_eff_arr(i, j, 0) / phiM_safe;
809 wscale = amrex::max(wscale, us_eff_arr(i, j, 0) /
Real(5.0));
810 wscale = amrex::min(wscale,
Real(16.0) * us_eff_arr(i, j, 0));
815 if (enable_ysu_topdown && cloud_top_arr(i, j, 0) >= ksrf) {
816 int k_cloud_top = cloud_top_arr(i, j, 0);
824 if (has_qheating_rates) {
827 for (
int kk = ksrf; kk <= k_cloud_top; ++kk) {
829 ? (z_nd_arr(i, j, kk+1) - z_nd_arr(i, j, kk))
833 LRAD += -qheat_arr(i, j, kk, 1) * ldz;
842 if (enable_ysu_rad_tend_limiter && has_qheating_rates) {
844 if (!amrex::Math::isfinite(LRAD_raw)) {
849 const amrex::Real lim_mag = ysu_rad_tend_limiter_magnitude;
850 LRAD_limited = amrex::min(LRAD_raw, lim_mag);
851 LRAD_limited = amrex::max(LRAD_limited, -lim_mag);
860 / cell_data(i, j, k_cloud_top,
Rho_comp);
862 wstar3_down = amrex::max(CONST_GRAV_d / t_local * LRAD
864 * pblh_corr_arr(i, j, 0), zero_d);
866 wstar3_down_arr(i, j, 0) = wstar3_down;
869 const Real bfx0_corr = amrex::max(sflux_arr(i, j, 0), zero_d);
870 const Real t_dry = t10_eff_arr(i, j, 0);
871 const Real wstar3_corr = (
CONST_GRAV / t_dry) * bfx0_corr * pblh_corr_arr(i, j, 0);
872 wstar3_arr(i, j, 0) = wstar3_corr;
875 const Real ust3 = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
877 wscale_corr = amrex::min(wscale_corr, us_eff_arr(i, j, 0) *
amrex::Real(16.0));
878 wscale_corr = amrex::max(wscale_corr, us_eff_arr(i, j, 0) /
amrex::Real(5.0));
879 wstar_arr(i, j, 0) = wscale_corr;
885 bool SFCFLG = (sfcflg_arr(i, j, 0) >
zero);
887 const Real hfx_col = -rho_sfc *
amrex::Real(1004.0) * us_eff_arr(i, j, 0) * ts_eff_arr(i, j, 0);
888 const Real gamfac = const_b / (rho_sfc * wscale_corr);
889 const Real HGAMT = (SFCFLG && enable_ysu_countergradient)
890 ? amrex::min(gamfac * hfx_col /
amrex::Real(1004.0), GAMCRT)
895 const Real qfx_col = -rho_sfc * us_eff_arr(i, j, 0) * qs_eff_arr(i, j, 0);
896 const Real HGAMQ_raw = (SFCFLG &&
use_moisture && enable_ysu_countergradient)
899 Real HGAMQ = amrex::min(amrex::max(HGAMQ_raw, zero_d), GAMCRQ);
902 if (lmask_arr && SFCFLG &&
use_moisture && enable_ysu_countergradient) {
903 bool is_land = (lmask_arr(i,j,0) == 1);
904 if (!is_land) HGAMQ =
zero;
908 if (enable_ysu_sat_limiter && moisture_indices.
qv >= 0 && SFCFLG &&
use_moisture && enable_ysu_countergradient) {
909 Real qv_klo = cell_data(i, j, ksrf, moisture_indices.
qv) / cell_data(i, j, ksrf,
Rho_comp);
916 Real rh_klo = (qsat_klo >
Real(1.0e-10)) ? (qv_klo / qsat_klo) :
zero;
917 if (rh_klo >
Real(0.95)) {
918 Real rh_scaling = amrex::max(zero_d, (
one - rh_klo) /
Real(0.05));
925 if (pbli_arr(i, j, 0) <= ksrf + 1) {
926 hgamt_arr(i, j, 0) =
zero;
927 hgamq_arr(i, j, 0) =
zero;
928 hgamu_arr(i, j, 0) =
zero;
929 hgamv_arr(i, j, 0) =
zero;
930 vpert_arr(i, j, 0) =
zero;
932 const Real pblh = pblh_corr_arr(i, j, 0);
933 hgamt_arr(i, j, 0) = (enable_ysu_countergradient) ? HGAMT / pblh :
zero;
934 hgamq_arr(i, j, 0) = (enable_ysu_countergradient &&
use_moisture) ? HGAMQ / pblh :
zero;
948 hgamu_arr(i, j, 0) =
zero;
949 hgamv_arr(i, j, 0) =
zero;
950 if (SFCFLG && enable_ysu_countergradient) {
951 const Real wspd_sfc = ws10_eff_arr(i, j, 0);
953 wscale = wstar_arr(i, j, 0);
954 const Real wstar3 = wstar3_arr(i, j, 0);
956 const Real wscale4 = amrex::max(wscale * wscale * wscale * wscale,
963 const Real u_klo =
myhalf * (uvel(i, j, ksrf) + uvel(i+1, j, ksrf));
964 const Real v_klo =
myhalf * (vvel(i, j, ksrf) + vvel(i, j+1, ksrf));
965 hgamu_arr(i, j, 0) = brint * u_klo / pblh;
966 hgamv_arr(i, j, 0) = brint * v_klo / pblh;
975 if (enable_ysu_countergradient) {
978 const Real zl1_col = (use_terrain_fitted_coords)
982 const Real height_lim = amrex::min(zl1_col / (sfcfrac_h * pblh), one_d);
985 const Real VPERT_capped = enable_ysu_unbounded_vpert
987 : amrex::min(VPERT_raw, GAMCRT);
988 vpert_arr(i, j, 0) = amrex::max(VPERT_capped, zero_d) * height_lim;
990 vpert_arr(i, j, 0) =
zero;
1008 BL_PROFILE_VAR(
"YSUNew_Rib_Recompute", prof_rib_recomp);
1009 ParallelFor(gbx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1011 const int ksrf = ksurf_arr(i, j, 0);
1012 const Real zib = zib_arr(i, j, 0);
1017 const amrex::Real t_enh = t_layer_v + vpert_arr(i,j,0);
1018 const amrex::Real z_sfc = (use_terrain_fitted_coords)
1020 const amrex::Real zval = (use_terrain_fitted_coords)
1025 ?
GetThetavl(i,j,k,cell_data,moisture_indices)
1026 :
GetThetav(i,j,k,cell_data,moisture_indices);
1028 ?
GetThetavl(i,j,ksrf,cell_data,moisture_indices)
1029 :
GetThetav(i,j,ksrf,cell_data,moisture_indices);
1030 const amrex::Real ws2_raw =
fourth * ((uvel(i,j,k)+uvel(i+1,j,k))*(uvel(i,j,k)+uvel(i+1,j,k))
1031 + (vvel(i,j,k)+vvel(i,j+1,k))*(vvel(i,j,k)+vvel(i,j+1,k)));
1037 rib_enhan_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_enh) / (ws2 * theta_v_klo);
1039 BL_PROFILE_VAR_STOP(prof_rib_recomp);
1048 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1050 const int ksrf = ksurf_arr(i, j, 0);
1051 const Real zib = zib_arr(i, j, 0);
1055 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
1059 const Real z0 = z0_eff_arr(i, j, 0);
1060 const Real ws_layer = ws10_eff_arr(i, j, 0);
1062 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
1069 Real Rib = rib_enhan_arr(i,j,ksrf);
1070 zval0 = (use_terrain_fitted_coords)
1074 bool above_critical = (Rib >= Ribcr);
1076 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
1077 if (rib_enhan_arr(i,j,kk) >= Ribcr) { kpbl = kk; above_critical =
true;
break; }
1078 zval0 = (use_terrain_fitted_coords)
1081 Rib0 = rib_enhan_arr(i,j,kk);
1086 const Real z_sfc = (use_terrain_fitted_coords)
1089 const Real dz_terrain = (use_terrain_fitted_coords)
1092 const Real z_max = (use_terrain_fitted_coords)
1095 const Real pblh_max =
Real(0.9) * z_max;
1101 const amrex::Real z_sfc_col = (use_terrain_fitted_coords)
1104 pblh_min = amrex::max(z_sfc_col +
Real(0.5)*dz0,
Real(10.0));
1106 pblh_min = amrex::max(z_sfc +
Real(0.5) * dz_terrain,
Real(10.0));
1108 pblh_floor_arr(i, j, 0) = pblh_min;
1111 if (kpbl <
khi && rib_enhan_arr(i,j,kpbl) >= Ribcr) {
1112 const Real zval = (use_terrain_fitted_coords)
1115 Rib = rib_enhan_arr(i,j,kpbl);
1116 Real pblh_interp = zval0 + (zval - zval0) / (Rib - Rib0) * (Ribcr - Rib0);
1117 pblh_corr_arr(i, j, 0) = amrex::max(amrex::min(pblh_interp, pblh_max), pblh_min);
1119 pblh_corr_arr(i, j, 0) = pblh_min;
1121 pbli_arr(i, j, 0) = kpbl;
1134 geom.Domain(), geom.periodicity());
1139 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept {
1140 pblh_corr_arr(i, j, 0) = amrex::max(pblh_corr_arr(i, j, 0), pblh_floor_arr(i, j, 0));
1150 auto pblh_out = pblh_mf.array(mfi);
1151 const Box& tbx = mfi.tilebox();
1152 ParallelFor(tbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
1153 pblh_out(i, j, k) = pblh_corr_arr(i, j, 0);
1164 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1166 const int ksrf = ksurf_arr(i, j, 0);
1167 const Real zib = zib_arr(i, j, 0);
1168 const int kpblold = pbli_arr(i,j,0);
1169 bool definebrup =
false;
1172 const Real thermalli =
GetThetavl(i, j, ksrf, cell_data, moisture_indices);
1175 for (
int kk = kpblold; kk <
khi; ++kk) {
1177 const Real ws2_raw =
fourth * ((uvel(i,j,kk)+uvel(i+1,j,kk))*(uvel(i,j,kk)+uvel(i+1,j,kk))
1178 + (vvel(i,j,kk)+vvel(i,j+1,kk))*(vvel(i,j,kk)+vvel(i,j+1,kk)));
1185 const Real z_sfc = (use_terrain_fitted_coords)
1188 const Real zval_kk = (use_terrain_fitted_coords)
1191 const Real zrel_kk = amrex::max(zval_kk - z_sfc,
amrex::Real(1.0e-4));
1194 const Real thlix_kk =
GetThetavl(i, j, kk, cell_data, moisture_indices);
1195 const Real thlix_klo =
GetThetavl(i, j, ksrf, cell_data, moisture_indices);
1198 const Real bruptmp =
CONST_GRAV * zrel_kk * (thlix_kk - thermalli) / (ws2 * thlix_klo);
1201 const bool stable = (bruptmp >=
zero);
1204 pbli_arr(i,j,0) = kk;
1215 pbli_arr(i,j,0) = amrex::min(pbli_arr(i,j,0), izmax);
1242 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1244 const int ksrf = ksurf_arr(i, j, 0);
1247 int kpbl_zero = ksrf;
1248 Real Rib = rib_enhan_arr(i,j,ksrf);
1249 bool above_critical = (Rib >= Ribcr_zero);
1252 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
1253 if (rib_enhan_arr(i,j,kk) >= Ribcr_zero) { kpbl_zero = kk; above_critical =
true;
break; }
1256 pbli_zero_arr(i, j, 0) = kpbl_zero;
1258 BL_PROFILE_VAR_STOP(prof_pblh);
1267 ParallelFor(xybx, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1269 const int ksrf = ksurf_arr(i, j, 0);
1270 entr_arr(i,j,0) =
zero;
1271 if (!enable_ysu_entrainment)
return;
1273 const int kpbl = pbli_arr(i,j,0);
1275 const Real pblh = pblh_corr_arr(i,j,0);
1276 const Real wscale = wstar_arr(i,j,0);
1282 const Real wstar3_col = wstar3_arr(i,j,0);
1289 ?
GetThetavl(i, j, ksrf, cell_data, moisture_indices)
1290 :
GetThetav(i, j, ksrf, cell_data, moisture_indices);
1295 const int kpbl_p1 = amrex::min(kpbl + 1, izmax);
1297 ?
GetThetavl(i, j, kpbl, cell_data, moisture_indices)
1298 :
GetThetav(i, j, kpbl, cell_data, moisture_indices);
1300 ?
GetThetavl(i, j, kpbl_p1, cell_data, moisture_indices)
1301 :
GetThetav(i, j, kpbl_p1, cell_data, moisture_indices);
1302 const Real dthvx = amrex::max(thvx_kpbl_p1 - thvx_kpbl,
amrex::Real(1.0e-2));
1306 const Real we = amrex::max(bfxpbl / dthvx, -std::sqrt(wm2));
1309 const Real met_h = (use_terrain_fitted_coords)
1311 const Real dz_kpbl = met_h / dz_inv;
1321 Real K_entr_final = (we <
zero) ? rho_kpbl * (-we) * dz_kpbl :
zero;
1324 const int k_below = amrex::max(kpbl - 1, ksrf);
1326 Real qc_below = (moisture_indices.
qc >= 0)
1327 ? cell_data(i, j, k_below, moisture_indices.
qc) / rho_k :
zero;
1328 Real qi_below = (moisture_indices.
qi >= 0)
1329 ? cell_data(i, j, k_below, moisture_indices.
qi) / rho_k :
zero;
1333 if ((qc_below + qi_below) > cloud_thresh_entr && kpbl >= ksrf + 2) {
1341 const int k_p2 = amrex::min(kpbl + 1, izmax);
1342 const Real thlix_kbelow =
GetThetavl(i, j, k_below, cell_data, moisture_indices);
1343 const Real thlix_kp2 =
GetThetavl(i, j, k_p2, cell_data, moisture_indices);
1346 const Real dthvx_li = amrex::max(thlix_kp2 - thlix_kbelow,
amrex::Real(0.1));
1352 * xlv_over_cp * qc_below / dthvx_li,
1357 const Real we_cloud = amrex::max(bfxpbl / dthvx_li, -std::sqrt(wm2));
1361 const Real bfx0_cloud = amrex::max(sflux_arr(i, j, 0), zero_d);
1362 const Real bfxpbl_cloud = -ent_eff * bfx0_cloud;
1363 const Real we_cloud_top = amrex::max(bfxpbl_cloud / dthvx_li,
1367 we_final = we_cloud + we_cloud_top;
1370 K_entr_final = (we_final <
zero) ? rho_kpbl * (-we_final) * dz_kpbl :
zero;
1377 entr_arr(i,j,0) = amrex::min(K_entr_final, K_cap);
1381 const int kpbl_current = pbli_arr(i, j, 0);
1385 if (moisture_indices.
qc >= 0)
1386 qc_kpbl = cell_data(i, j, kpbl_current, moisture_indices.
qc) / cell_data(i, j, kpbl_current,
Rho_comp);
1387 if (moisture_indices.
qi >= 0)
1388 qi_kpbl = cell_data(i, j, kpbl_current, moisture_indices.
qi) / cell_data(i, j, kpbl_current,
Rho_comp);
1391 if ((qc_kpbl + qi_kpbl) > ysu_qcloud_threshold) {
1392 pbli_arr(i, j, 0) = amrex::min(kpbl_current + 1, izmax);
1399 FArrayBox K_down_fab(gbx, 1, The_Async_Arena());
1400 K_down_fab.setVal<RunOn::Device>(
zero);
1401 const auto& K_down_arr = K_down_fab.array();
1403 if (enable_ysu_topdown) {
1404 ParallelFor(gbx, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1406 const int ksrf = ksurf_arr(i, j, 0);
1407 const Real zib = zib_arr(i, j, 0);
1408 K_down_arr(i,j,k) =
zero;
1409 if (k >= pbli_arr(i,j,0) || k < ksrf)
return;
1413 const amrex::Real zval = (use_terrain_fitted_coords)
1416 const amrex::Real z_sfc = (use_terrain_fitted_coords)
1424 const amrex::Real wstar3_down_col = wstar3_down_arr(i,j,0);
1426 ? std::cbrt(wstar3_down_col)
1428 const amrex::Real zfac_up = amrex::max(zrel / pblh_rel, zero_d);
1429 K_down_arr(i,j,k) =
rho * wstar_down_eff *
KAPPA
1430 * amrex::max(pblh_rel - zrel, zero_d)
1431 * zfac_up * zfac_up;
1437 const Array4<Real>& K_turb = eddyViscosity.array(mfi);
1448 BL_PROFILE_VAR(
"YSUNew_Kprofile", prof_kprof);
1449 ParallelFor(gbx, [=, wstar3_arr_cap=wstar3_arr, zol1_arr_cap=zol1_arr, sfcflg_arr_cap=sfcflg_arr,
1450 zero_d=
zero, one_d=
one, two_d=
two] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1452 const int ksrf = ksurf_arr(i, j, 0);
1453 const Real zib = zib_arr(i, j, 0);
1456 if (rho_guard <=
Real(0)) {
1468 Real obuk_val = ol_eff_arr(i, j, 0);
1473 const Real zval = (use_terrain_fitted_coords)
1486 const Real met_h_zeta = (use_terrain_fitted_coords)
1488 const Real dz_terrain = met_h_zeta / dz_inv;
1509 constexpr
Real qc_threshold =
Real(1.0e-5);
1514 if (moisture_indices.
qc >= 0) {
1515 qc_mix = cell_data(i, j, k, moisture_indices.
qc) /
rho;
1517 if (moisture_indices.
qi >= 0) {
1518 qi_mix = cell_data(i, j, k, moisture_indices.
qi) /
rho;
1521 const Real total_qcloud = qc_mix + qi_mix;
1522 const bool has_cloud = (total_qcloud > qc_threshold);
1531 if (k < pbli_extent) {
1552 bool SFCFLG = (sfcflg_arr_cap(i, j, 0) >
zero);
1558 const Real HOL = sf * pblh_corr_arr(i, j, 0) / obuk_val;
1559 const Real HOL_bounded = amrex::max(amrex::min(HOL,
Real(100.0)),
Real(-100.0));
1562 const Real phiM = (obuk_val > 0)
1563 ? (1 + 5 * HOL_bounded)
1565 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
1572 const Real phit = (obuk_val > 0)
1573 ? (1 + 5 * HOL_bounded)
1575 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
1584 Real phit_cloud = phit;
1585 Real phiM_cloud = phiM;
1586 if (has_cloud && obuk_val >
zero) {
1590 Real reduction_factor =
one -
Real(0.15) * amrex::min(total_qcloud / qc_threshold, one_d);
1592 phiM_cloud =
one +
Real(5.0) * reduction_factor * sf * pblh_corr_arr(i, j, 0) / obuk_val;
1593 phit_cloud =
one +
Real(5.0) * reduction_factor * sf * pblh_corr_arr(i, j, 0) / obuk_val;
1594 }
else if (has_cloud && obuk_val <=
zero) {
1598 Real cloud_boost =
Real(1.0) +
Real(0.05) * amrex::min(total_qcloud / qc_threshold, one_d);
1601 phiM_cloud = std::pow(
1602 amrex::max(one_d -
Real(16.0) * HOL_bounded / cloud_boost,
Real(0.01)),
1604 phit_cloud = std::pow(
1605 amrex::max(one_d -
Real(16.0) * HOL_bounded / cloud_boost,
Real(0.01)),
1610 const Real phiM_eff = phiM_cloud;
1611 const Real phit_eff = phit_cloud;
1624 const Real conpr = bfac *
KAPPA * sfcfrac;
1627 const Real zq_kp1_prandtl = zval +
myhalf * dz_terrain;
1631 const Real prfac = SFCFLG ? conpr :
zero;
1636 const Real wstar3_col = wstar3_arr_cap(i, j, 0);
1637 const Real ust3 = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
1640 const Real wstar3_2 = wstar3_down_arr(i, j, 0);
1644 const Real wstar_tot3 = wstar3_col + wstar3_2;
1652 const Real pblh = pblh_corr_arr(i, j, 0);
1653 const Real sfclayer = sfcfrac * pblh;
1654 const Real zdiff = amrex::max(zq_kp1_prandtl - sfclayer, zero_d);
1655 const Real prnumfac =
amrex::Real(-3.0) * zdiff * zdiff / (pblh * pblh);
1661 Real prnum0 = (phit_eff / phiM_eff) + prfac;
1662 prnum0 = amrex::min(amrex::max(prnum0, prmin_wrf), prmax_wrf);
1666 Real prnum0_heat = prnum0 / (
one + prfac2 *
KAPPA * sfcfrac);
1667 prnum0_heat = amrex::min(amrex::max(prnum0_heat, prmin_wrf), prmax_wrf);
1668 const Real Prt =
one + (prnum0_heat -
one) * std::exp(prnumfac);
1672 const Real prnum_q =
one + (prnum0 -
one) * std::exp(prnumfac);
1689 const Real zq_kp1 = zval +
myhalf * dz_terrain;
1697 const Real zl1 = (use_terrain_fitted_coords)
1704 const Real pblh_rel = amrex::max(pblh_corr_arr(i, j, 0) - zl1,
amrex::Real(1.0e-4));
1705 const Real zfac = amrex::min(
1706 amrex::max(one_d - (zq_kp1 - zl1) / pblh_rel, zfacmin), one_d);
1710 const Real ust3_wscale = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
1714 wscalek_val = std::cbrt(ust3_wscale +
amrex::Real(8.0) *
KAPPA * wstar3_col * (
one - zfac));
1720 constexpr
Real ckz_pbl =
Real(0.001);
1721 const Real K_base = ckz_pbl * dz_terrain *
rho;
1723 K_turb(i, j, k,
EddyDiff::Mom_v) = K_base +
rho * wscalek_val *
KAPPA * (zq_kp1 - zib) * std::pow(zfac, pfac);
1734 if (enable_ysu_topdown && k < pbli_arr(i, j, 0)) {
1745 const Real zq_kp1_stable = zval +
myhalf * dz_terrain;
1748 const Real zl1_stable = (use_terrain_fitted_coords)
1754 const Real pblh_rel_stable = amrex::max(pblh_corr_arr(i, j, 0) - zl1_stable,
amrex::Real(1.0e-4));
1755 const Real zfac_stable = amrex::min(
1756 amrex::max(one_d - (zq_kp1_stable - zl1_stable) / pblh_rel_stable, zfacmin_stable), one_d);
1760 const Real zol1_stable = zol1_arr_cap(i, j, 0);
1761 const Real zol_ratio = (zq_kp1_stable - zib) / (zl1_stable - zib);
1762 const Real phim_stable_arg = zol1_stable * zol_ratio;
1767 const Real phim_stable = (enable_qnse_d >
Real(0.5))
1768 ? ((
one + qnse_am_d * phim_stable_arg) / (
one + qnse_bm_d * phim_stable_arg))
1770 const Real wscalek_stable = amrex::max(
1771 us_eff_arr(i, j, 0) / amrex::max(phim_stable,
amrex::Real(0.01)),
1775 constexpr
Real ckz_pbl_stable =
Real(0.001);
1776 const Real K_base_stable = ckz_pbl_stable * dz_terrain *
rho;
1778 K_turb(i, j, k,
EddyDiff::Mom_v) = K_base_stable +
rho * wscalek_stable *
KAPPA * (zq_kp1_stable - zib) * std::pow(zfac_stable, pfac_stable);
1783 const Real prnum_stable =
one + (prnum0 -
one) * std::exp(prnumfac);
1792 }
else if (k >= pbli_extent) {
1797 const Real lambda_min =
Real(30.0);
1798 const Real lambda_max =
Real(300.0);
1799 const Real lambdadz = amrex::min(amrex::max(
Real(0.1) * dz_terrain, lambda_min), lambda_max);
1800 const Real lscale = (lambdadz *
KAPPA * zval) / (lambdadz +
KAPPA * zval);
1801 Real dthetadz, dudz, dvdz;
1802 ComputeVerticalDerivativesPBL(i, j, k, uvel, vvel, cell_data, izmin, izmax, pbl_derivative_dz_inv(i,j,k),
1803 c_ext_dir_on_zlo, c_ext_dir_on_zhi, u_ext_dir_on_zlo,
1804 u_ext_dir_on_zhi, v_ext_dir_on_zlo, v_ext_dir_on_zhi, dthetadz,
1805 dudz, dvdz, moisture_indices, pbl_strat);
1814 const Real zrel_sl = amrex::max(zval - zib,
Real(1.0e-4));
1816 const Real qv = (moisture_indices.
qv >= 0) ?
1817 cell_data(i, j, k, moisture_indices.
qv) /
rho :
zero;
1819 sl.
u_star = us_eff_arr(i, j, 0);
1824 sl.
zeta = zrel_sl / obuk_val;
1829 const Real dudz_safe = (k < izmax) ? dudz :
zero;
1830 const Real dvdz_safe = (k < izmax) ? dvdz :
zero;
1834 const Real wind_shear = dudz_safe * dudz_safe + dvdz_safe * dvdz_safe;
1835 const Real wind_shear_safe = std::max(wind_shear,
Real(1.0e-8));
1841 const Real theta_v =
GetThetav(i, j, k, cell_data, moisture_indices);
1842 const Real dtheta_v_dz = dthetadz;
1855 Real grad_Ri =
CONST_GRAV / theta_v * dtheta_v_dz / wind_shear_safe;
1856 grad_Ri = std::max(std::min(grad_Ri,
Real(100.0)), -
Real(100.0));
1864 Real qc_k = (moisture_indices.
qc >= 0) ? cell_data(i,j,k, moisture_indices.
qc)/rho_k :
zero;
1865 Real qc_kp1 = (moisture_indices.
qc >= 0) ? cell_data(i,j,k+1,moisture_indices.
qc)/rho_kp1 :
zero;
1866 Real qi_k = (moisture_indices.
qi >= 0) ? cell_data(i,j,k, moisture_indices.
qi)/rho_k :
zero;
1867 Real qi_kp1 = (moisture_indices.
qi >= 0) ? cell_data(i,j,k+1,moisture_indices.
qi)/rho_kp1 :
zero;
1870 if ((qc_k + qi_k) > cloud_thresh && (qc_kp1 + qi_kp1) > cloud_thresh) {
1877 const Real qv_k_mri = (moisture_indices.
qv >= 0)
1878 ? cell_data(i,j,k, moisture_indices.
qv) / rho_k :
zero;
1879 const Real qv_kp1_mri = (moisture_indices.
qv >= 0)
1880 ? cell_data(i,j,k+1,moisture_indices.
qv) / rho_kp1 :
zero;
1885 const Real qmean =
myhalf * (qv_k_mri + qv_kp1_mri);
1891 const Real chi =
xlv *
xlv * qmean / (
cp * rv * tmean * tmean);
1914 const Real grad_Ri_safe = amrex::max(grad_Ri, -
Real(100.0));
1915 const Real fm = (grad_Ri_safe > 0)
1917 : 1 - 8 * grad_Ri_safe / (1 +
Real(1.746) * std::sqrt(amrex::max(-grad_Ri_safe, zero_d)));
1918 const Real ft = (grad_Ri_safe > 0)
1920 : 1 - 8 * grad_Ri_safe / (1 +
Real(1.286) * std::sqrt(amrex::max(-grad_Ri_safe, zero_d)));
1921 const Real rl2wsp =
rho * lscale * lscale * std::sqrt(wind_shear);
1925 if (grad_Ri_safe > 0) {
1944 if (k == pbli_arr(i,j,0)) {
1970 Real rhoKmin, rhoKmax;
1976 constexpr
Real Kmax =
Real(1000.0);
1977 rhoKmin = ckz * dz_terrain *
rho;
1978 rhoKmax =
rho * Kmax;
1985 rhoKmin =
rho * Kmin;
1986 rhoKmax =
rho * Kmax;
1989 #ifdef ERF_USE_WINDFARM
2003 if (k < pbli_extent) {
2018 std::min(K_turb(i, j, k,
EddyDiff::Q_v), rhoKmax), rhoKmin);
2043 if (k < pbli_extent) {
2057 BL_PROFILE_VAR_STOP(prof_kprof);
2061 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int ) noexcept
2086 SurfLayer->set_pblh(level, pblh_mf);
constexpr amrex::Real epsv
Definition: ERF_Constants.H:52
constexpr amrex::Real KAPPA
Definition: ERF_Constants.H:67
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:68
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenRandRTh(const amrex::Real rho, const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:46
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:81
#define Rho_comp
Definition: ERF_IndexDefines.H:42
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:43
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:8
const int klo
Definition: ERF_InitCustomPert_ABL.H:75
const bool use_moisture
Definition: ERF_InitCustomPert_ABL.H:71
const int khi
Definition: ERF_InitCustomPert_Bubble.H:21
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsatw(amrex::Real t, amrex::Real p, amrex::Real &qsatw)
Definition: ERF_MicrophysicsUtils.H:264
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:74
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetavl(int i, int j, int k, const amrex::Array4< amrex::Real const > &cell_data, const MoistureComponentIndices &moisture_indices)
Definition: ERF_MoistUtils.H:94
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);})
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:38
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ComputeVerticalDerivativesPBL(int i, int j, int k, const amrex::Array4< const amrex::Real > &uvel, const amrex::Array4< const amrex::Real > &vvel, const amrex::Array4< const amrex::Real > &cell_data, const int izmin, const int izmax, const PBLDerivativeDzInv &dz_inv, const bool c_ext_dir_on_zlo, const bool c_ext_dir_on_zhi, const bool u_ext_dir_on_zlo, const bool u_ext_dir_on_zhi, const bool v_ext_dir_on_zlo, const bool v_ext_dir_on_zhi, amrex::Real &dthetadz, amrex::Real &dudz, amrex::Real &dvdz, const MoistureComponentIndices &moisture_indices, const StratType strat=StratType::thetav)
Definition: ERF_PBLModels.H:304
void ApplyPBLHSmoothing(amrex::FArrayBox &pblh_fab, const amrex::Box &xybx_valid, const amrex::Real weight, const int passes, const amrex::Box &domain, const amrex::Periodicity &periodicity)
Apply spatial smoothing to PBLH field using 5-point stencil.
Definition: ERF_PBLModels.H:717
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ApplySurfaceLayerGradientsPBL(const PBLSurfaceLayerGradient &sl, amrex::Real &dthetadz, amrex::Real &dudz, amrex::Real &dvdz)
Definition: ERF_PBLModels.H:423
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeVirtualTStarPBL(amrex::Real t_star, amrex::Real q_star, amrex::Real theta, amrex::Real qv, bool use_moisture)
Definition: ERF_PBLModels.H:386
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Zrel_AtCellCenter(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:758
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtCellCenter(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:197
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ yvel_bc
Definition: ERF_IndexDefines.H:109
@ cons_bc
Definition: ERF_IndexDefines.H:92
@ xvel_bc
Definition: ERF_IndexDefines.H:108
@ ext_dir
Definition: ERF_IndexDefines.H:300
@ Theta_v
Definition: ERF_IndexDefines.H:253
@ Turb_lengthscale
Definition: ERF_IndexDefines.H:257
@ HGAMU_v
Definition: ERF_IndexDefines.H:265
@ Q_v
Definition: ERF_IndexDefines.H:256
@ Mom_v
Definition: ERF_IndexDefines.H:252
@ HGAMQ_v
Definition: ERF_IndexDefines.H:264
@ HGAMT_v
Definition: ERF_IndexDefines.H:263
@ HGAMV_v
Definition: ERF_IndexDefines.H:266
@ ustar
Definition: ERF_SLM.H:28
@ ks
Definition: ERF_SLM.H:74
@ qstar
Definition: ERF_SLM.H:30
@ tstar
Definition: ERF_SLM.H:29
@ rho
Definition: ERF_Kessler.H:25
@ theta
Definition: ERF_Kessler.H:26
@ qv
Definition: ERF_Kessler.H:31
@ alpha
Definition: ERF_SLM.H:151
@ xvel
Definition: ERF_IndexDefines.H:218
@ yvel
Definition: ERF_IndexDefines.H:219
@ dz
Definition: ERF_AdvanceWDM6.cpp:272
real(c_double), parameter cp
Definition: ERF_module_model_constants.F90:22
real(c_double), parameter xlv
Definition: ERF_module_model_constants.F90:57
int qi
cloud ice
Definition: ERF_DataStruct.H:251
int qv
water vapor
Definition: ERF_DataStruct.H:249
int qc
cloud liquid water
Definition: ERF_DataStruct.H:250
Functor for inverse vertical spacings for terrain-following grids using cell-center heights.
Definition: ERF_PBLModels.H:663
Definition: ERF_PBLModels.H:366
amrex::Real tstar_v
virtual temperature scale
Definition: ERF_PBLModels.H:368
amrex::Real zeta
stability coordinate z/L
Definition: ERF_PBLModels.H:370
amrex::Real u_star
friction velocity
Definition: ERF_PBLModels.H:367
amrex::Real zval
height of the cell center above the surface
Definition: ERF_PBLModels.H:369
bool enable_mrf_unbounded_vpert
Whether MRF leaves VPERT unlimited by GAMCRT.
Definition: ERF_TurbStruct.H:996
bool pbl_mrf_use_zero_ri_extent
Whether MRF uses the Ri=0 K-profile extent.
Definition: ERF_TurbStruct.H:997
StratType pbl_strat_type
Definition: ERF_TurbStruct.H:819
bool enable_vh96_shear_correction
Whether Vogelezang & Holtslag (1996) shear-correction term is enabled.
Definition: ERF_TurbStruct.H:974
bool enable_ysu_entrainment
Whether YSU entrainment-layer parameterization is enabled.
Definition: ERF_TurbStruct.H:962
bool enable_ysu_sat_limiter
Whether YSU applies a saturation limiter to moisture countergradient terms.
Definition: ERF_TurbStruct.H:958
bool enable_ysu_cloud_pblh
Whether YSU cloud-based PBL-height detection is enabled.
Definition: ERF_TurbStruct.H:964
amrex::Real pbl_mrf_const_b
MRF constant used to compute PBL height.
Definition: ERF_TurbStruct.H:982
amrex::Real pblh_smoothing_weight
Center-cell weight in PBLH smoothing stencil (must be in [0,1]).
Definition: ERF_TurbStruct.H:978
amrex::Real ysu_qcloud_threshold
Cloud liquid water threshold for YSUNew [kg/kg].
Definition: ERF_TurbStruct.H:966
amrex::Real qnse_bm
Definition: ERF_TurbStruct.H:1006
bool enable_qnse_stable_functions
Definition: ERF_TurbStruct.H:1003
bool enable_ysu_countergradient
Whether YSU countergradient corrections are enabled.
Definition: ERF_TurbStruct.H:954
bool enable_pblh_smoothing
Whether spatial smoothing of diagnosed PBLH is enabled.
Definition: ERF_TurbStruct.H:976
int pblh_smoothing_passes
Number of PBLH smoothing iterations to apply.
Definition: ERF_TurbStruct.H:977
amrex::Real pbl_ib_z0
Definition: ERF_TurbStruct.H:993
bool enable_ysu_topdown
Whether YSU top-down mixing is enabled.
Definition: ERF_TurbStruct.H:960
bool pbl_ib_aware
Definition: ERF_TurbStruct.H:992
amrex::Real ysu_rad_tend_limiter_magnitude
Definition: ERF_TurbStruct.H:972
amrex::Real pbl_ysu_land_Ribcr
Critical bulk Richardson number over land for stable YSU conditions.
Definition: ERF_TurbStruct.H:948
amrex::Real vh96_shear_const_b
Vogelezang & Holtslag (1996) shear-correction constant b.
Definition: ERF_TurbStruct.H:975
amrex::Real qnse_am
Definition: ERF_TurbStruct.H:1005
amrex::Real pbl_mrf_sf
MRF surface flux value used to compute PBL height.
Definition: ERF_TurbStruct.H:983
bool pbl_ysunew_highres_bounds
Whether YSUNew applies high-resolution grid-dependent diffusivity bounds.
Definition: ERF_TurbStruct.H:969
amrex::Real pbl_ysu_coriolis_freq
Coriolis frequency used by YSU-family PBL schemes.
Definition: ERF_TurbStruct.H:939
bool ysu_moistvars
Whether YSU applies turbulence to moisture variables.
Definition: ERF_TurbStruct.H:968
bool enable_ysu_terrain_pblh_floor
Whether YSU applies a terrain-following PBL-height floor.
Definition: ERF_TurbStruct.H:956
bool enable_ysu_liquid_theta
Whether YSU uses liquid-water virtual potential temperature for stability.
Definition: ERF_TurbStruct.H:952
bool enable_ysu_rad_tend_limiter
Definition: ERF_TurbStruct.H:971