Compute vertical eddy viscosity coefficients using the Yonsei University (YSU) boundary layer scheme.
128 int klo = geom.Domain().smallEnd(2);
129 int khi = geom.Domain().bigEnd(2);
130 const int izmin =
klo;
131 const int izmax =
khi;
133 const Real dz = geom.CellSize(2);
134 const Real dz_inv = geom.InvCellSize(2);
135 const auto&
dxInv = geom.InvCellSizeArray();
140 MultiFab pblh_mf(eddyViscosity.boxArray(), eddyViscosity.DistributionMap(), 1, 0);
155 const auto needs_widening = [&] (
const MultiFab* mf) {
156 return mf !=
nullptr && std::min(mf->nGrowVect()[0], mf->nGrowVect()[1]) < ng_pblh;
158 const auto widen_sfc = [&] (
const MultiFab* mf) -> std::unique_ptr<MultiFab> {
159 if (!needs_widening(mf)) {
return nullptr; }
161 [&] (MultiFab& wide) { SurfLayer->fill_planar_boundary(level, wide); });
163 const std::unique_ptr<MultiFab> u_star_wide = widen_sfc(SurfLayer->get_u_star(level));
164 const std::unique_ptr<MultiFab> t_star_wide = widen_sfc(SurfLayer->get_t_star(level));
165 const std::unique_ptr<MultiFab> q_star_wide = widen_sfc(SurfLayer->get_q_star(level));
166 const std::unique_ptr<MultiFab> olen_wide = widen_sfc(SurfLayer->get_olen(level));
167 const std::unique_ptr<MultiFab> z0_wide = widen_sfc(SurfLayer->get_z0(level));
168 const std::unique_ptr<MultiFab> qheat_wide = (needs_widening(qheating_rates))
170 [&] (MultiFab& wide) { wide.FillBoundary(geom.periodicity()); })
172 const MultiFab* u_star_src = (u_star_wide) ? u_star_wide.get() : SurfLayer->get_u_star(level);
173 const MultiFab* t_star_src = (t_star_wide) ? t_star_wide.get() : SurfLayer->get_t_star(level);
174 const MultiFab* q_star_src = (q_star_wide) ? q_star_wide.get() : SurfLayer->get_q_star(level);
175 const MultiFab* olen_src = (olen_wide) ? olen_wide.get() : SurfLayer->get_olen(level);
176 const MultiFab* z0_src = (z0_wide) ? z0_wide.get() : SurfLayer->get_z0(level);
177 const MultiFab* qheat_src = (qheat_wide) ? qheat_wide.get() : qheating_rates;
180 int ng_avail = std::min({cons_in.nGrowVect()[0], cons_in.nGrowVect()[1],
181 xvel.nGrowVect()[0],
xvel.nGrowVect()[1],
182 yvel.nGrowVect()[0],
yvel.nGrowVect()[1],
183 u_star_src->nGrowVect()[0], u_star_src->nGrowVect()[1],
184 olen_src->nGrowVect()[0], olen_src->nGrowVect()[1],
185 (terrain_blank) ? terrain_blank->nGrowVect()[0] : 1000,
186 (terrain_blank) ? terrain_blank->nGrowVect()[1] : 1000});
189 auto limit_by = [&ng_avail] (
const auto* mf) {
190 if (mf) { ng_avail = std::min({ng_avail, mf->nGrowVect()[0], mf->nGrowVect()[1]}); }
192 limit_by(t_star_src);
193 limit_by(q_star_src);
194 limit_by(SurfLayer->get_mac_avg(level, 3));
195 limit_by(SurfLayer->get_mac_avg(level, 4));
196 limit_by(SurfLayer->get_mac_avg(level, 6));
198 limit_by(SurfLayer->get_lmask(level));
199 limit_by(z_phys_nd.get());
201 if (ng_pblh > ng_avail) {
203 +
" needs " + std::to_string(ng_pblh) +
" halo columns, but the fields the "
204 "PBLH passes read carry only " + std::to_string(ng_avail)
205 +
"; reduce erf.pblh_smoothing_passes to at most " + std::to_string(ng_avail));
210 #pragma omp parallel if (Gpu::notInLaunchRegion())
213 for (MFIter mfi(eddyViscosity,
TileNoZ()); mfi.isValid(); ++mfi) {
216 const Box& gbx = mfi.growntilebox(IntVect(1,1,0));
218 gbx.bigEnd(2) ==
khi );
236 const Box xybx = PerpendicularBox<ZDir>(gbx, IntVect{0, 0, 0});
246 ? amrex::grow(mfi.tilebox(), IntVect(ng_pblh,ng_pblh,0)) : gbx;
247 const Box xybx_work = PerpendicularBox<ZDir>(gbx_work, IntVect{0, 0, 0});
248 const Box xybx_tile = PerpendicularBox<ZDir>(mfi.tilebox(), IntVect{0, 0, 0});
249 FArrayBox pbl_height_corrector(xybx_work, 1, The_Async_Arena());
250 IArrayBox pbl_index(xybx_work, 1, The_Async_Arena());
251 IArrayBox pbl_index_zero_ri(xybx_work, 1, The_Async_Arena());
252 FArrayBox hgamt_fab(xybx_work, 1, The_Async_Arena());
253 FArrayBox hgamq_fab(xybx_work, 1, The_Async_Arena());
254 FArrayBox hgamu_fab(xybx_work, 1, The_Async_Arena());
255 FArrayBox hgamv_fab(xybx_work, 1, The_Async_Arena());
256 FArrayBox wstar_fab(xybx_work, 1, The_Async_Arena());
257 FArrayBox vpert_fab(xybx_work, 1, The_Async_Arena());
258 FArrayBox entr_fab(xybx_work, 1, The_Async_Arena());
259 IArrayBox cloud_top_fab(xybx_work, 1, The_Async_Arena());
260 FArrayBox wstar3_down_fab(xybx_work, 1, The_Async_Arena());
261 FArrayBox sflux_fab(xybx_work, 1, The_Async_Arena());
262 FArrayBox wstar3_fab(xybx_work, 1, The_Async_Arena());
263 FArrayBox zol1_fab(xybx_work, 1, The_Async_Arena());
264 FArrayBox sfcflg_fab(xybx_work, 1, The_Async_Arena());
268 vpert_fab.setVal<RunOn::Device>(
zero);
269 sflux_fab.setVal<RunOn::Device>(
zero);
270 wstar3_fab.setVal<RunOn::Device>(
zero);
271 wstar3_down_fab.setVal<RunOn::Device>(
zero);
272 sfcflg_fab.setVal<RunOn::Device>(
zero);
273 hgamt_fab.setVal<RunOn::Device>(
zero);
274 hgamq_fab.setVal<RunOn::Device>(
zero);
275 hgamu_fab.setVal<RunOn::Device>(
zero);
276 hgamv_fab.setVal<RunOn::Device>(
zero);
277 wstar_fab.setVal<RunOn::Device>(
zero);
278 entr_fab.setVal<RunOn::Device>(
zero);
279 pbl_height_corrector.setVal<RunOn::Device>(
zero);
280 const auto& pblh_corr_arr = pbl_height_corrector.array();
281 const auto& pbli_arr = pbl_index.array();
282 const auto& pbli_zero_arr = pbl_index_zero_ri.array();
283 const auto& hgamt_arr = hgamt_fab.array();
284 const auto& hgamq_arr = hgamq_fab.array();
285 const auto& hgamu_arr = hgamu_fab.array();
286 const auto& hgamv_arr = hgamv_fab.array();
287 const auto& wstar_arr = wstar_fab.array();
288 const auto& vpert_arr = vpert_fab.array();
289 const auto& entr_arr = entr_fab.array();
290 const auto& cloud_top_arr = cloud_top_fab.array();
291 const auto& wstar3_down_arr = wstar3_down_fab.array();
292 const auto& sflux_arr = sflux_fab.array();
293 const auto& wstar3_arr = wstar3_fab.array();
294 const auto& zol1_arr = zol1_fab.array();
295 const auto& sfcflg_arr = sfcflg_fab.array();
298 const auto& cell_data = cons_in.const_array(mfi);
299 const auto& uvel =
xvel.const_array(mfi);
300 const auto& vvel =
yvel.const_array(mfi);
304 const auto& u_star_arr = u_star_src->const_array(mfi);
305 const auto& t_star_arr = t_star_src->const_array(mfi);
306 const auto& q_star_arr = q_star_src->const_array(mfi);
307 const auto& l_obuk_arr = olen_src->const_array(mfi);
308 const auto& t10av_arr = SurfLayer->get_mac_avg(level, 3)->const_array(mfi);
309 const auto& q10av_arr = SurfLayer->get_mac_avg(level, 4)->const_array(mfi);
310 const auto& ws10av_arr = SurfLayer->get_mac_avg(level, 6)->const_array(mfi);
311 const auto& z0_arr = z0_src->const_array(mfi);
314 const auto& lmask_arr = (SurfLayer->get_lmask(level)) ?
315 SurfLayer->get_lmask(level)->const_array(mfi) :
328 const bool l_ib = turbChoice.
pbl_ib_aware && (terrain_blank !=
nullptr);
330 "erf.pbl_ib_aware is not supported with terrain-fitted coordinates");
331 const Array4<Real const> blank_arr = l_ib ? terrain_blank->const_array(mfi) : Array4<Real const>{};
332 IArrayBox ksurf_fab(xybx_work, 1, The_Async_Arena());
333 FArrayBox zib_fab(xybx_work, 1, The_Async_Arena());
334 FArrayBox pblh_floor_fab(xybx_work, 1, The_Async_Arena());
335 IArrayBox pbl_open_fab(xybx_work, 1, The_Async_Arena());
336 FArrayBox us_eff_fab(xybx_work, 1, The_Async_Arena()), ts_eff_fab(xybx_work, 1, The_Async_Arena());
337 FArrayBox qs_eff_fab(xybx_work, 1, The_Async_Arena()), ol_eff_fab(xybx_work, 1, The_Async_Arena());
338 FArrayBox t10_eff_fab(xybx_work, 1, The_Async_Arena()), q10_eff_fab(xybx_work, 1, The_Async_Arena());
339 FArrayBox ws10_eff_fab(xybx_work, 1, The_Async_Arena()), z0_eff_fab(xybx_work, 1, The_Async_Arena());
340 const auto& ksurf_arr = ksurf_fab.array();
341 const auto& zib_arr = zib_fab.array();
342 const auto& pblh_floor_arr = pblh_floor_fab.array();
343 const auto& pbl_open_arr = pbl_open_fab.array();
344 const auto& us_eff_arr = us_eff_fab.array();
const auto& ts_eff_arr = ts_eff_fab.array();
345 const auto& qs_eff_arr = qs_eff_fab.array();
const auto& ol_eff_arr = ol_eff_fab.array();
346 const auto& t10_eff_arr = t10_eff_fab.array();
const auto& q10_eff_arr = q10_eff_fab.array();
347 const auto& ws10_eff_arr = ws10_eff_fab.array();
const auto& z0_eff_arr = z0_eff_fab.array();
349 const Real dz_ib = geom.CellSize(2);
351 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
355 for (
int kk =
klo; kk <=
khi; ++kk) {
if (blank_arr(i, j, kk) >=
Real(0.5)) {
ks = kk + 1; } }
358 ksurf_arr(i, j, 0) =
ks;
359 zib_arr(i, j, 0) = (
ks -
klo) * dz_ib;
361 const Real u_top =
myhalf * (uvel(i, j,
ks) + uvel(i + 1, j,
ks));
362 const Real v_top =
myhalf * (vvel(i, j,
ks) + vvel(i, j + 1,
ks));
363 const Real ws_top = std::sqrt(u_top * u_top + v_top * v_top);
364 us_eff_arr(i, j, 0) = amrex::max(
KAPPA * ws_top / std::log(
myhalf * dz_ib / z0_ib),
Real(1.0e-3));
365 ts_eff_arr(i, j, 0) =
Real(0);
366 qs_eff_arr(i, j, 0) =
Real(0);
371 ws10_eff_arr(i, j, 0) = ws_top;
372 z0_eff_arr(i, j, 0) = z0_ib;
374 us_eff_arr(i, j, 0) = u_star_arr(i, j, 0);
375 ts_eff_arr(i, j, 0) = t_star_arr(i, j, 0);
376 qs_eff_arr(i, j, 0) = q_star_arr(i, j, 0);
377 ol_eff_arr(i, j, 0) = l_obuk_arr(i, j, 0);
378 t10_eff_arr(i, j, 0) = t10av_arr(i, j, 0);
379 q10_eff_arr(i, j, 0) = q10av_arr(i, j, 0);
380 ws10_eff_arr(i, j, 0) = ws10av_arr(i, j, 0);
381 z0_eff_arr(i, j, 0) = z0_arr(i, j, 0);
385 const Array4<Real const> z_nd_arr = z_phys_nd->array(mfi);
388 const Array4<Real const> qheat_arr = (qheat_src !=
nullptr)
389 ? qheat_src->const_array(mfi)
390 : Array4<Real const>{};
391 const bool has_qheating_rates = (qheating_rates !=
nullptr);
402 FArrayBox rib_base_fab(gbx_work, 1, The_Async_Arena());
403 FArrayBox rib_enhan_fab(gbx_work, 1, The_Async_Arena());
404 const auto& rib_base_arr = rib_base_fab.array();
405 const auto& rib_enhan_arr = rib_enhan_fab.array();
407 BL_PROFILE_VAR(
"YSUNew_Rib_Precompute", prof_rib_precomp);
408 ParallelFor(gbx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
410 const int ksrf = ksurf_arr(i, j, 0);
411 const Real zib = zib_arr(i, j, 0);
416 const amrex::Real t_enh = t_layer_v + vpert_arr(i,j,0);
417 const amrex::Real z_sfc = (use_terrain_fitted_coords)
419 const amrex::Real zval = (use_terrain_fitted_coords)
425 const amrex::Real ws2_raw =
fourth * ((uvel(i,j,k)+uvel(i+1,j,k))*(uvel(i,j,k)+uvel(i+1,j,k))
426 + (vvel(i,j,k)+vvel(i,j+1,k))*(vvel(i,j,k)+vvel(i,j+1,k)));
434 rib_base_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_layer_v) / (ws2 * theta_v_klo);
435 rib_enhan_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_enh) / (ws2 * theta_v_klo);
437 BL_PROFILE_VAR_STOP(prof_rib_precomp);
450 BL_PROFILE_VAR(
"YSUNew_SurfFlux_Precompute", prof_sflux_precomp);
451 ParallelFor(xybx_work, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
453 const int ksrf = ksurf_arr(i, j, 0);
455 const Real t_layer = t10_eff_arr(i, j, 0);
458 const Real rhox = rho_sfc;
473 const Real sflux = hfx / (rhox * cp_air) + qfx / rhox * ep1 * t_layer;
474 sflux_arr(i, j, 0) = sflux;
485 const bool sfcflg = (sflux >= -sflux_roundoff);
486 sfcflg_arr(i, j, 0) = sfcflg ?
one :
zero;
495 const Real bfx0 = amrex::max(sflux, zero_d);
496 const Real wstar3 = govrth * bfx0 * pblh_guess;
497 wstar3_arr(i, j, 0) = wstar3;
507 wstar_arr(i, j, 0) = wscale;
512 Real obuk_val = ol_eff_arr(i, j, 0);
516 const Real zl1 = (use_terrain_fitted_coords)
519 Real zol1 = zl1 / obuk_val;
526 zol1_arr(i, j, 0) = zol1;
528 BL_PROFILE_VAR_STOP(prof_sflux_precomp);
540 BL_PROFILE_VAR(
"YSUNew_PBLH_Passes", prof_pblh);
541 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
543 const int ksrf = ksurf_arr(i, j, 0);
548 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
552 const Real z0 = z0_eff_arr(i, j, 0);
553 const Real ws_layer = ws10_eff_arr(i, j, 0);
555 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
563 Real Rib = rib_base_arr(i,j,ksrf);
564 bool above_critical = (Rib >= Ribcr);
567 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
568 if (rib_base_arr(i,j,kk) >= Ribcr) {
570 above_critical =
true;
575 pbli_arr(i, j, 0) = kpbl;
577 BL_PROFILE_VAR_STOP(prof_pblh);
662 constexpr
Real GAMCRQ =
Real(2.e-3);
665 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
667 const int ksrf = ksurf_arr(i, j, 0);
668 const Real zib = zib_arr(i, j, 0);
673 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
677 const Real z0 = z0_eff_arr(i, j, 0);
678 const Real ws_layer = ws10_eff_arr(i, j, 0);
680 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
690 const amrex::Real z_sfc_col = (use_terrain_fitted_coords)
695 const Real z_sfc = (use_terrain_fitted_coords)
698 const Real dz_terrain = (use_terrain_fitted_coords)
701 const Real z_max = (use_terrain_fitted_coords)
704 const Real pblh_max =
Real(0.9) * z_max;
710 pblh_min = amrex::max(z_sfc_col +
Real(0.5)*dz0,
Real(10.0));
712 pblh_min = amrex::max(z_sfc +
Real(0.5) * dz_terrain,
Real(10.0));
719 auto rib_at = [=] (
int kk) {
return rib_enhan_arr(i,j,kk); };
720 auto z_at = [=] (
int kk) {
725 pblh_corr_arr(i, j, 0) = pbl.
pblh;
726 pbli_arr(i, j, 0) = pbl.
kpbl;
729 hgamt_arr(i, j, 0) =
zero;
730 hgamq_arr(i, j, 0) =
zero;
731 wstar_arr(i, j, 0) =
zero;
777 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
779 const int ksrf = ksurf_arr(i, j, 0);
780 cloud_top_arr(i, j, 0) = -1;
783 int kpbl = pbli_arr(i, j, 0);
784 for (
int kk = kpbl - 1; kk >= ksrf; --kk) {
786 if (moisture_indices.
qc >= 0)
787 qc_kk = cell_data(i, j, kk, moisture_indices.
qc) / cell_data(i, j, kk,
Rho_comp);
788 if (moisture_indices.
qi >= 0)
789 qi_kk = cell_data(i, j, kk, moisture_indices.
qi) / cell_data(i, j, kk,
Rho_comp);
791 if (qc_kk + qi_kk > ysu_qcloud_threshold) {
792 cloud_top_arr(i, j, 0) = kk;
799 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
801 cloud_top_arr(i, j, 0) = -1;
807 const int ksrf = ksurf_arr(i, j, 0);
808 const Real t_layer = t10_eff_arr(i, j, 0);
809 Real obuk_val = ol_eff_arr(i, j, 0);
818 const Real HOL = sf * pblh_corr_arr(i, j, 0) / obuk_val;
819 const Real HOL_bounded = amrex::max(amrex::min(HOL,
Real(100.0)),
Real(-100.0));
821 const Real phiM = (obuk_val > 0)
822 ? (1 + 5 * HOL_bounded)
824 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
826 const Real phiM_safe = amrex::max(phiM,
Real(0.01));
832 Real wscale = us_eff_arr(i, j, 0) / phiM_safe;
833 wscale = amrex::max(wscale, us_eff_arr(i, j, 0) /
Real(5.0));
834 wscale = amrex::min(wscale,
Real(16.0) * us_eff_arr(i, j, 0));
839 if (enable_ysu_topdown && cloud_top_arr(i, j, 0) >= ksrf) {
840 int k_cloud_top = cloud_top_arr(i, j, 0);
848 if (has_qheating_rates) {
851 for (
int kk = ksrf; kk <= k_cloud_top; ++kk) {
853 ? (z_nd_arr(i, j, kk+1) - z_nd_arr(i, j, kk))
857 LRAD += -qheat_arr(i, j, kk, 1) * ldz;
866 if (enable_ysu_rad_tend_limiter && has_qheating_rates) {
868 if (!amrex::Math::isfinite(LRAD_raw)) {
873 const amrex::Real lim_mag = ysu_rad_tend_limiter_magnitude;
874 LRAD_limited = amrex::min(LRAD_raw, lim_mag);
875 LRAD_limited = amrex::max(LRAD_limited, -lim_mag);
884 / cell_data(i, j, k_cloud_top,
Rho_comp);
886 wstar3_down = amrex::max(CONST_GRAV_d / t_local * LRAD
888 * pblh_corr_arr(i, j, 0), zero_d);
890 wstar3_down_arr(i, j, 0) = wstar3_down;
893 const Real bfx0_corr = amrex::max(sflux_arr(i, j, 0), zero_d);
894 const Real t_dry = t10_eff_arr(i, j, 0);
895 const Real wstar3_corr = (
CONST_GRAV / t_dry) * bfx0_corr * pblh_corr_arr(i, j, 0);
896 wstar3_arr(i, j, 0) = wstar3_corr;
899 const Real ust3 = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
901 wscale_corr = amrex::min(wscale_corr, us_eff_arr(i, j, 0) *
amrex::Real(16.0));
902 wscale_corr = amrex::max(wscale_corr, us_eff_arr(i, j, 0) /
amrex::Real(5.0));
903 wstar_arr(i, j, 0) = wscale_corr;
909 bool SFCFLG = (sfcflg_arr(i, j, 0) >
zero);
911 const Real hfx_col = -rho_sfc *
amrex::Real(1004.0) * us_eff_arr(i, j, 0) * ts_eff_arr(i, j, 0);
912 const Real gamfac = const_b / (rho_sfc * wscale_corr);
913 const Real HGAMT = (SFCFLG && enable_ysu_countergradient)
914 ? amrex::min(gamfac * hfx_col /
amrex::Real(1004.0), GAMCRT)
919 const Real qfx_col = -rho_sfc * us_eff_arr(i, j, 0) * qs_eff_arr(i, j, 0);
920 const Real HGAMQ_raw = (SFCFLG &&
use_moisture && enable_ysu_countergradient)
923 Real HGAMQ = amrex::min(amrex::max(HGAMQ_raw, zero_d), GAMCRQ);
926 if (lmask_arr && SFCFLG &&
use_moisture && enable_ysu_countergradient) {
927 bool is_land = (lmask_arr(i,j,0) == 1);
928 if (!is_land) HGAMQ =
zero;
932 if (enable_ysu_sat_limiter && moisture_indices.
qv >= 0 && SFCFLG &&
use_moisture && enable_ysu_countergradient) {
933 Real qv_klo = cell_data(i, j, ksrf, moisture_indices.
qv) / cell_data(i, j, ksrf,
Rho_comp);
940 Real rh_klo = (qsat_klo >
Real(1.0e-10)) ? (qv_klo / qsat_klo) :
zero;
941 if (rh_klo >
Real(0.95)) {
942 Real rh_scaling = amrex::max(zero_d, (
one - rh_klo) /
Real(0.05));
949 if (pbli_arr(i, j, 0) <= ksrf + 1) {
950 hgamt_arr(i, j, 0) =
zero;
951 hgamq_arr(i, j, 0) =
zero;
952 hgamu_arr(i, j, 0) =
zero;
953 hgamv_arr(i, j, 0) =
zero;
954 vpert_arr(i, j, 0) =
zero;
956 const Real pblh = pblh_corr_arr(i, j, 0);
957 hgamt_arr(i, j, 0) = (enable_ysu_countergradient) ? HGAMT / pblh :
zero;
958 hgamq_arr(i, j, 0) = (enable_ysu_countergradient &&
use_moisture) ? HGAMQ / pblh :
zero;
972 hgamu_arr(i, j, 0) =
zero;
973 hgamv_arr(i, j, 0) =
zero;
974 if (SFCFLG && enable_ysu_countergradient) {
975 const Real wspd_sfc = ws10_eff_arr(i, j, 0);
977 wscale = wstar_arr(i, j, 0);
978 const Real wstar3 = wstar3_arr(i, j, 0);
980 const Real wscale4 = amrex::max(wscale * wscale * wscale * wscale,
987 const Real u_klo =
myhalf * (uvel(i, j, ksrf) + uvel(i+1, j, ksrf));
988 const Real v_klo =
myhalf * (vvel(i, j, ksrf) + vvel(i, j+1, ksrf));
989 hgamu_arr(i, j, 0) = brint * u_klo / pblh;
990 hgamv_arr(i, j, 0) = brint * v_klo / pblh;
999 if (enable_ysu_countergradient) {
1002 const Real zl1_col = (use_terrain_fitted_coords)
1006 const Real height_lim = amrex::min(zl1_col / (sfcfrac_h * pblh), one_d);
1009 const Real VPERT_capped = enable_ysu_unbounded_vpert
1011 : amrex::min(VPERT_raw, GAMCRT);
1012 vpert_arr(i, j, 0) = amrex::max(VPERT_capped, zero_d) * height_lim;
1014 vpert_arr(i, j, 0) =
zero;
1032 BL_PROFILE_VAR(
"YSUNew_Rib_Recompute", prof_rib_recomp);
1033 ParallelFor(gbx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1035 const int ksrf = ksurf_arr(i, j, 0);
1036 const Real zib = zib_arr(i, j, 0);
1041 const amrex::Real t_enh = t_layer_v + vpert_arr(i,j,0);
1042 const amrex::Real z_sfc = (use_terrain_fitted_coords)
1044 const amrex::Real zval = (use_terrain_fitted_coords)
1050 const amrex::Real ws2_raw =
fourth * ((uvel(i,j,k)+uvel(i+1,j,k))*(uvel(i,j,k)+uvel(i+1,j,k))
1051 + (vvel(i,j,k)+vvel(i,j+1,k))*(vvel(i,j,k)+vvel(i,j+1,k)));
1057 rib_enhan_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_enh) / (ws2 * theta_v_klo);
1059 BL_PROFILE_VAR_STOP(prof_rib_recomp);
1068 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1070 const int ksrf = ksurf_arr(i, j, 0);
1071 const Real zib = zib_arr(i, j, 0);
1075 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
1079 const Real z0 = z0_eff_arr(i, j, 0);
1080 const Real ws_layer = ws10_eff_arr(i, j, 0);
1082 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
1087 const Real z_sfc = (use_terrain_fitted_coords)
1090 const Real dz_terrain = (use_terrain_fitted_coords)
1093 const Real z_max = (use_terrain_fitted_coords)
1096 const Real pblh_max =
Real(0.9) * z_max;
1102 const amrex::Real z_sfc_col = (use_terrain_fitted_coords)
1105 pblh_min = amrex::max(z_sfc_col +
Real(0.5)*dz0,
Real(10.0));
1107 pblh_min = amrex::max(z_sfc +
Real(0.5) * dz_terrain,
Real(10.0));
1109 pblh_floor_arr(i, j, 0) = pblh_min;
1114 auto rib_at = [=] (
int kk) {
return rib_enhan_arr(i,j,kk); };
1115 auto z_at = [=] (
int kk) {
1120 pblh_corr_arr(i, j, 0) = pbl.
pblh;
1121 pbli_arr(i, j, 0) = pbl.
kpbl;
1122 pbl_open_arr(i, j, 0) = pbl.
crossed ? 0 : 1;
1135 geom.Domain(), geom.periodicity());
1140 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept {
1141 pblh_corr_arr(i, j, 0) = amrex::max(pblh_corr_arr(i, j, 0), pblh_floor_arr(i, j, 0));
1151 auto pblh_out = pblh_mf.array(mfi);
1152 const Box& tbx = mfi.tilebox();
1153 ParallelFor(tbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
1154 pblh_out(i, j, k) = pblh_corr_arr(i, j, 0);
1165 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1167 const int ksrf = ksurf_arr(i, j, 0);
1168 const Real zib = zib_arr(i, j, 0);
1169 const int kpblold = pbli_arr(i,j,0);
1170 bool definebrup =
false;
1173 const Real thermalli =
GetThetal(i, j, ksrf, cell_data, moisture_indices);
1176 for (
int kk = kpblold; kk <
khi; ++kk) {
1178 const Real ws2_raw =
fourth * ((uvel(i,j,kk)+uvel(i+1,j,kk))*(uvel(i,j,kk)+uvel(i+1,j,kk))
1179 + (vvel(i,j,kk)+vvel(i,j+1,kk))*(vvel(i,j,kk)+vvel(i,j+1,kk)));
1186 const Real z_sfc = (use_terrain_fitted_coords)
1189 const Real zval_kk = (use_terrain_fitted_coords)
1192 const Real zrel_kk = amrex::max(zval_kk - z_sfc,
amrex::Real(1.0e-4));
1195 const Real thlix_kk =
GetThetal(i, j, kk, cell_data, moisture_indices);
1196 const Real thlix_klo =
GetThetal(i, j, ksrf, cell_data, moisture_indices);
1199 const Real bruptmp =
CONST_GRAV * zrel_kk * (thlix_kk - thermalli) / (ws2 * thlix_klo);
1202 const bool stable = (bruptmp >=
zero);
1205 pbli_arr(i,j,0) = kk;
1216 pbli_arr(i,j,0) = amrex::min(pbli_arr(i,j,0), izmax);
1243 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1245 const int ksrf = ksurf_arr(i, j, 0);
1248 int kpbl_zero = ksrf;
1249 Real Rib = rib_enhan_arr(i,j,ksrf);
1250 bool above_critical = (Rib >= Ribcr_zero);
1253 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
1254 if (rib_enhan_arr(i,j,kk) >= Ribcr_zero) { kpbl_zero = kk; above_critical =
true;
break; }
1257 pbli_zero_arr(i, j, 0) = kpbl_zero;
1259 BL_PROFILE_VAR_STOP(prof_pblh);
1268 ParallelFor(xybx, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1270 const int ksrf = ksurf_arr(i, j, 0);
1271 entr_arr(i,j,0) =
zero;
1272 if (!enable_ysu_entrainment)
return;
1276 if (pbl_open_arr(i,j,0) != 0)
return;
1278 const int kpbl = pbli_arr(i,j,0);
1280 const Real pblh = pblh_corr_arr(i,j,0);
1281 const Real wscale = wstar_arr(i,j,0);
1287 const Real wstar3_col = wstar3_arr(i,j,0);
1293 const Real thvx_klo =
GetThetav(i, j, ksrf, cell_data, moisture_indices);
1298 const int kpbl_p1 = amrex::min(kpbl + 1, izmax);
1299 const Real thvx_kpbl =
GetThetav(i, j, kpbl, cell_data, moisture_indices);
1300 const Real thvx_kpbl_p1 =
GetThetav(i, j, kpbl_p1, cell_data, moisture_indices);
1301 const Real dthvx = amrex::max(thvx_kpbl_p1 - thvx_kpbl,
amrex::Real(1.0e-2));
1305 const Real we = amrex::max(bfxpbl / dthvx, -std::sqrt(wm2));
1308 const Real met_h = (use_terrain_fitted_coords)
1310 const Real dz_kpbl = met_h / dz_inv;
1320 Real K_entr_final = (we <
zero) ? rho_kpbl * (-we) * dz_kpbl :
zero;
1323 const int k_below = amrex::max(kpbl - 1, ksrf);
1325 Real qc_below = (moisture_indices.
qc >= 0)
1326 ? cell_data(i, j, k_below, moisture_indices.
qc) / rho_k :
zero;
1327 Real qi_below = (moisture_indices.
qi >= 0)
1328 ? cell_data(i, j, k_below, moisture_indices.
qi) / rho_k :
zero;
1332 if ((qc_below + qi_below) > cloud_thresh_entr && kpbl >= ksrf + 2) {
1341 const int k_p2 = amrex::min(kpbl + 1, izmax);
1342 auto thlix_v = [=] (
int kk) {
1345 const Real qv_kk = (moisture_indices.
qv >= 0)
1346 ? cell_data(i, j, kk, moisture_indices.
qv) / rho_kk :
zero;
1347 const Real qc_kk = (moisture_indices.
qc >= 0)
1348 ? cell_data(i, j, kk, moisture_indices.
qc) / rho_kk :
zero;
1349 return GetThetal(i, j, kk, cell_data, moisture_indices)
1350 + theta_kk *
epsv * (qv_kk + qc_kk);
1352 const Real thlix_kbelow = thlix_v(k_below);
1353 const Real thlix_kp2 = thlix_v(k_p2);
1355 const Real dthvx_li = amrex::max(thlix_kp2 - thlix_kbelow,
amrex::Real(0.1));
1361 * xlv_over_cp * qc_below / dthvx_li,
1366 const Real we_cloud = amrex::max(bfxpbl / dthvx_li, -std::sqrt(wm2));
1370 const Real bfx0_cloud = amrex::max(sflux_arr(i, j, 0), zero_d);
1371 const Real bfxpbl_cloud = -ent_eff * bfx0_cloud;
1372 const Real we_cloud_top = amrex::max(bfxpbl_cloud / dthvx_li,
1376 we_final = we_cloud + we_cloud_top;
1379 K_entr_final = (we_final <
zero) ? rho_kpbl * (-we_final) * dz_kpbl :
zero;
1386 entr_arr(i,j,0) = amrex::min(K_entr_final, K_cap);
1390 const int kpbl_current = pbli_arr(i, j, 0);
1394 if (moisture_indices.
qc >= 0)
1395 qc_kpbl = cell_data(i, j, kpbl_current, moisture_indices.
qc) / cell_data(i, j, kpbl_current,
Rho_comp);
1396 if (moisture_indices.
qi >= 0)
1397 qi_kpbl = cell_data(i, j, kpbl_current, moisture_indices.
qi) / cell_data(i, j, kpbl_current,
Rho_comp);
1400 if ((qc_kpbl + qi_kpbl) > ysu_qcloud_threshold) {
1401 pbli_arr(i, j, 0) = amrex::min(kpbl_current + 1, izmax);
1408 FArrayBox K_down_fab(gbx, 1, The_Async_Arena());
1409 K_down_fab.setVal<RunOn::Device>(
zero);
1410 const auto& K_down_arr = K_down_fab.array();
1412 if (enable_ysu_topdown) {
1413 ParallelFor(gbx, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1415 const int ksrf = ksurf_arr(i, j, 0);
1416 const Real zib = zib_arr(i, j, 0);
1417 K_down_arr(i,j,k) =
zero;
1418 if (k >= pbli_arr(i,j,0) || k < ksrf)
return;
1422 const amrex::Real zval = (use_terrain_fitted_coords)
1425 const amrex::Real z_sfc = (use_terrain_fitted_coords)
1433 const amrex::Real wstar3_down_col = wstar3_down_arr(i,j,0);
1435 ? std::cbrt(wstar3_down_col)
1437 const amrex::Real zfac_up = amrex::max(zrel / pblh_rel, zero_d);
1438 K_down_arr(i,j,k) =
rho * wstar_down_eff *
KAPPA
1439 * amrex::max(pblh_rel - zrel, zero_d)
1440 * zfac_up * zfac_up;
1446 const Array4<Real>& K_turb = eddyViscosity.array(mfi);
1457 BL_PROFILE_VAR(
"YSUNew_Kprofile", prof_kprof);
1458 ParallelFor(gbx, [=, wstar3_arr_cap=wstar3_arr, zol1_arr_cap=zol1_arr, sfcflg_arr_cap=sfcflg_arr,
1459 zero_d=
zero, one_d=
one, two_d=
two] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1461 const int ksrf = ksurf_arr(i, j, 0);
1462 const Real zib = zib_arr(i, j, 0);
1465 if (rho_guard <=
Real(0)) {
1477 Real obuk_val = ol_eff_arr(i, j, 0);
1482 const Real zval = (use_terrain_fitted_coords)
1495 const Real met_h_zeta = (use_terrain_fitted_coords)
1497 const Real dz_terrain = met_h_zeta / dz_inv;
1518 constexpr
Real qc_threshold =
Real(1.0e-5);
1523 if (moisture_indices.
qc >= 0) {
1524 qc_mix = cell_data(i, j, k, moisture_indices.
qc) /
rho;
1526 if (moisture_indices.
qi >= 0) {
1527 qi_mix = cell_data(i, j, k, moisture_indices.
qi) /
rho;
1530 const Real total_qcloud = qc_mix + qi_mix;
1531 const bool has_cloud = (total_qcloud > qc_threshold);
1540 if (k < pbli_extent) {
1561 bool SFCFLG = (sfcflg_arr_cap(i, j, 0) >
zero);
1567 const Real HOL = sf * pblh_corr_arr(i, j, 0) / obuk_val;
1568 const Real HOL_bounded = amrex::max(amrex::min(HOL,
Real(100.0)),
Real(-100.0));
1571 const Real phiM = (obuk_val > 0)
1572 ? (1 + 5 * HOL_bounded)
1574 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
1581 const Real phit = (obuk_val > 0)
1582 ? (1 + 5 * HOL_bounded)
1584 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
1593 Real phit_cloud = phit;
1594 Real phiM_cloud = phiM;
1595 if (has_cloud && obuk_val >
zero) {
1599 Real reduction_factor =
one -
Real(0.15) * amrex::min(total_qcloud / qc_threshold, one_d);
1601 phiM_cloud =
one +
Real(5.0) * reduction_factor * sf * pblh_corr_arr(i, j, 0) / obuk_val;
1602 phit_cloud =
one +
Real(5.0) * reduction_factor * sf * pblh_corr_arr(i, j, 0) / obuk_val;
1603 }
else if (has_cloud && obuk_val <=
zero) {
1607 Real cloud_boost =
Real(1.0) +
Real(0.05) * amrex::min(total_qcloud / qc_threshold, one_d);
1610 phiM_cloud = std::pow(
1611 amrex::max(one_d -
Real(16.0) * HOL_bounded / cloud_boost,
Real(0.01)),
1613 phit_cloud = std::pow(
1614 amrex::max(one_d -
Real(16.0) * HOL_bounded / cloud_boost,
Real(0.01)),
1619 const Real phiM_eff = phiM_cloud;
1620 const Real phit_eff = phit_cloud;
1633 const Real conpr = bfac *
KAPPA * sfcfrac;
1636 const Real zq_kp1_prandtl = zval +
myhalf * dz_terrain;
1640 const Real prfac = SFCFLG ? conpr :
zero;
1645 const Real wstar3_col = wstar3_arr_cap(i, j, 0);
1646 const Real ust3 = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
1649 const Real wstar3_2 = wstar3_down_arr(i, j, 0);
1653 const Real wstar_tot3 = wstar3_col + wstar3_2;
1661 const Real pblh = pblh_corr_arr(i, j, 0);
1662 const Real sfclayer = sfcfrac * pblh;
1663 const Real zdiff = amrex::max(zq_kp1_prandtl - sfclayer, zero_d);
1664 const Real prnumfac =
amrex::Real(-3.0) * zdiff * zdiff / (pblh * pblh);
1670 Real prnum0 = (phit_eff / phiM_eff) + prfac;
1671 prnum0 = amrex::min(amrex::max(prnum0, prmin_wrf), prmax_wrf);
1675 Real prnum0_heat = prnum0 / (
one + prfac2 *
KAPPA * sfcfrac);
1676 prnum0_heat = amrex::min(amrex::max(prnum0_heat, prmin_wrf), prmax_wrf);
1677 const Real Prt =
one + (prnum0_heat -
one) * std::exp(prnumfac);
1681 const Real prnum_q =
one + (prnum0 -
one) * std::exp(prnumfac);
1698 const Real zq_kp1 = zval +
myhalf * dz_terrain;
1706 const Real zl1 = (use_terrain_fitted_coords)
1713 const Real pblh_rel = amrex::max(pblh_corr_arr(i, j, 0) - zl1,
amrex::Real(1.0e-4));
1714 const Real zfac = amrex::min(
1715 amrex::max(one_d - (zq_kp1 - zl1) / pblh_rel, zfacmin), one_d);
1719 const Real ust3_wscale = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
1723 wscalek_val = std::cbrt(ust3_wscale +
amrex::Real(8.0) *
KAPPA * wstar3_col * (
one - zfac));
1729 constexpr
Real ckz_pbl =
Real(0.001);
1730 const Real K_base = ckz_pbl * dz_terrain *
rho;
1732 K_turb(i, j, k,
EddyDiff::Mom_v) = K_base +
rho * wscalek_val *
KAPPA * (zq_kp1 - zib) * std::pow(zfac, pfac);
1743 if (enable_ysu_topdown && k < pbli_arr(i, j, 0)) {
1754 const Real zq_kp1_stable = zval +
myhalf * dz_terrain;
1757 const Real zl1_stable = (use_terrain_fitted_coords)
1763 const Real pblh_rel_stable = amrex::max(pblh_corr_arr(i, j, 0) - zl1_stable,
amrex::Real(1.0e-4));
1764 const Real zfac_stable = amrex::min(
1765 amrex::max(one_d - (zq_kp1_stable - zl1_stable) / pblh_rel_stable, zfacmin_stable), one_d);
1769 const Real zol1_stable = zol1_arr_cap(i, j, 0);
1770 const Real zol_ratio = (zq_kp1_stable - zib) / (zl1_stable - zib);
1771 const Real phim_stable_arg = zol1_stable * zol_ratio;
1776 const Real phim_stable = (enable_qnse_d >
Real(0.5))
1777 ? ((
one + qnse_am_d * phim_stable_arg) / (
one + qnse_bm_d * phim_stable_arg))
1779 const Real wscalek_stable = amrex::max(
1780 us_eff_arr(i, j, 0) / amrex::max(phim_stable,
amrex::Real(0.01)),
1784 constexpr
Real ckz_pbl_stable =
Real(0.001);
1785 const Real K_base_stable = ckz_pbl_stable * dz_terrain *
rho;
1787 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);
1792 const Real prnum_stable =
one + (prnum0 -
one) * std::exp(prnumfac);
1801 }
else if (k >= pbli_extent) {
1806 const Real lambda_min =
Real(30.0);
1807 const Real lambda_max =
Real(300.0);
1808 const Real lambdadz = amrex::min(amrex::max(
Real(0.1) * dz_terrain, lambda_min), lambda_max);
1809 const Real lscale = (lambdadz *
KAPPA * zval) / (lambdadz +
KAPPA * zval);
1810 Real dthetadz, dudz, dvdz;
1811 ComputeVerticalDerivativesPBL(i, j, k, uvel, vvel, cell_data, izmin, izmax, pbl_derivative_dz_inv(i,j,k),
1812 c_ext_dir_on_zlo, c_ext_dir_on_zhi, u_ext_dir_on_zlo,
1813 u_ext_dir_on_zhi, v_ext_dir_on_zlo, v_ext_dir_on_zhi, dthetadz,
1814 dudz, dvdz, moisture_indices, pbl_strat);
1823 const Real zrel_sl = amrex::max(zval - zib,
Real(1.0e-4));
1825 const Real qv = (moisture_indices.
qv >= 0) ?
1826 cell_data(i, j, k, moisture_indices.
qv) /
rho :
zero;
1828 sl.
u_star = us_eff_arr(i, j, 0);
1833 sl.
zeta = zrel_sl / obuk_val;
1838 const Real dudz_safe = (k < izmax) ? dudz :
zero;
1839 const Real dvdz_safe = (k < izmax) ? dvdz :
zero;
1843 const Real wind_shear = dudz_safe * dudz_safe + dvdz_safe * dvdz_safe;
1844 const Real wind_shear_safe = std::max(wind_shear,
Real(1.0e-8));
1850 const Real theta_v =
GetThetav(i, j, k, cell_data, moisture_indices);
1851 const Real dtheta_v_dz = dthetadz;
1864 Real grad_Ri =
CONST_GRAV / theta_v * dtheta_v_dz / wind_shear_safe;
1865 grad_Ri = std::max(std::min(grad_Ri,
Real(100.0)), -
Real(100.0));
1873 Real qc_k = (moisture_indices.
qc >= 0) ? cell_data(i,j,k, moisture_indices.
qc)/rho_k :
zero;
1874 Real qc_kp1 = (moisture_indices.
qc >= 0) ? cell_data(i,j,k+1,moisture_indices.
qc)/rho_kp1 :
zero;
1875 Real qi_k = (moisture_indices.
qi >= 0) ? cell_data(i,j,k, moisture_indices.
qi)/rho_k :
zero;
1876 Real qi_kp1 = (moisture_indices.
qi >= 0) ? cell_data(i,j,k+1,moisture_indices.
qi)/rho_kp1 :
zero;
1879 if ((qc_k + qi_k) > cloud_thresh && (qc_kp1 + qi_kp1) > cloud_thresh) {
1886 const Real qv_k_mri = (moisture_indices.
qv >= 0)
1887 ? cell_data(i,j,k, moisture_indices.
qv) / rho_k :
zero;
1888 const Real qv_kp1_mri = (moisture_indices.
qv >= 0)
1889 ? cell_data(i,j,k+1,moisture_indices.
qv) / rho_kp1 :
zero;
1894 const Real qmean =
myhalf * (qv_k_mri + qv_kp1_mri);
1900 const Real chi =
xlv *
xlv * qmean / (
cp * rv * tmean * tmean);
1923 const Real grad_Ri_safe = amrex::max(grad_Ri, -
Real(100.0));
1924 const Real fm = (grad_Ri_safe > 0)
1926 : 1 - 8 * grad_Ri_safe / (1 +
Real(1.746) * std::sqrt(amrex::max(-grad_Ri_safe, zero_d)));
1927 const Real ft = (grad_Ri_safe > 0)
1929 : 1 - 8 * grad_Ri_safe / (1 +
Real(1.286) * std::sqrt(amrex::max(-grad_Ri_safe, zero_d)));
1930 const Real rl2wsp =
rho * lscale * lscale * std::sqrt(wind_shear);
1934 if (grad_Ri_safe > 0) {
1953 if (k == pbli_arr(i,j,0)) {
1979 Real rhoKmin, rhoKmax;
1985 constexpr
Real Kmax =
Real(1000.0);
1986 rhoKmin = ckz * dz_terrain *
rho;
1987 rhoKmax =
rho * Kmax;
1994 rhoKmin =
rho * Kmin;
1995 rhoKmax =
rho * Kmax;
1998 #ifdef ERF_USE_WINDFARM
2012 if (k < pbli_extent) {
2027 std::min(K_turb(i, j, k,
EddyDiff::Q_v), rhoKmax), rhoKmin);
2053 if (k < pbli_extent) {
2067 BL_PROFILE_VAR_STOP(prof_kprof);
2071 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int ) noexcept
2096 SurfLayer->set_pblh(level, pblh_mf);
constexpr amrex::Real epsv
Definition: ERF_Constants.H:56
constexpr amrex::Real KAPPA
Definition: ERF_Constants.H:71
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:72
constexpr amrex::Real immersed_neutral_obukhov_length
Definition: ERF_Constants.H:31
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:53
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:12
const bool use_moisture
Definition: ERF_InitCustomPert_ABL.H:71
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
const int khi
Definition: ERF_InitCustomPert_Bubble.H:25
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
const int klo
Definition: ERF_InitCustomPert_KE.H:9
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:93
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetal(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:127
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 real_eps
Definition: ERF_NumericalConstants.H:34
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
std::unique_ptr< amrex::MultiFab > WidenForPBLH(const amrex::MultiFab &src, const int ng, const std::function< void(amrex::MultiFab &)> &fill)
Definition: ERF_PBLModels.H:805
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:309
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:722
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ApplySurfaceLayerGradientsPBL(const PBLSurfaceLayerGradient &sl, amrex::Real &dthetadz, amrex::Real &dudz, amrex::Real &dvdz)
Definition: ERF_PBLModels.H:428
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:391
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE RibCrossing find_rib_crossing(int ksrf, int khi, amrex::Real Ribcr, RibAt const &rib_at, ZAt const &z_at, amrex::Real pblh_min, amrex::Real pblh_max) noexcept
Definition: ERF_PBLRibCrossing.H:50
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:762
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:201
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ yvel_bc
Definition: ERF_IndexDefines.H:127
@ cons_bc
Definition: ERF_IndexDefines.H:110
@ xvel_bc
Definition: ERF_IndexDefines.H:126
@ ext_dir
Definition: ERF_IndexDefines.H:340
@ Theta_v
Definition: ERF_IndexDefines.H:290
@ Turb_lengthscale
Definition: ERF_IndexDefines.H:294
@ HGAMU_v
Definition: ERF_IndexDefines.H:302
@ Q_v
Definition: ERF_IndexDefines.H:293
@ Mom_v
Definition: ERF_IndexDefines.H:289
@ HGAMQ_v
Definition: ERF_IndexDefines.H:301
@ HGAMT_v
Definition: ERF_IndexDefines.H:300
@ HGAMV_v
Definition: ERF_IndexDefines.H:303
@ 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:255
@ yvel
Definition: ERF_IndexDefines.H:256
@ dz
Definition: ERF_AdvanceWDM6.cpp:273
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:264
int qv
water vapor
Definition: ERF_DataStruct.H:262
int qc
cloud liquid water
Definition: ERF_DataStruct.H:263
Functor for inverse vertical spacings for terrain-following grids using cell-center heights.
Definition: ERF_PBLModels.H:668
Definition: ERF_PBLModels.H:371
amrex::Real tstar_v
virtual temperature scale
Definition: ERF_PBLModels.H:373
amrex::Real zeta
stability coordinate z/L
Definition: ERF_PBLModels.H:375
amrex::Real u_star
friction velocity
Definition: ERF_PBLModels.H:372
amrex::Real zval
height of the cell center above the surface
Definition: ERF_PBLModels.H:374
Definition: ERF_PBLRibCrossing.H:11
amrex::Real pblh
PBL height, kept in [pblh_min, pblh_max].
Definition: ERF_PBLRibCrossing.H:13
int kpbl
level where Rib first reaches Ribcr; khi when it never does
Definition: ERF_PBLRibCrossing.H:12
bool crossed
Rib reached Ribcr at or below khi.
Definition: ERF_PBLRibCrossing.H:14
bool enable_mrf_unbounded_vpert
Whether MRF leaves VPERT unlimited by GAMCRT.
Definition: ERF_TurbStruct.H:1050
bool pbl_mrf_use_zero_ri_extent
Whether MRF uses the Ri=0 K-profile extent.
Definition: ERF_TurbStruct.H:1051
StratType pbl_strat_type
Definition: ERF_TurbStruct.H:868
bool enable_vh96_shear_correction
Whether Vogelezang & Holtslag (1996) shear-correction term is enabled.
Definition: ERF_TurbStruct.H:1028
bool enable_ysu_entrainment
Whether YSU entrainment-layer parameterization is enabled.
Definition: ERF_TurbStruct.H:1016
bool enable_ysu_sat_limiter
Whether YSU applies a saturation limiter to moisture countergradient terms.
Definition: ERF_TurbStruct.H:1012
bool enable_ysu_cloud_pblh
Whether YSU cloud-based PBL-height detection is enabled.
Definition: ERF_TurbStruct.H:1018
amrex::Real pbl_mrf_const_b
MRF constant used to compute PBL height.
Definition: ERF_TurbStruct.H:1036
amrex::Real pblh_smoothing_weight
Center-cell weight in PBLH smoothing stencil (must be in [0,1]).
Definition: ERF_TurbStruct.H:1032
amrex::Real ysu_qcloud_threshold
Cloud liquid water threshold for YSUNew [kg/kg].
Definition: ERF_TurbStruct.H:1020
amrex::Real qnse_bm
Definition: ERF_TurbStruct.H:1060
bool enable_qnse_stable_functions
Definition: ERF_TurbStruct.H:1057
bool enable_ysu_countergradient
Whether YSU countergradient corrections are enabled.
Definition: ERF_TurbStruct.H:1008
bool enable_pblh_smoothing
Whether spatial smoothing of diagnosed PBLH is enabled.
Definition: ERF_TurbStruct.H:1030
int pblh_smoothing_passes
Number of PBLH smoothing iterations to apply.
Definition: ERF_TurbStruct.H:1031
amrex::Real pbl_ib_z0
Definition: ERF_TurbStruct.H:1047
bool enable_ysu_topdown
Whether YSU top-down mixing is enabled.
Definition: ERF_TurbStruct.H:1014
bool pbl_ib_aware
Definition: ERF_TurbStruct.H:1046
amrex::Real ysu_rad_tend_limiter_magnitude
Definition: ERF_TurbStruct.H:1026
amrex::Real pbl_ysu_land_Ribcr
Critical bulk Richardson number over land for stable YSU conditions.
Definition: ERF_TurbStruct.H:1004
amrex::Real vh96_shear_const_b
Vogelezang & Holtslag (1996) shear-correction constant b.
Definition: ERF_TurbStruct.H:1029
amrex::Real qnse_am
Definition: ERF_TurbStruct.H:1059
amrex::Real pbl_mrf_sf
MRF surface flux value used to compute PBL height.
Definition: ERF_TurbStruct.H:1037
bool pbl_ysunew_highres_bounds
Whether YSUNew applies high-resolution grid-dependent diffusivity bounds.
Definition: ERF_TurbStruct.H:1023
amrex::Real pbl_ysu_coriolis_freq
Coriolis frequency used by YSU-family PBL schemes.
Definition: ERF_TurbStruct.H:995
bool ysu_moistvars
Whether YSU applies turbulence to moisture variables.
Definition: ERF_TurbStruct.H:1022
bool enable_ysu_terrain_pblh_floor
Whether YSU applies a terrain-following PBL-height floor.
Definition: ERF_TurbStruct.H:1010
bool enable_ysu_rad_tend_limiter
Definition: ERF_TurbStruct.H:1025