Compute vertical eddy viscosity coefficients using the Yonsei University (YSU) boundary layer scheme.
126 int klo = geom.Domain().smallEnd(2);
127 int khi = geom.Domain().bigEnd(2);
128 const int izmin =
klo;
129 const int izmax =
khi;
131 const Real dz = geom.CellSize(2);
132 const Real dz_inv = geom.InvCellSize(2);
133 const auto&
dxInv = geom.InvCellSizeArray();
138 MultiFab pblh_mf(eddyViscosity.boxArray(), eddyViscosity.DistributionMap(), 1, 0);
149 const int ng_avail = std::min({cons_in.nGrowVect()[0], cons_in.nGrowVect()[1],
150 xvel.nGrowVect()[0],
xvel.nGrowVect()[1],
151 yvel.nGrowVect()[0],
yvel.nGrowVect()[1],
152 SurfLayer->get_u_star(level)->nGrowVect()[0],
153 SurfLayer->get_u_star(level)->nGrowVect()[1],
154 SurfLayer->get_olen(level)->nGrowVect()[0],
155 SurfLayer->get_olen(level)->nGrowVect()[1],
156 (terrain_blank) ? terrain_blank->nGrowVect()[0] : 1000,
157 (terrain_blank) ? terrain_blank->nGrowVect()[1] : 1000});
158 if (ng_pblh > ng_avail) {
160 +
" needs " + std::to_string(ng_pblh) +
" halo columns, but the state and "
161 "surface-layer arrays carry only " + std::to_string(ng_avail)
162 +
"; reduce erf.pblh_smoothing_passes to at most " + std::to_string(ng_avail));
167 #pragma omp parallel if (Gpu::notInLaunchRegion())
170 for (MFIter mfi(eddyViscosity,
TileNoZ()); mfi.isValid(); ++mfi) {
173 const Box& gbx = mfi.growntilebox(IntVect(1,1,0));
175 gbx.bigEnd(2) ==
khi );
193 const Box xybx = PerpendicularBox<ZDir>(gbx, IntVect{0, 0, 0});
203 ? amrex::grow(mfi.tilebox(), IntVect(ng_pblh,ng_pblh,0)) : gbx;
204 const Box xybx_work = PerpendicularBox<ZDir>(gbx_work, IntVect{0, 0, 0});
205 const Box xybx_tile = PerpendicularBox<ZDir>(mfi.tilebox(), IntVect{0, 0, 0});
206 FArrayBox pbl_height_corrector(xybx_work, 1, The_Async_Arena());
207 IArrayBox pbl_index(xybx_work, 1, The_Async_Arena());
208 IArrayBox pbl_index_zero_ri(xybx_work, 1, The_Async_Arena());
209 FArrayBox hgamt_fab(xybx_work, 1, The_Async_Arena());
210 FArrayBox hgamq_fab(xybx_work, 1, The_Async_Arena());
211 FArrayBox hgamu_fab(xybx_work, 1, The_Async_Arena());
212 FArrayBox hgamv_fab(xybx_work, 1, The_Async_Arena());
213 FArrayBox wstar_fab(xybx_work, 1, The_Async_Arena());
214 FArrayBox vpert_fab(xybx_work, 1, The_Async_Arena());
215 FArrayBox entr_fab(xybx_work, 1, The_Async_Arena());
216 IArrayBox cloud_top_fab(xybx_work, 1, The_Async_Arena());
217 FArrayBox wstar3_down_fab(xybx_work, 1, The_Async_Arena());
218 FArrayBox sflux_fab(xybx_work, 1, The_Async_Arena());
219 FArrayBox wstar3_fab(xybx_work, 1, The_Async_Arena());
220 FArrayBox zol1_fab(xybx_work, 1, The_Async_Arena());
221 FArrayBox sfcflg_fab(xybx_work, 1, The_Async_Arena());
225 vpert_fab.setVal<RunOn::Device>(
zero);
226 sflux_fab.setVal<RunOn::Device>(
zero);
227 wstar3_fab.setVal<RunOn::Device>(
zero);
228 wstar3_down_fab.setVal<RunOn::Device>(
zero);
229 sfcflg_fab.setVal<RunOn::Device>(
zero);
230 hgamt_fab.setVal<RunOn::Device>(
zero);
231 hgamq_fab.setVal<RunOn::Device>(
zero);
232 hgamu_fab.setVal<RunOn::Device>(
zero);
233 hgamv_fab.setVal<RunOn::Device>(
zero);
234 wstar_fab.setVal<RunOn::Device>(
zero);
235 entr_fab.setVal<RunOn::Device>(
zero);
236 pbl_height_corrector.setVal<RunOn::Device>(
zero);
237 const auto& pblh_corr_arr = pbl_height_corrector.array();
238 const auto& pbli_arr = pbl_index.array();
239 const auto& pbli_zero_arr = pbl_index_zero_ri.array();
240 const auto& hgamt_arr = hgamt_fab.array();
241 const auto& hgamq_arr = hgamq_fab.array();
242 const auto& hgamu_arr = hgamu_fab.array();
243 const auto& hgamv_arr = hgamv_fab.array();
244 const auto& wstar_arr = wstar_fab.array();
245 const auto& vpert_arr = vpert_fab.array();
246 const auto& entr_arr = entr_fab.array();
247 const auto& cloud_top_arr = cloud_top_fab.array();
248 const auto& wstar3_down_arr = wstar3_down_fab.array();
249 const auto& sflux_arr = sflux_fab.array();
250 const auto& wstar3_arr = wstar3_fab.array();
251 const auto& zol1_arr = zol1_fab.array();
252 const auto& sfcflg_arr = sfcflg_fab.array();
255 const auto& cell_data = cons_in.const_array(mfi);
256 const auto& uvel =
xvel.const_array(mfi);
257 const auto& vvel =
yvel.const_array(mfi);
261 const auto& u_star_arr = SurfLayer->get_u_star(level)->const_array(mfi);
262 const auto& t_star_arr = SurfLayer->get_t_star(level)->const_array(mfi);
263 const auto& q_star_arr = SurfLayer->get_q_star(level)->const_array(mfi);
264 const auto& l_obuk_arr = SurfLayer->get_olen(level)->const_array(mfi);
265 const auto& t10av_arr = SurfLayer->get_mac_avg(level, 3)->const_array(mfi);
266 const auto& q10av_arr = SurfLayer->get_mac_avg(level, 4)->const_array(mfi);
267 const auto& ws10av_arr = SurfLayer->get_mac_avg(level, 6)->const_array(mfi);
268 const auto& z0_arr = SurfLayer->get_z0(level)->const_array(mfi);
271 const auto& lmask_arr = (SurfLayer->get_lmask(level)) ?
272 SurfLayer->get_lmask(level)->const_array(mfi) :
285 const bool l_ib = turbChoice.
pbl_ib_aware && (terrain_blank !=
nullptr);
287 "erf.pbl_ib_aware is not supported with terrain-fitted coordinates");
288 const Array4<Real const> blank_arr = l_ib ? terrain_blank->const_array(mfi) : Array4<Real const>{};
289 IArrayBox ksurf_fab(xybx_work, 1, The_Async_Arena());
290 FArrayBox zib_fab(xybx_work, 1, The_Async_Arena());
291 FArrayBox pblh_floor_fab(xybx_work, 1, The_Async_Arena());
292 FArrayBox us_eff_fab(xybx_work, 1, The_Async_Arena()), ts_eff_fab(xybx_work, 1, The_Async_Arena());
293 FArrayBox qs_eff_fab(xybx_work, 1, The_Async_Arena()), ol_eff_fab(xybx_work, 1, The_Async_Arena());
294 FArrayBox t10_eff_fab(xybx_work, 1, The_Async_Arena()), q10_eff_fab(xybx_work, 1, The_Async_Arena());
295 FArrayBox ws10_eff_fab(xybx_work, 1, The_Async_Arena()), z0_eff_fab(xybx_work, 1, The_Async_Arena());
296 const auto& ksurf_arr = ksurf_fab.array();
297 const auto& zib_arr = zib_fab.array();
298 const auto& pblh_floor_arr = pblh_floor_fab.array();
299 const auto& us_eff_arr = us_eff_fab.array();
const auto& ts_eff_arr = ts_eff_fab.array();
300 const auto& qs_eff_arr = qs_eff_fab.array();
const auto& ol_eff_arr = ol_eff_fab.array();
301 const auto& t10_eff_arr = t10_eff_fab.array();
const auto& q10_eff_arr = q10_eff_fab.array();
302 const auto& ws10_eff_arr = ws10_eff_fab.array();
const auto& z0_eff_arr = z0_eff_fab.array();
304 const Real dz_ib = geom.CellSize(2);
306 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
310 for (
int kk =
klo; kk <=
khi; ++kk) {
if (blank_arr(i, j, kk) >=
Real(0.5)) { ks = kk + 1; } }
311 if (ks >
khi) { ks =
khi; }
313 ksurf_arr(i, j, 0) = ks;
314 zib_arr(i, j, 0) = (ks -
klo) * dz_ib;
316 const Real u_top =
myhalf * (uvel(i, j, ks) + uvel(i + 1, j, ks));
317 const Real v_top =
myhalf * (vvel(i, j, ks) + vvel(i, j + 1, ks));
318 const Real ws_top = std::sqrt(u_top * u_top + v_top * v_top);
319 us_eff_arr(i, j, 0) = amrex::max(
KAPPA * ws_top / std::log(
myhalf * dz_ib / z0_ib),
Real(1.0e-3));
320 ts_eff_arr(i, j, 0) =
Real(0);
321 qs_eff_arr(i, j, 0) =
Real(0);
322 ol_eff_arr(i, j, 0) =
Real(1.0e10);
325 ? cell_data(i, j, ks, moisture_indices.
qv) / cell_data(i, j, ks,
Rho_comp) :
Real(0);
326 ws10_eff_arr(i, j, 0) = ws_top;
327 z0_eff_arr(i, j, 0) = z0_ib;
329 us_eff_arr(i, j, 0) = u_star_arr(i, j, 0);
330 ts_eff_arr(i, j, 0) = t_star_arr(i, j, 0);
331 qs_eff_arr(i, j, 0) = q_star_arr(i, j, 0);
332 ol_eff_arr(i, j, 0) = l_obuk_arr(i, j, 0);
333 t10_eff_arr(i, j, 0) = t10av_arr(i, j, 0);
334 q10_eff_arr(i, j, 0) = q10av_arr(i, j, 0);
335 ws10_eff_arr(i, j, 0) = ws10av_arr(i, j, 0);
336 z0_eff_arr(i, j, 0) = z0_arr(i, j, 0);
340 const Array4<Real const> z_nd_arr = z_phys_nd->array(mfi);
343 const Array4<Real const> qheat_arr = (qheating_rates !=
nullptr)
344 ? qheating_rates->const_array(mfi)
345 : Array4<Real const>{};
346 const bool has_qheating_rates = (qheating_rates !=
nullptr);
358 FArrayBox rib_base_fab(gbx_work, 1, The_Async_Arena());
359 FArrayBox rib_enhan_fab(gbx_work, 1, The_Async_Arena());
360 const auto& rib_base_arr = rib_base_fab.array();
361 const auto& rib_enhan_arr = rib_enhan_fab.array();
363 BL_PROFILE_VAR(
"YSUNew_Rib_Precompute", prof_rib_precomp);
364 ParallelFor(gbx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
366 const int ksrf = ksurf_arr(i, j, 0);
367 const Real zib = zib_arr(i, j, 0);
372 const amrex::Real t_enh = t_layer_v + vpert_arr(i,j,0);
373 const amrex::Real z_sfc = (use_terrain_fitted_coords)
375 const amrex::Real zval = (use_terrain_fitted_coords)
380 ?
GetThetavl(i,j,k,cell_data,moisture_indices)
381 :
GetThetav(i,j,k,cell_data,moisture_indices);
383 ?
GetThetavl(i,j,ksrf,cell_data,moisture_indices)
384 :
GetThetav(i,j,ksrf,cell_data,moisture_indices);
385 const amrex::Real ws2_raw =
fourth * ((uvel(i,j,k)+uvel(i+1,j,k))*(uvel(i,j,k)+uvel(i+1,j,k))
386 + (vvel(i,j,k)+vvel(i,j+1,k))*(vvel(i,j,k)+vvel(i,j+1,k)));
394 rib_base_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_layer_v) / (ws2 * theta_v_klo);
395 rib_enhan_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_enh) / (ws2 * theta_v_klo);
397 BL_PROFILE_VAR_STOP(prof_rib_precomp);
410 BL_PROFILE_VAR(
"YSUNew_SurfFlux_Precompute", prof_sflux_precomp);
411 ParallelFor(xybx_work, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
413 const int ksrf = ksurf_arr(i, j, 0);
415 const Real t_layer = t10_eff_arr(i, j, 0);
418 const Real rhox = rho_sfc;
428 const Real ustar = us_eff_arr(i, j, 0);
429 const Real tstar = ts_eff_arr(i, j, 0);
431 const Real hfx = -rhox * cp_air * ustar * tstar;
432 const Real qfx = -rhox * ustar * qstar;
433 const Real sflux = hfx / (rhox * cp_air) + qfx / rhox * ep1 * t_layer;
434 sflux_arr(i, j, 0) = sflux;
439 const bool sfcflg = (sflux >
zero);
440 sfcflg_arr(i, j, 0) = sfcflg ?
one :
zero;
449 const Real bfx0 = amrex::max(sflux, zero_d);
450 const Real wstar3 = govrth * bfx0 * pblh_guess;
451 wstar3_arr(i, j, 0) = wstar3;
456 const Real ust3 = ustar * ustar * ustar;
459 wscale = amrex::min(wscale, ustar *
amrex::Real(16.0));
460 wscale = amrex::max(wscale, ustar /
amrex::Real(5.0));
461 wstar_arr(i, j, 0) = wscale;
466 Real obuk_val = ol_eff_arr(i, j, 0);
469 const Real zl1 = (use_terrain_fitted_coords)
472 Real zol1 = zl1 / obuk_val;
479 zol1_arr(i, j, 0) = zol1;
481 BL_PROFILE_VAR_STOP(prof_sflux_precomp);
493 BL_PROFILE_VAR(
"YSUNew_PBLH_Passes", prof_pblh);
494 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
496 const int ksrf = ksurf_arr(i, j, 0);
501 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
505 const Real z0 = z0_eff_arr(i, j, 0);
506 const Real ws_layer = ws10_eff_arr(i, j, 0);
508 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
516 Real Rib = rib_base_arr(i,j,ksrf);
517 bool above_critical = (Rib >= Ribcr);
520 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
521 if (rib_base_arr(i,j,kk) >= Ribcr) {
523 above_critical =
true;
528 pbli_arr(i, j, 0) = kpbl;
530 BL_PROFILE_VAR_STOP(prof_pblh);
615 constexpr
Real GAMCRQ =
Real(2.e-3);
618 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
620 const int ksrf = ksurf_arr(i, j, 0);
621 const Real zib = zib_arr(i, j, 0);
626 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
630 const Real z0 = z0_eff_arr(i, j, 0);
631 const Real ws_layer = ws10_eff_arr(i, j, 0);
633 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
643 const amrex::Real z_sfc_col = (use_terrain_fitted_coords)
651 Real Rib = rib_enhan_arr(i,j,ksrf);
652 zval0 = (use_terrain_fitted_coords)
656 bool above_critical = (Rib >= Ribcr);
659 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
660 if (rib_enhan_arr(i,j,kk) >= Ribcr) { kpbl = kk; above_critical =
true;
break; }
661 zval0 = (use_terrain_fitted_coords)
664 Rib0 = rib_enhan_arr(i,j,kk);
669 const Real z_sfc = (use_terrain_fitted_coords)
672 const Real dz_terrain = (use_terrain_fitted_coords)
675 const Real z_max = (use_terrain_fitted_coords)
678 const Real pblh_max =
Real(0.9) * z_max;
684 pblh_min = amrex::max(z_sfc_col +
Real(0.5)*dz0,
Real(10.0));
686 pblh_min = amrex::max(z_sfc +
Real(0.5) * dz_terrain,
Real(10.0));
690 if (kpbl <
khi && rib_enhan_arr(i,j,kpbl) >= Ribcr) {
691 const Real zval = (use_terrain_fitted_coords)
694 Rib = rib_enhan_arr(i,j,kpbl);
695 Real pblh_interp = zval0 + (zval - zval0) / (Rib - Rib0) * (Ribcr - Rib0);
696 pblh_corr_arr(i, j, 0) = amrex::max(amrex::min(pblh_interp, pblh_max), pblh_min);
698 pblh_corr_arr(i, j, 0) = pblh_min;
700 pbli_arr(i, j, 0) = kpbl;
703 hgamt_arr(i, j, 0) =
zero;
704 hgamq_arr(i, j, 0) =
zero;
705 wstar_arr(i, j, 0) =
zero;
751 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
753 const int ksrf = ksurf_arr(i, j, 0);
754 cloud_top_arr(i, j, 0) = -1;
757 int kpbl = pbli_arr(i, j, 0);
758 for (
int kk = kpbl - 1; kk >= ksrf; --kk) {
760 if (moisture_indices.
qc >= 0)
761 qc_kk = cell_data(i, j, kk, moisture_indices.
qc) / cell_data(i, j, kk,
Rho_comp);
762 if (moisture_indices.
qi >= 0)
763 qi_kk = cell_data(i, j, kk, moisture_indices.
qi) / cell_data(i, j, kk,
Rho_comp);
765 if (qc_kk + qi_kk > ysu_qcloud_threshold) {
766 cloud_top_arr(i, j, 0) = kk;
773 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
775 cloud_top_arr(i, j, 0) = -1;
781 const int ksrf = ksurf_arr(i, j, 0);
782 const Real t_layer = t10_eff_arr(i, j, 0);
783 Real obuk_val = ol_eff_arr(i, j, 0);
792 const Real HOL = sf * pblh_corr_arr(i, j, 0) / obuk_val;
793 const Real HOL_bounded = amrex::max(amrex::min(HOL,
Real(100.0)),
Real(-100.0));
795 const Real phiM = (obuk_val > 0)
796 ? (1 + 5 * HOL_bounded)
798 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
800 const Real phiM_safe = amrex::max(phiM,
Real(0.01));
806 Real wscale = us_eff_arr(i, j, 0) / phiM_safe;
807 wscale = amrex::max(wscale, us_eff_arr(i, j, 0) /
Real(5.0));
808 wscale = amrex::min(wscale,
Real(16.0) * us_eff_arr(i, j, 0));
813 if (enable_ysu_topdown && cloud_top_arr(i, j, 0) >= ksrf) {
814 int k_cloud_top = cloud_top_arr(i, j, 0);
822 if (has_qheating_rates) {
825 for (
int kk = ksrf; kk <= k_cloud_top; ++kk) {
827 ? (z_nd_arr(i, j, kk+1) - z_nd_arr(i, j, kk))
831 LRAD += -qheat_arr(i, j, kk, 1) * ldz;
840 if (enable_ysu_rad_tend_limiter && has_qheating_rates) {
842 if (!amrex::Math::isfinite(LRAD_raw)) {
847 const amrex::Real lim_mag = ysu_rad_tend_limiter_magnitude;
848 LRAD_limited = amrex::min(LRAD_raw, lim_mag);
849 LRAD_limited = amrex::max(LRAD_limited, -lim_mag);
858 / cell_data(i, j, k_cloud_top,
Rho_comp);
860 wstar3_down = amrex::max(CONST_GRAV_d / t_local * LRAD
862 * pblh_corr_arr(i, j, 0), zero_d);
864 wstar3_down_arr(i, j, 0) = wstar3_down;
867 const Real bfx0_corr = amrex::max(sflux_arr(i, j, 0), zero_d);
868 const Real t_dry = t10_eff_arr(i, j, 0);
869 const Real wstar3_corr = (
CONST_GRAV / t_dry) * bfx0_corr * pblh_corr_arr(i, j, 0);
870 wstar3_arr(i, j, 0) = wstar3_corr;
873 const Real ust3 = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
875 wscale_corr = amrex::min(wscale_corr, us_eff_arr(i, j, 0) *
amrex::Real(16.0));
876 wscale_corr = amrex::max(wscale_corr, us_eff_arr(i, j, 0) /
amrex::Real(5.0));
877 wstar_arr(i, j, 0) = wscale_corr;
883 bool SFCFLG = (sfcflg_arr(i, j, 0) >
zero);
885 const Real hfx_col = -rho_sfc *
amrex::Real(1004.0) * us_eff_arr(i, j, 0) * ts_eff_arr(i, j, 0);
886 const Real gamfac = const_b / (rho_sfc * wscale_corr);
887 const Real HGAMT = (SFCFLG && enable_ysu_countergradient)
888 ? amrex::min(gamfac * hfx_col /
amrex::Real(1004.0), GAMCRT)
893 const Real qfx_col = -rho_sfc * us_eff_arr(i, j, 0) * qs_eff_arr(i, j, 0);
894 const Real HGAMQ_raw = (SFCFLG &&
use_moisture && enable_ysu_countergradient)
897 Real HGAMQ = amrex::min(amrex::max(HGAMQ_raw, zero_d), GAMCRQ);
900 if (lmask_arr && SFCFLG &&
use_moisture && enable_ysu_countergradient) {
901 bool is_land = (lmask_arr(i,j,0) == 1);
902 if (!is_land) HGAMQ =
zero;
906 if (enable_ysu_sat_limiter && moisture_indices.
qv >= 0 && SFCFLG &&
use_moisture && enable_ysu_countergradient) {
907 Real qv_klo = cell_data(i, j, ksrf, moisture_indices.
qv) / cell_data(i, j, ksrf,
Rho_comp);
914 Real rh_klo = (qsat_klo >
Real(1.0e-10)) ? (qv_klo / qsat_klo) :
zero;
915 if (rh_klo >
Real(0.95)) {
916 Real rh_scaling = amrex::max(zero_d, (
one - rh_klo) /
Real(0.05));
923 if (pbli_arr(i, j, 0) <= ksrf + 1) {
924 hgamt_arr(i, j, 0) =
zero;
925 hgamq_arr(i, j, 0) =
zero;
926 hgamu_arr(i, j, 0) =
zero;
927 hgamv_arr(i, j, 0) =
zero;
928 vpert_arr(i, j, 0) =
zero;
930 const Real pblh = pblh_corr_arr(i, j, 0);
931 hgamt_arr(i, j, 0) = (enable_ysu_countergradient) ? HGAMT / pblh :
zero;
932 hgamq_arr(i, j, 0) = (enable_ysu_countergradient &&
use_moisture) ? HGAMQ / pblh :
zero;
946 hgamu_arr(i, j, 0) =
zero;
947 hgamv_arr(i, j, 0) =
zero;
948 if (SFCFLG && enable_ysu_countergradient) {
949 const Real wspd_sfc = ws10_eff_arr(i, j, 0);
950 const Real ustar = us_eff_arr(i, j, 0);
951 wscale = wstar_arr(i, j, 0);
952 const Real wstar3 = wstar3_arr(i, j, 0);
954 const Real wscale4 = amrex::max(wscale * wscale * wscale * wscale,
961 const Real u_klo =
myhalf * (uvel(i, j, ksrf) + uvel(i+1, j, ksrf));
962 const Real v_klo =
myhalf * (vvel(i, j, ksrf) + vvel(i, j+1, ksrf));
963 hgamu_arr(i, j, 0) = brint * u_klo / pblh;
964 hgamv_arr(i, j, 0) = brint * v_klo / pblh;
973 if (enable_ysu_countergradient) {
976 const Real zl1_col = (use_terrain_fitted_coords)
980 const Real height_lim = amrex::min(zl1_col / (sfcfrac_h * pblh), one_d);
983 const Real VPERT_capped = enable_ysu_unbounded_vpert
985 : amrex::min(VPERT_raw, GAMCRT);
986 vpert_arr(i, j, 0) = amrex::max(VPERT_capped, zero_d) * height_lim;
988 vpert_arr(i, j, 0) =
zero;
1006 BL_PROFILE_VAR(
"YSUNew_Rib_Recompute", prof_rib_recomp);
1007 ParallelFor(gbx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1009 const int ksrf = ksurf_arr(i, j, 0);
1010 const Real zib = zib_arr(i, j, 0);
1015 const amrex::Real t_enh = t_layer_v + vpert_arr(i,j,0);
1016 const amrex::Real z_sfc = (use_terrain_fitted_coords)
1018 const amrex::Real zval = (use_terrain_fitted_coords)
1023 ?
GetThetavl(i,j,k,cell_data,moisture_indices)
1024 :
GetThetav(i,j,k,cell_data,moisture_indices);
1026 ?
GetThetavl(i,j,ksrf,cell_data,moisture_indices)
1027 :
GetThetav(i,j,ksrf,cell_data,moisture_indices);
1028 const amrex::Real ws2_raw =
fourth * ((uvel(i,j,k)+uvel(i+1,j,k))*(uvel(i,j,k)+uvel(i+1,j,k))
1029 + (vvel(i,j,k)+vvel(i,j+1,k))*(vvel(i,j,k)+vvel(i,j+1,k)));
1035 rib_enhan_arr(i,j,k) =
CONST_GRAV * zrel * (theta_v - t_enh) / (ws2 * theta_v_klo);
1037 BL_PROFILE_VAR_STOP(prof_rib_recomp);
1046 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1048 const int ksrf = ksurf_arr(i, j, 0);
1049 const Real zib = zib_arr(i, j, 0);
1053 bool over_land = (!lmask_arr) || (lmask_arr(i, j, 0) == 1);
1057 const Real z0 = z0_eff_arr(i, j, 0);
1058 const Real ws_layer = ws10_eff_arr(i, j, 0);
1060 Ribcr = amrex::min(
Real(0.16) * std::pow(
Real(1.0e-7) * Rossby, -
Real(0.18)),
Real(0.3));
1067 Real Rib = rib_enhan_arr(i,j,ksrf);
1068 zval0 = (use_terrain_fitted_coords)
1072 bool above_critical = (Rib >= Ribcr);
1074 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
1075 if (rib_enhan_arr(i,j,kk) >= Ribcr) { kpbl = kk; above_critical =
true;
break; }
1076 zval0 = (use_terrain_fitted_coords)
1079 Rib0 = rib_enhan_arr(i,j,kk);
1084 const Real z_sfc = (use_terrain_fitted_coords)
1087 const Real dz_terrain = (use_terrain_fitted_coords)
1090 const Real z_max = (use_terrain_fitted_coords)
1093 const Real pblh_max =
Real(0.9) * z_max;
1099 const amrex::Real z_sfc_col = (use_terrain_fitted_coords)
1102 pblh_min = amrex::max(z_sfc_col +
Real(0.5)*dz0,
Real(10.0));
1104 pblh_min = amrex::max(z_sfc +
Real(0.5) * dz_terrain,
Real(10.0));
1106 pblh_floor_arr(i, j, 0) = pblh_min;
1109 if (kpbl <
khi && rib_enhan_arr(i,j,kpbl) >= Ribcr) {
1110 const Real zval = (use_terrain_fitted_coords)
1113 Rib = rib_enhan_arr(i,j,kpbl);
1114 Real pblh_interp = zval0 + (zval - zval0) / (Rib - Rib0) * (Ribcr - Rib0);
1115 pblh_corr_arr(i, j, 0) = amrex::max(amrex::min(pblh_interp, pblh_max), pblh_min);
1117 pblh_corr_arr(i, j, 0) = pblh_min;
1119 pbli_arr(i, j, 0) = kpbl;
1132 geom.Domain(), geom.periodicity());
1137 ParallelFor(xybx_work, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept {
1138 pblh_corr_arr(i, j, 0) = amrex::max(pblh_corr_arr(i, j, 0), pblh_floor_arr(i, j, 0));
1148 auto pblh_out = pblh_mf.array(mfi);
1149 const Box& tbx = mfi.tilebox();
1150 ParallelFor(tbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
1151 pblh_out(i, j, k) = pblh_corr_arr(i, j, 0);
1162 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1164 const int ksrf = ksurf_arr(i, j, 0);
1165 const Real zib = zib_arr(i, j, 0);
1166 const int kpblold = pbli_arr(i,j,0);
1167 bool definebrup =
false;
1170 const Real thermalli =
GetThetavl(i, j, ksrf, cell_data, moisture_indices);
1173 for (
int kk = kpblold; kk <
khi; ++kk) {
1175 const Real ws2_raw =
fourth * ((uvel(i,j,kk)+uvel(i+1,j,kk))*(uvel(i,j,kk)+uvel(i+1,j,kk))
1176 + (vvel(i,j,kk)+vvel(i,j+1,kk))*(vvel(i,j,kk)+vvel(i,j+1,kk)));
1183 const Real z_sfc = (use_terrain_fitted_coords)
1186 const Real zval_kk = (use_terrain_fitted_coords)
1189 const Real zrel_kk = amrex::max(zval_kk - z_sfc,
amrex::Real(1.0e-4));
1192 const Real thlix_kk =
GetThetavl(i, j, kk, cell_data, moisture_indices);
1193 const Real thlix_klo =
GetThetavl(i, j, ksrf, cell_data, moisture_indices);
1196 const Real bruptmp =
CONST_GRAV * zrel_kk * (thlix_kk - thermalli) / (ws2 * thlix_klo);
1199 const bool stable = (bruptmp >=
zero);
1202 pbli_arr(i,j,0) = kk;
1213 pbli_arr(i,j,0) = amrex::min(pbli_arr(i,j,0), izmax);
1240 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1242 const int ksrf = ksurf_arr(i, j, 0);
1245 int kpbl_zero = ksrf;
1246 Real Rib = rib_enhan_arr(i,j,ksrf);
1247 bool above_critical = (Rib >= Ribcr_zero);
1250 for (
int kk = ksrf+1; !above_critical && kk <=
khi; ++kk) {
1251 if (rib_enhan_arr(i,j,kk) >= Ribcr_zero) { kpbl_zero = kk; above_critical =
true;
break; }
1254 pbli_zero_arr(i, j, 0) = kpbl_zero;
1256 BL_PROFILE_VAR_STOP(prof_pblh);
1265 ParallelFor(xybx, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int) noexcept
1267 const int ksrf = ksurf_arr(i, j, 0);
1268 entr_arr(i,j,0) =
zero;
1269 if (!enable_ysu_entrainment)
return;
1271 const int kpbl = pbli_arr(i,j,0);
1273 const Real pblh = pblh_corr_arr(i,j,0);
1274 const Real wscale = wstar_arr(i,j,0);
1275 const Real ustar = us_eff_arr(i, j, 0);
1276 const Real ustar3 = ustar * ustar * ustar;
1280 const Real wstar3_col = wstar3_arr(i,j,0);
1287 ?
GetThetavl(i, j, ksrf, cell_data, moisture_indices)
1288 :
GetThetav(i, j, ksrf, cell_data, moisture_indices);
1293 const int kpbl_p1 = amrex::min(kpbl + 1, izmax);
1295 ?
GetThetavl(i, j, kpbl, cell_data, moisture_indices)
1296 :
GetThetav(i, j, kpbl, cell_data, moisture_indices);
1298 ?
GetThetavl(i, j, kpbl_p1, cell_data, moisture_indices)
1299 :
GetThetav(i, j, kpbl_p1, cell_data, moisture_indices);
1300 const Real dthvx = amrex::max(thvx_kpbl_p1 - thvx_kpbl,
amrex::Real(1.0e-2));
1304 const Real we = amrex::max(bfxpbl / dthvx, -std::sqrt(wm2));
1307 const Real met_h = (use_terrain_fitted_coords)
1309 const Real dz_kpbl = met_h / dz_inv;
1319 Real K_entr_final = (we <
zero) ? rho_kpbl * (-we) * dz_kpbl :
zero;
1322 const int k_below = amrex::max(kpbl - 1, ksrf);
1324 Real qc_below = (moisture_indices.
qc >= 0)
1325 ? cell_data(i, j, k_below, moisture_indices.
qc) / rho_k :
zero;
1326 Real qi_below = (moisture_indices.
qi >= 0)
1327 ? cell_data(i, j, k_below, moisture_indices.
qi) / rho_k :
zero;
1331 if ((qc_below + qi_below) > cloud_thresh_entr && kpbl >= ksrf + 2) {
1339 const int k_p2 = amrex::min(kpbl + 1, izmax);
1340 const Real thlix_kbelow =
GetThetavl(i, j, k_below, cell_data, moisture_indices);
1341 const Real thlix_kp2 =
GetThetavl(i, j, k_p2, cell_data, moisture_indices);
1344 const Real dthvx_li = amrex::max(thlix_kp2 - thlix_kbelow,
amrex::Real(0.1));
1350 * xlv_over_cp * qc_below / dthvx_li,
1355 const Real we_cloud = amrex::max(bfxpbl / dthvx_li, -std::sqrt(wm2));
1359 const Real bfx0_cloud = amrex::max(sflux_arr(i, j, 0), zero_d);
1360 const Real bfxpbl_cloud = -ent_eff * bfx0_cloud;
1361 const Real we_cloud_top = amrex::max(bfxpbl_cloud / dthvx_li,
1365 we_final = we_cloud + we_cloud_top;
1368 K_entr_final = (we_final <
zero) ? rho_kpbl * (-we_final) * dz_kpbl :
zero;
1375 entr_arr(i,j,0) = amrex::min(K_entr_final, K_cap);
1379 const int kpbl_current = pbli_arr(i, j, 0);
1383 if (moisture_indices.
qc >= 0)
1384 qc_kpbl = cell_data(i, j, kpbl_current, moisture_indices.
qc) / cell_data(i, j, kpbl_current,
Rho_comp);
1385 if (moisture_indices.
qi >= 0)
1386 qi_kpbl = cell_data(i, j, kpbl_current, moisture_indices.
qi) / cell_data(i, j, kpbl_current,
Rho_comp);
1389 if ((qc_kpbl + qi_kpbl) > ysu_qcloud_threshold) {
1390 pbli_arr(i, j, 0) = amrex::min(kpbl_current + 1, izmax);
1397 FArrayBox K_down_fab(gbx, 1, The_Async_Arena());
1398 K_down_fab.setVal<RunOn::Device>(
zero);
1399 const auto& K_down_arr = K_down_fab.array();
1401 if (enable_ysu_topdown) {
1402 ParallelFor(gbx, [=, zero_d=
zero] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1404 const int ksrf = ksurf_arr(i, j, 0);
1405 const Real zib = zib_arr(i, j, 0);
1406 K_down_arr(i,j,k) =
zero;
1407 if (k >= pbli_arr(i,j,0) || k < ksrf)
return;
1411 const amrex::Real zval = (use_terrain_fitted_coords)
1414 const amrex::Real z_sfc = (use_terrain_fitted_coords)
1422 const amrex::Real wstar3_down_col = wstar3_down_arr(i,j,0);
1424 ? std::cbrt(wstar3_down_col)
1426 const amrex::Real zfac_up = amrex::max(zrel / pblh_rel, zero_d);
1427 K_down_arr(i,j,k) =
rho * wstar_down_eff *
KAPPA
1428 * amrex::max(pblh_rel - zrel, zero_d)
1429 * zfac_up * zfac_up;
1435 const Array4<Real>& K_turb = eddyViscosity.array(mfi);
1446 BL_PROFILE_VAR(
"YSUNew_Kprofile", prof_kprof);
1447 ParallelFor(gbx, [=, wstar3_arr_cap=wstar3_arr, zol1_arr_cap=zol1_arr, sfcflg_arr_cap=sfcflg_arr,
1448 zero_d=
zero, one_d=
one, two_d=
two] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
1450 const int ksrf = ksurf_arr(i, j, 0);
1451 const Real zib = zib_arr(i, j, 0);
1454 if (rho_guard <=
Real(0)) {
1466 Real obuk_val = ol_eff_arr(i, j, 0);
1471 const Real zval = (use_terrain_fitted_coords)
1484 const Real met_h_zeta = (use_terrain_fitted_coords)
1486 const Real dz_terrain = met_h_zeta / dz_inv;
1507 constexpr
Real qc_threshold =
Real(1.0e-5);
1512 if (moisture_indices.
qc >= 0) {
1513 qc_mix = cell_data(i, j, k, moisture_indices.
qc) /
rho;
1515 if (moisture_indices.
qi >= 0) {
1516 qi_mix = cell_data(i, j, k, moisture_indices.
qi) /
rho;
1519 const Real total_qcloud = qc_mix + qi_mix;
1520 const bool has_cloud = (total_qcloud > qc_threshold);
1529 if (k < pbli_extent) {
1550 bool SFCFLG = (sfcflg_arr_cap(i, j, 0) >
zero);
1556 const Real HOL = sf * pblh_corr_arr(i, j, 0) / obuk_val;
1557 const Real HOL_bounded = amrex::max(amrex::min(HOL,
Real(100.0)),
Real(-100.0));
1560 const Real phiM = (obuk_val > 0)
1561 ? (1 + 5 * HOL_bounded)
1563 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
1570 const Real phit = (obuk_val > 0)
1571 ? (1 + 5 * HOL_bounded)
1573 amrex::max(1 - 16 * HOL_bounded,
Real(0.01)),
1582 Real phit_cloud = phit;
1583 Real phiM_cloud = phiM;
1584 if (has_cloud && obuk_val >
zero) {
1588 Real reduction_factor =
one -
Real(0.15) * amrex::min(total_qcloud / qc_threshold, one_d);
1590 phiM_cloud =
one +
Real(5.0) * reduction_factor * sf * pblh_corr_arr(i, j, 0) / obuk_val;
1591 phit_cloud =
one +
Real(5.0) * reduction_factor * sf * pblh_corr_arr(i, j, 0) / obuk_val;
1592 }
else if (has_cloud && obuk_val <=
zero) {
1596 Real cloud_boost =
Real(1.0) +
Real(0.05) * amrex::min(total_qcloud / qc_threshold, one_d);
1599 phiM_cloud = std::pow(
1600 amrex::max(one_d -
Real(16.0) * HOL_bounded / cloud_boost,
Real(0.01)),
1602 phit_cloud = std::pow(
1603 amrex::max(one_d -
Real(16.0) * HOL_bounded / cloud_boost,
Real(0.01)),
1608 const Real phiM_eff = phiM_cloud;
1609 const Real phit_eff = phit_cloud;
1622 const Real conpr = bfac *
KAPPA * sfcfrac;
1625 const Real zq_kp1_prandtl = zval +
myhalf * dz_terrain;
1629 const Real prfac = SFCFLG ? conpr :
zero;
1634 const Real wstar3_col = wstar3_arr_cap(i, j, 0);
1635 const Real ust3 = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
1638 const Real wstar3_2 = wstar3_down_arr(i, j, 0);
1642 const Real wstar_tot3 = wstar3_col + wstar3_2;
1650 const Real pblh = pblh_corr_arr(i, j, 0);
1651 const Real sfclayer = sfcfrac * pblh;
1652 const Real zdiff = amrex::max(zq_kp1_prandtl - sfclayer, zero_d);
1653 const Real prnumfac =
amrex::Real(-3.0) * zdiff * zdiff / (pblh * pblh);
1659 Real prnum0 = (phit_eff / phiM_eff) + prfac;
1660 prnum0 = amrex::min(amrex::max(prnum0, prmin_wrf), prmax_wrf);
1664 Real prnum0_heat = prnum0 / (
one + prfac2 *
KAPPA * sfcfrac);
1665 prnum0_heat = amrex::min(amrex::max(prnum0_heat, prmin_wrf), prmax_wrf);
1666 const Real Prt =
one + (prnum0_heat -
one) * std::exp(prnumfac);
1670 const Real prnum_q =
one + (prnum0 -
one) * std::exp(prnumfac);
1687 const Real zq_kp1 = zval +
myhalf * dz_terrain;
1695 const Real zl1 = (use_terrain_fitted_coords)
1702 const Real pblh_rel = amrex::max(pblh_corr_arr(i, j, 0) - zl1,
amrex::Real(1.0e-4));
1703 const Real zfac = amrex::min(
1704 amrex::max(one_d - (zq_kp1 - zl1) / pblh_rel, zfacmin), one_d);
1708 const Real ust3_wscale = us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0) * us_eff_arr(i, j, 0);
1712 wscalek_val = std::cbrt(ust3_wscale +
amrex::Real(8.0) *
KAPPA * wstar3_col * (
one - zfac));
1718 constexpr
Real ckz_pbl =
Real(0.001);
1719 const Real K_base = ckz_pbl * dz_terrain *
rho;
1721 K_turb(i, j, k,
EddyDiff::Mom_v) = K_base +
rho * wscalek_val *
KAPPA * (zq_kp1 - zib) * std::pow(zfac, pfac);
1732 if (enable_ysu_topdown && k < pbli_arr(i, j, 0)) {
1743 const Real zq_kp1_stable = zval +
myhalf * dz_terrain;
1746 const Real zl1_stable = (use_terrain_fitted_coords)
1752 const Real pblh_rel_stable = amrex::max(pblh_corr_arr(i, j, 0) - zl1_stable,
amrex::Real(1.0e-4));
1753 const Real zfac_stable = amrex::min(
1754 amrex::max(one_d - (zq_kp1_stable - zl1_stable) / pblh_rel_stable, zfacmin_stable), one_d);
1758 const Real zol1_stable = zol1_arr_cap(i, j, 0);
1759 const Real zol_ratio = (zq_kp1_stable - zib) / (zl1_stable - zib);
1760 const Real phim_stable_arg = zol1_stable * zol_ratio;
1765 const Real phim_stable = (enable_qnse_d >
Real(0.5))
1766 ? ((
one + qnse_am_d * phim_stable_arg) / (
one + qnse_bm_d * phim_stable_arg))
1768 const Real wscalek_stable = amrex::max(
1769 us_eff_arr(i, j, 0) / amrex::max(phim_stable,
amrex::Real(0.01)),
1773 constexpr
Real ckz_pbl_stable =
Real(0.001);
1774 const Real K_base_stable = ckz_pbl_stable * dz_terrain *
rho;
1776 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);
1781 const Real prnum_stable =
one + (prnum0 -
one) * std::exp(prnumfac);
1790 }
else if (k >= pbli_extent) {
1795 const Real lambda_min =
Real(30.0);
1796 const Real lambda_max =
Real(300.0);
1797 const Real lambdadz = amrex::min(amrex::max(
Real(0.1) * dz_terrain, lambda_min), lambda_max);
1798 const Real lscale = (lambdadz *
KAPPA * zval) / (lambdadz +
KAPPA * zval);
1799 Real dthetadz, dudz, dvdz;
1800 ComputeVerticalDerivativesPBL(i, j, k, uvel, vvel, cell_data, izmin, izmax, pbl_derivative_dz_inv(i,j,k),
1801 c_ext_dir_on_zlo, c_ext_dir_on_zhi, u_ext_dir_on_zlo,
1802 u_ext_dir_on_zhi, v_ext_dir_on_zlo, v_ext_dir_on_zhi, dthetadz,
1803 dudz, dvdz, moisture_indices);
1806 const Real dudz_safe = (k < izmax) ? dudz :
zero;
1807 const Real dvdz_safe = (k < izmax) ? dvdz :
zero;
1811 const Real wind_shear = dudz_safe * dudz_safe + dvdz_safe * dvdz_safe;
1812 const Real wind_shear_safe = std::max(wind_shear,
Real(1.0e-8));
1818 const Real theta_v =
GetThetav(i, j, k, cell_data, moisture_indices);
1819 const Real dtheta_v_dz = dthetadz;
1832 Real grad_Ri =
CONST_GRAV / theta_v * dtheta_v_dz / wind_shear_safe;
1833 grad_Ri = std::max(std::min(grad_Ri,
Real(100.0)), -
Real(100.0));
1841 Real qc_k = (moisture_indices.
qc >= 0) ? cell_data(i,j,k, moisture_indices.
qc)/rho_k :
zero;
1842 Real qc_kp1 = (moisture_indices.
qc >= 0) ? cell_data(i,j,k+1,moisture_indices.
qc)/rho_kp1 :
zero;
1843 Real qi_k = (moisture_indices.
qi >= 0) ? cell_data(i,j,k, moisture_indices.
qi)/rho_k :
zero;
1844 Real qi_kp1 = (moisture_indices.
qi >= 0) ? cell_data(i,j,k+1,moisture_indices.
qi)/rho_kp1 :
zero;
1847 if ((qc_k + qi_k) > cloud_thresh && (qc_kp1 + qi_kp1) > cloud_thresh) {
1854 const Real qv_k_mri = (moisture_indices.
qv >= 0)
1855 ? cell_data(i,j,k, moisture_indices.
qv) / rho_k :
zero;
1856 const Real qv_kp1_mri = (moisture_indices.
qv >= 0)
1857 ? cell_data(i,j,k+1,moisture_indices.
qv) / rho_kp1 :
zero;
1862 const Real qmean =
myhalf * (qv_k_mri + qv_kp1_mri);
1868 const Real chi =
xlv *
xlv * qmean / (
cp * rv * tmean * tmean);
1891 const Real grad_Ri_safe = amrex::max(grad_Ri, -
Real(100.0));
1892 const Real fm = (grad_Ri_safe > 0)
1894 : 1 - 8 * grad_Ri_safe / (1 +
Real(1.746) * std::sqrt(amrex::max(-grad_Ri_safe, zero_d)));
1895 const Real ft = (grad_Ri_safe > 0)
1897 : 1 - 8 * grad_Ri_safe / (1 +
Real(1.286) * std::sqrt(amrex::max(-grad_Ri_safe, zero_d)));
1898 const Real rl2wsp =
rho * lscale * lscale * std::sqrt(wind_shear);
1902 if (grad_Ri_safe > 0) {
1921 if (k == pbli_arr(i,j,0)) {
1947 Real rhoKmin, rhoKmax;
1953 constexpr
Real Kmax =
Real(1000.0);
1954 rhoKmin = ckz * dz_terrain *
rho;
1955 rhoKmax =
rho * Kmax;
1962 rhoKmin =
rho * Kmin;
1963 rhoKmax =
rho * Kmax;
1966 #ifdef ERF_USE_WINDFARM
1980 if (k < pbli_extent) {
1995 std::min(K_turb(i, j, k,
EddyDiff::Q_v), rhoKmax), rhoKmin);
2020 if (k < pbli_extent) {
2034 BL_PROFILE_VAR_STOP(prof_kprof);
2038 ParallelFor(xybx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int ) noexcept
2063 SurfLayer->set_pblh(level, pblh_mf);
constexpr amrex::Real epsv
Definition: ERF_Constants.H:40
constexpr amrex::Real KAPPA
Definition: ERF_Constants.H:55
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:56
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:39
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:40
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:31
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:30
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:35
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:29
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:34
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)
Definition: ERF_PBLModels.H:281
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:515
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:751
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:190
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ yvel_bc
Definition: ERF_IndexDefines.H:106
@ cons_bc
Definition: ERF_IndexDefines.H:89
@ xvel_bc
Definition: ERF_IndexDefines.H:105
@ ext_dir
Definition: ERF_IndexDefines.H:297
@ Theta_v
Definition: ERF_IndexDefines.H:250
@ Turb_lengthscale
Definition: ERF_IndexDefines.H:254
@ HGAMU_v
Definition: ERF_IndexDefines.H:262
@ Q_v
Definition: ERF_IndexDefines.H:253
@ Mom_v
Definition: ERF_IndexDefines.H:249
@ HGAMQ_v
Definition: ERF_IndexDefines.H:261
@ HGAMT_v
Definition: ERF_IndexDefines.H:260
@ HGAMV_v
Definition: ERF_IndexDefines.H:263
@ rho
Definition: ERF_Kessler.H:25
@ xvel
Definition: ERF_IndexDefines.H:215
@ yvel
Definition: ERF_IndexDefines.H:216
@ 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
real(kind=kind_phys), parameter, private alpha
Definition: ERF_module_mp_wdm6.F90:62
int qi
cloud ice
Definition: ERF_DataStruct.H:236
int qv
water vapor
Definition: ERF_DataStruct.H:234
int qc
cloud liquid water
Definition: ERF_DataStruct.H:235
Functor for inverse vertical spacings for terrain-following grids using cell-center heights.
Definition: ERF_PBLModels.H:461
bool enable_mrf_unbounded_vpert
Whether MRF leaves VPERT unlimited by GAMCRT.
Definition: ERF_TurbStruct.H:910
bool pbl_mrf_use_zero_ri_extent
Whether MRF uses the Ri=0 K-profile extent.
Definition: ERF_TurbStruct.H:911
bool enable_vh96_shear_correction
Whether Vogelezang & Holtslag (1996) shear-correction term is enabled.
Definition: ERF_TurbStruct.H:888
bool enable_ysu_entrainment
Whether YSU entrainment-layer parameterization is enabled.
Definition: ERF_TurbStruct.H:876
bool enable_ysu_sat_limiter
Whether YSU applies a saturation limiter to moisture countergradient terms.
Definition: ERF_TurbStruct.H:872
bool enable_ysu_cloud_pblh
Whether YSU cloud-based PBL-height detection is enabled.
Definition: ERF_TurbStruct.H:878
amrex::Real pbl_mrf_const_b
MRF constant used to compute PBL height.
Definition: ERF_TurbStruct.H:896
amrex::Real pblh_smoothing_weight
Center-cell weight in PBLH smoothing stencil (must be in [0,1]).
Definition: ERF_TurbStruct.H:892
amrex::Real ysu_qcloud_threshold
Cloud liquid water threshold for YSUNew [kg/kg].
Definition: ERF_TurbStruct.H:880
amrex::Real qnse_bm
Definition: ERF_TurbStruct.H:920
bool enable_qnse_stable_functions
Definition: ERF_TurbStruct.H:917
bool enable_ysu_countergradient
Whether YSU countergradient corrections are enabled.
Definition: ERF_TurbStruct.H:868
bool enable_pblh_smoothing
Whether spatial smoothing of diagnosed PBLH is enabled.
Definition: ERF_TurbStruct.H:890
int pblh_smoothing_passes
Number of PBLH smoothing iterations to apply.
Definition: ERF_TurbStruct.H:891
amrex::Real pbl_ib_z0
Definition: ERF_TurbStruct.H:907
bool enable_ysu_topdown
Whether YSU top-down mixing is enabled.
Definition: ERF_TurbStruct.H:874
bool pbl_ib_aware
Definition: ERF_TurbStruct.H:906
amrex::Real ysu_rad_tend_limiter_magnitude
Definition: ERF_TurbStruct.H:886
amrex::Real pbl_ysu_land_Ribcr
Critical bulk Richardson number over land for stable YSU conditions.
Definition: ERF_TurbStruct.H:862
amrex::Real vh96_shear_const_b
Vogelezang & Holtslag (1996) shear-correction constant b.
Definition: ERF_TurbStruct.H:889
amrex::Real qnse_am
Definition: ERF_TurbStruct.H:919
amrex::Real pbl_mrf_sf
MRF surface flux value used to compute PBL height.
Definition: ERF_TurbStruct.H:897
bool pbl_ysunew_highres_bounds
Whether YSUNew applies high-resolution grid-dependent diffusivity bounds.
Definition: ERF_TurbStruct.H:883
amrex::Real pbl_ysu_coriolis_freq
Coriolis frequency used by YSU-family PBL schemes.
Definition: ERF_TurbStruct.H:853
bool ysu_moistvars
Whether YSU applies turbulence to moisture variables.
Definition: ERF_TurbStruct.H:882
bool enable_ysu_terrain_pblh_floor
Whether YSU applies a terrain-following PBL-height floor.
Definition: ERF_TurbStruct.H:870
bool enable_ysu_liquid_theta
Whether YSU uses liquid-water virtual potential temperature for stability.
Definition: ERF_TurbStruct.H:866
bool enable_ysu_rad_tend_limiter
Definition: ERF_TurbStruct.H:885