Function for computing the slow RHS for the evolution equations for the density, potential temperature and momentum.
75 BL_PROFILE_REGION(
"erf_make_mom_sources()");
77 Real time =
static_cast<Real>(time_d);
79 Box domain(geom.Domain());
80 const GpuArray<Real, AMREX_SPACEDIM>
dxInv = geom.InvCellSizeArray();
114 if (solverChoice.
terrain_type == TerrainType::ImmersedForcing) {
116 amrex::Error(
" Currently forest canopy cannot be used with immersed forcing");
126 auto cosphi = solverChoice.
cosphi;
127 auto sinphi = solverChoice.
sinphi;
158 Real rhoUA_target{0};
159 Real rhoVA_target{0};
166 Table1D<Real> dptr_r_plane, dptr_u_plane, dptr_v_plane;
167 TableData<Real, 1> r_plane_tab, u_plane_tab, v_plane_tab;
169 if (is_slow_step && (dptr_wbar_sub ||
172 enforce_massflux_x || enforce_massflux_y))
177 const bool planar_averages_valid =
178 solverChoice.
mesh_type != MeshType::VariableDz ||
181 planar_averages_valid,
182 "Fixed-index planar averages require a non-variable-dz mesh or "
183 "a validated flat fitted mesh (erf.flat_terrain = true).");
186 const int u_offset = 1;
187 const int v_offset = 1;
196 r_ave.compute_averages(
ZDir(), r_ave.field());
198 int ncell = r_ave.ncell_line();
199 Gpu::HostVector< Real> r_plane_h(ncell);
200 Gpu::DeviceVector< Real> r_plane_d(ncell);
202 r_ave.line_average(
Rho_comp, r_plane_h);
204 Gpu::copyAsync(Gpu::hostToDevice, r_plane_h.begin(), r_plane_h.end(), r_plane_d.begin());
206 Real* dptr_r = r_plane_d.data();
208 Box tdomain = domain; tdomain.grow(2,ng_c[2]);
209 r_plane_tab.resize({tdomain.smallEnd(2)}, {tdomain.bigEnd(2)});
211 dptr_r_plane = r_plane_tab.table();
212 ParallelFor(ncell, [=] AMREX_GPU_DEVICE (
int k) noexcept
214 dptr_r_plane(k-
offset) = dptr_r[k];
218 IntVect ng_u = S_data[
IntVars::xmom].nGrowVect(); ng_u[2] = u_offset;
221 IntVect ng_v = S_data[
IntVars::ymom].nGrowVect(); ng_v[2] = v_offset;
224 u_ave.compute_averages(
ZDir(), u_ave.field());
225 v_ave.compute_averages(
ZDir(), v_ave.field());
227 int u_ncell = u_ave.ncell_line();
228 int v_ncell = v_ave.ncell_line();
229 Gpu::HostVector< Real> u_plane_h(u_ncell), v_plane_h(v_ncell);
230 Gpu::DeviceVector< Real> u_plane_d(u_ncell), v_plane_d(v_ncell);
232 u_ave.line_average(0, u_plane_h);
233 v_ave.line_average(0, v_plane_h);
235 Gpu::copyAsync(Gpu::hostToDevice, u_plane_h.begin(), u_plane_h.end(), u_plane_d.begin());
236 Gpu::copyAsync(Gpu::hostToDevice, v_plane_h.begin(), v_plane_h.end(), v_plane_d.begin());
238 Real* dptr_u = u_plane_d.data();
239 Real* dptr_v = v_plane_d.data();
241 Box udomain = domain; udomain.grow(2,ng_u[2]);
242 Box vdomain = domain; vdomain.grow(2,ng_v[2]);
243 u_plane_tab.resize({udomain.smallEnd(2)}, {udomain.bigEnd(2)});
244 v_plane_tab.resize({vdomain.smallEnd(2)}, {vdomain.bigEnd(2)});
246 dptr_u_plane = u_plane_tab.table();
247 ParallelFor(u_ncell, [=] AMREX_GPU_DEVICE (
int k) noexcept
249 dptr_u_plane(k-u_offset) = dptr_u[k];
252 dptr_v_plane = v_plane_tab.table();
253 ParallelFor(v_ncell, [=] AMREX_GPU_DEVICE (
int k) noexcept
255 dptr_v_plane(k-v_offset) = dptr_v[k];
259 if (enforce_massflux_x || enforce_massflux_y) {
260 Real Lx = geom.ProbHi(0) - geom.ProbLo(0);
261 Real Ly = geom.ProbHi(1) - geom.ProbLo(1);
263 if (solverChoice.
mesh_type == MeshType::ConstantDz) {
265 rhoUA = std::accumulate(u_plane_h.begin() + u_offset + massflux_klo,
266 u_plane_h.begin() + u_offset + massflux_khi+1,
zero);
267 rhoVA = std::accumulate(v_plane_h.begin() + v_offset + massflux_klo,
268 v_plane_h.begin() + v_offset + massflux_khi+1,
zero);
269 rhoUA_target = std::accumulate(r_plane_h.begin() +
offset + massflux_klo,
270 r_plane_h.begin() +
offset + massflux_khi+1,
zero);
271 rhoVA_target = rhoUA_target;
273 rhoUA *= geom.CellSize(2) * Ly;
274 rhoVA *= geom.CellSize(2) * Lx;
275 rhoUA_target *= geom.CellSize(2) * Ly;
276 rhoVA_target *= geom.CellSize(2) * Lx;
278 }
else if (solverChoice.
mesh_type == MeshType::StretchedDz) {
280 for (
int k=massflux_klo; k < massflux_khi; ++k) {
281 rhoUA += u_plane_h[k + u_offset] * stretched_dz_h[k];
282 rhoVA += v_plane_h[k + v_offset] * stretched_dz_h[k];
283 rhoUA_target += r_plane_h[k +
offset] * stretched_dz_h[k];
285 rhoVA_target = rhoUA_target;
294 rhoUA_target *= U_target;
295 rhoVA_target *= V_target;
297 Print() <<
"Integrated mass flux : " << rhoUA <<
" " << rhoVA
298 <<
" (target: " << rhoUA_target <<
" " << rhoVA_target <<
")"
306 for ( MFIter mfi(S_data[
IntVars::cons]); mfi.isValid(); ++mfi)
308 Box tbx = mfi.nodaltilebox(0);
309 Box tby = mfi.nodaltilebox(1);
310 Box tbz = mfi.nodaltilebox(2);
311 if (tbz.bigEnd(2) == domain.bigEnd(2)+1) tbz.growHi(2,-1);
313 const Array4<const Real>& cell_data = S_data[
IntVars::cons].array(mfi);
314 const Array4<const Real>& rho_u = S_data[
IntVars::xmom].array(mfi);
315 const Array4<const Real>& rho_v = S_data[
IntVars::ymom].array(mfi);
316 const Array4<const Real>& rho_w = S_data[
IntVars::zmom].array(mfi);
318 const Array4<const Real>& u =
xvel.array(mfi);
319 const Array4<const Real>& v =
yvel.array(mfi);
320 const Array4<const Real>&
w = wvel.array(mfi);
322 const Array4< Real>& xmom_src_arr = xmom_src.array(mfi);
323 const Array4< Real>& ymom_src_arr = ymom_src.array(mfi);
324 const Array4< Real>& zmom_src_arr = zmom_src.array(mfi);
326 const Array4<const Real>&
r0 = r_hse.const_array(mfi);
328 const Array4<const Real>& f_drag_arr = (forest_drag) ? forest_drag->const_array(mfi) :
329 Array4<const Real>{};
330 const Array4<const Real>& t_blank_arr = (terrain_blank) ? terrain_blank->const_array(mfi) :
331 Array4<const Real>{};
332 const Array4<const Real>& t_blank_xface_arr = (terrain_blank_xface) ? terrain_blank_xface->const_array(mfi) :
333 Array4<const Real>{};
334 const Array4<const Real>& t_blank_yface_arr = (terrain_blank_yface) ? terrain_blank_yface->const_array(mfi) :
335 Array4<const Real>{};
336 const Array4<const Real>& t_blank_zface_arr = (terrain_blank_zface) ? terrain_blank_zface->const_array(mfi) :
337 Array4<const Real>{};
339 const Array4<const Real>& cphi_arr = (cosPhi_mf) ? cosPhi_mf->const_array(mfi) :
340 Array4<const Real>{};
341 const Array4<const Real>& sphi_arr = (sinPhi_mf) ? sinPhi_mf->const_array(mfi) :
342 Array4<const Real>{};
344 const Array4<const Real>& z_nd_arr = z_phys_nd->const_array(mfi);
345 const Array4<const Real>& z_cc_arr = z_phys_cc->const_array(mfi);
351 if (use_coriolis && is_slow_step) {
352 if(solverChoice.
init_type == InitType::HindCast) {
353 const Array4<const Real>& latlon_arr = (*forecast_state_at_lev)[4].array(mfi);
355 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
358 Real v_loc =
fourth * (v(i,j+1,k) + v(i,j,k) + v(i-1,j+1,k) + v(i-1,j,k));
359 Real w_loc =
fourth * (
w(i,j,k+1) +
w(i,j,k) +
w(i-1,j,k+1) +
w(i-1,j,k));
360 Real latitude = latlon_arr(i,j,k,0);
361 Real sphi_loc = std::sin(latitude*
PI/
Real(180.0));
362 Real cphi_loc = std::cos(latitude*
PI/
Real(180.0));
363 xmom_src_arr(i, j, k) += coriolis_factor * rho_on_u_face * (v_loc * sphi_loc - w_loc * cphi_loc);
365 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
367 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j-1,k) + u(i,j-1,k));
368 Real latitude = latlon_arr(i,j,k,0);
369 Real sphi_loc = std::sin(latitude*
PI/
Real(180.0));
370 ymom_src_arr(i, j, k) += -coriolis_factor * rho_on_v_face * u_loc * sphi_loc;
372 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
374 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j,k-1) + u(i,j,k-1));
375 Real latitude = latlon_arr(i,j,k,0);
376 Real cphi_loc = std::cos(latitude*
PI/
Real(180.0));
377 zmom_src_arr(i, j, k) += coriolis_factor * rho_on_w_face * u_loc * cphi_loc;
380 else if (var_coriolis && (sinPhi_mf) && (cosPhi_mf)) {
382 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
385 Real v_loc =
fourth * (v(i,j+1,k) + v(i,j,k) + v(i-1,j+1,k) + v(i-1,j,k));
386 Real w_loc =
fourth * (
w(i,j,k+1) +
w(i,j,k) +
w(i-1,j,k+1) +
w(i-1,j,k));
387 Real sphi_loc =
myhalf * (sphi_arr(i,j,0) + sphi_arr(i-1,j,0));
388 Real cphi_loc =
myhalf * (cphi_arr(i,j,0) + cphi_arr(i-1,j,0));
389 xmom_src_arr(i, j, k) += coriolis_factor * rho_on_u_face * (v_loc * sphi_loc - w_loc * cphi_loc);
391 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
393 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j-1,k) + u(i,j-1,k));
394 Real sphi_loc =
myhalf * (sphi_arr(i,j,0) + sphi_arr(i,j-1,0));
395 ymom_src_arr(i, j, k) += -coriolis_factor * rho_on_v_face * u_loc * sphi_loc;
397 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
399 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j,k-1) + u(i,j,k-1));
400 zmom_src_arr(i, j, k) += coriolis_factor * rho_on_w_face * u_loc * cphi_arr(i,j,0);
404 Array4<const Real> u_volfrac = (ebfact.
get_u_const_factory())->getVolFrac().const_array(mfi);
405 Array4<const Real> v_volfrac = (ebfact.
get_v_const_factory())->getVolFrac().const_array(mfi);
406 Array4<const Real> w_volfrac = (ebfact.
get_w_const_factory())->getVolFrac().const_array(mfi);
407 ParallelFor(tbx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
410 Real v_vol = v_volfrac(i,j+1,k) + v_volfrac(i,j,k) + v_volfrac(i-1,j+1,k) + v_volfrac(i-1,j,k);
411 Real w_vol = w_volfrac(i,j,k+1) + w_volfrac(i,j,k) + w_volfrac(i-1,j,k+1) + w_volfrac(i-1,j,k);
414 v_loc = ( v_volfrac(i ,j+1,k) * v(i ,j+1,k) + v_volfrac(i ,j,k) * v(i ,j,k)
415 + v_volfrac(i-1,j+1,k) * v(i-1,j+1,k) + v_volfrac(i-1,j,k) * v(i-1,j,k)) / v_vol;
418 w_loc = ( w_volfrac(i ,j,k+1) *
w(i ,j,k+1) + w_volfrac(i ,j,k) *
w(i ,j,k)
419 + w_volfrac(i-1,j,k+1) *
w(i-1,j,k+1) + w_volfrac(i-1,j,k) *
w(i-1,j,k)) / w_vol;
421 xmom_src_arr(i, j, k) += coriolis_factor * rho_on_u_face * (v_loc * sinphi - w_loc * cosphi);
423 ParallelFor(tby, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
425 Real u_vol = u_volfrac(i+1,j,k) + u_volfrac(i,j,k) + u_volfrac(i+1,j-1,k) + u_volfrac(i,j-1,k);
428 u_loc = ( u_volfrac(i+1,j ,k) * u(i+1,j ,k) + u_volfrac(i,j ,k) * u(i,j ,k)
429 + u_volfrac(i+1,j-1,k) * u(i+1,j-1,k) + u_volfrac(i,j-1,k) * u(i,j-1,k)) / u_vol;
431 ymom_src_arr(i, j, k) += -coriolis_factor * rho_on_v_face * u_loc * sinphi;
433 ParallelFor(tbz, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
435 Real u_vol = u_volfrac(i+1,j,k) + u_volfrac(i,j,k) + u_volfrac(i+1,j,k-1) + u_volfrac(i,j,k-1);
438 u_loc = ( u_volfrac(i+1,j,k ) * u(i+1,j,k ) + u_volfrac(i,j,k) * u(i,j,k )
439 + u_volfrac(i+1,j,k-1) * u(i+1,j,k-1) + u_volfrac(i,j,k-1) * u(i,j,k-1)) / u_vol;
441 zmom_src_arr(i, j, k) += coriolis_factor * rho_on_w_face * u_loc * cosphi;
445 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
447 Real v_loc =
fourth * (v(i,j+1,k) + v(i,j,k) + v(i-1,j+1,k) + v(i-1,j,k));
448 Real w_loc =
fourth * (
w(i,j,k+1) +
w(i,j,k) +
w(i-1,j,k+1) +
w(i-1,j,k));
450 xmom_src_arr(i, j, k) += rho_on_u_face * ( coriolis_factor * (v_loc * sinphi - w_loc * cosphi) );
452 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
454 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j-1,k) + u(i,j-1,k));
455 ymom_src_arr(i, j, k) += rho_on_v_face * ( -coriolis_factor * u_loc * sinphi );
457 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
458 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j,k-1) + u(i,j,k-1));
460 zmom_src_arr(i, j, k) += rho_on_w_face * ( coriolis_factor * u_loc * cosphi );
471 if ( (is_slow_step && !use_Rayleigh_fast_uv) || (!is_slow_step && use_Rayleigh_fast_uv)) {
472 if (rayleigh_damp_U) {
473 ParallelFor(tbx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
476 Real uu = rho_u(i,j,k) / rho_on_u_face;
477 Real sinesq = d_sinesq_at_lev[k];
478 xmom_src_arr(i, j, k) -= dampcoef*sinesq * (uu -
ubar[k]) * rho_on_u_face;
482 if (rayleigh_damp_V) {
483 ParallelFor(tby, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
486 Real vv = rho_v(i,j,k) / rho_on_v_face;
487 Real sinesq = d_sinesq_at_lev[k];
488 ymom_src_arr(i, j, k) -= dampcoef*sinesq * (vv -
vbar[k]) * rho_on_v_face;
493 if ( (is_slow_step && !use_Rayleigh_fast_w) || (!is_slow_step && use_Rayleigh_fast_w)) {
494 if (rayleigh_damp_W) {
495 ParallelFor(tbz, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
498 Real ww = rho_w(i,j,k) / rho_on_w_face;
499 Real sinesq = d_sinesq_stag_at_lev[k];
500 zmom_src_arr(i, j, k) -= dampcoef*sinesq * (
ww -
wbar[k]) * rho_on_w_face;
510 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
513 xmom_src_arr(i, j, k) += rho_on_u_face * abl_geo_forcing[0];
515 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
518 ymom_src_arr(i, j, k) += rho_on_v_face * abl_geo_forcing[1];
520 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
523 zmom_src_arr(i, j, k) += rho_on_w_face * abl_geo_forcing[2];
530 if (geo_wind_profile && is_slow_step) {
532 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
535 xmom_src_arr(i, j, k) -= coriolis_factor * rho_on_u_face * dptr_v_geos[k] * sinphi;
537 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
540 ymom_src_arr(i, j, k) += coriolis_factor * rho_on_v_face * dptr_u_geos[k] * sinphi;
551 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
555 Real z_xf_lo =
fourth * ( z_nd_arr(i,j,k ) + z_nd_arr(i,j+1,k )
556 + z_nd_arr(i,j,k-1) + z_nd_arr(i,j+1,k-1) );
557 Real z_xf_hi =
fourth * ( z_nd_arr(i,j,k+1) + z_nd_arr(i,j+1,k+1)
558 + z_nd_arr(i,j,k+2) + z_nd_arr(i,j+1,k+2) );
559 dzInv =
one / (z_xf_hi - z_xf_lo);
561 Real rho_on_u_face =
myhalf * ( cell_data(i,j,k,
nr) + cell_data(i-1,j,k,
nr) );
562 Real U_hi = dptr_u_plane(k+1) / dptr_r_plane(k+1);
563 Real U_lo = dptr_u_plane(k-1) / dptr_r_plane(k-1);
564 Real wbar_xf =
myhalf * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
565 xmom_src_arr(i, j, k) -= rho_on_u_face * wbar_xf * (U_hi - U_lo) * dzInv;
567 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
571 Real z_yf_lo =
fourth * ( z_nd_arr(i,j,k ) + z_nd_arr(i+1,j,k )
572 + z_nd_arr(i,j,k-1) + z_nd_arr(i+1,j,k-1) );
573 Real z_yf_hi =
fourth * ( z_nd_arr(i,j,k+1) + z_nd_arr(i+1,j,k+1)
574 + z_nd_arr(i,j,k+2) + z_nd_arr(i+1,j,k+2) );
575 dzInv =
one / (z_yf_hi - z_yf_lo);
577 Real rho_on_v_face =
myhalf * ( cell_data(i,j,k,
nr) + cell_data(i,j-1,k,
nr) );
578 Real V_hi = dptr_v_plane(k+1) / dptr_r_plane(k+1);
579 Real V_lo = dptr_v_plane(k-1) / dptr_r_plane(k-1);
580 Real wbar_yf =
myhalf * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
581 ymom_src_arr(i, j, k) -= rho_on_v_face * wbar_yf * (V_hi - V_lo) * dzInv;
585 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
589 Real z_xf_lo =
fourth * ( z_nd_arr(i,j,k ) + z_nd_arr(i,j+1,k )
590 + z_nd_arr(i,j,k-1) + z_nd_arr(i,j+1,k-1) );
591 Real z_xf_hi =
fourth * ( z_nd_arr(i,j,k+1) + z_nd_arr(i,j+1,k+1)
592 + z_nd_arr(i,j,k+2) + z_nd_arr(i,j+1,k+2) );
593 dzInv =
one / (z_xf_hi - z_xf_lo);
595 Real U_hi = dptr_u_plane(k+1) / dptr_r_plane(k+1);
596 Real U_lo = dptr_u_plane(k-1) / dptr_r_plane(k-1);
597 Real wbar_xf =
myhalf * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
598 xmom_src_arr(i, j, k) -= wbar_xf * (U_hi - U_lo) * dzInv;
600 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
604 Real z_yf_lo =
fourth * ( z_nd_arr(i,j,k ) + z_nd_arr(i+1,j,k )
605 + z_nd_arr(i,j,k-1) + z_nd_arr(i+1,j,k-1) );
606 Real z_yf_hi =
fourth * ( z_nd_arr(i,j,k+1) + z_nd_arr(i+1,j,k+1)
607 + z_nd_arr(i,j,k+2) + z_nd_arr(i+1,j,k+2) );
608 dzInv =
one / (z_yf_hi - z_yf_lo);
610 Real V_hi = dptr_v_plane(k+1) / dptr_r_plane(k+1);
611 Real V_lo = dptr_v_plane(k-1) / dptr_r_plane(k-1);
612 Real wbar_yf =
myhalf * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
613 ymom_src_arr(i, j, k) -= wbar_yf * (V_hi - V_lo) * dzInv;
621 auto lsf_arr = lsf_tendencies->const_array(mfi);
623 const int kmin = domain.smallEnd(2) + 1;
624 const int kmax = domain.bigEnd(2) - 1;
626 ParallelFor(tbx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
628 if (k >= kmin && k <= kmax) {
630 if (lsf_arr(i, j, k, 2) >= 0.0)
643 + z_nd_arr(i,j,
k1+1) + z_nd_arr(i,j+1,
k1+1) );
644 Real z_uf_2 =
fourth * ( z_nd_arr(i,j,k2 ) + z_nd_arr(i,j+1,k2 )
645 + z_nd_arr(i,j,k2+1) + z_nd_arr(i,j+1,k2+1) );
646 dzInv =
one / (z_uf_1 - z_uf_2);
649 amrex::Real utend = -(dzInv * lsf_arr(i, j, k, 2)) * ( u(i, j,
k1) - u(i, j, k2) );
650 xmom_src_arr(i, j, k) += utend * rho_on_u_face;
654 ParallelFor(tby, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
656 if (k >= kmin && k <= kmax) {
658 if (lsf_arr(i, j, k, 2) >= 0.0)
671 + z_nd_arr(i,j,
k1+1) + z_nd_arr(i+1,j,
k1+1) );
672 Real z_vf_2 =
fourth * ( z_nd_arr(i,j,k2 ) + z_nd_arr(i+1,j,k2 )
673 + z_nd_arr(i,j,k2+1) + z_nd_arr(i+1,j,k2+1) );
674 dzInv =
one / (z_vf_1 - z_vf_2);
677 amrex::Real vtend = -(dzInv * lsf_arr(i, j, k, 2)) * ( v(i, j,
k1) - v(i, j, k2) );
678 ymom_src_arr(i, j, k) += vtend * rho_on_v_face;
696 Real uv_coeff_n = 1.0;
697 Real uv_coeff_np1 = 0.0;
699 const Real *u_nudge_n, *u_nudge_np1, *v_nudge_n, *v_nudge_np1;
706 for (
int nt = 1; nt < n_sounding_times; nt++) {
709 if (itime_n == n_sounding_times-1) {
712 itime_np1 = itime_n+1;
715 uv_coeff_n =
Real(1.0) - uv_coeff_np1;
717 u_nudge_n = input_sounding_data.
U_inp_sound_d[itime_n].dataPtr() + 1;
718 u_nudge_np1 = input_sounding_data.
U_inp_sound_d[itime_np1].dataPtr() + 1;
719 v_nudge_n = input_sounding_data.
V_inp_sound_d[itime_n].dataPtr() + 1;
720 v_nudge_np1 = input_sounding_data.
V_inp_sound_d[itime_np1].dataPtr() + 1;
729 u_nudge_n = lsf_data.
u_int_lsf_d[itime_curr].dataPtr();
730 u_nudge_np1 = lsf_data.
u_int_lsf_d[itime_next].dataPtr();
731 v_nudge_n = lsf_data.
v_int_lsf_d[itime_curr].dataPtr();
732 v_nudge_np1 = lsf_data.
v_int_lsf_d[itime_next].dataPtr();
735 ParallelFor(tbx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
737 Real z = z_cc_arr(i,j,k);
738 if (l_lsf || (z >= u_z1 && z <= u_z2)) {
739 Real unudge = -((dptr_u_plane(k)/dptr_r_plane(k)) - (uv_coeff_n*u_nudge_n[k] + uv_coeff_np1*u_nudge_np1[k]));
740 xmom_src_arr(i, j, k) += tau * unudge * dptr_r_plane(k);
744 ParallelFor(tby, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
746 Real z = z_cc_arr(i,j,k);
747 if (l_lsf || (z >= u_z1 && z <= u_z2)) {
748 Real vnudge = -((dptr_v_plane(k)/dptr_r_plane(k)) - (uv_coeff_n*v_nudge_n[k] + uv_coeff_np1*v_nudge_np1[k]));
749 ymom_src_arr(i, j, k) += tau * vnudge * dptr_r_plane(k);
759 const Array4<const Real>& mf_ux = mapfac[MapFac::ux]->const_array(mfi);
760 const Array4<const Real>& mf_uy = mapfac[MapFac::uy]->const_array(mfi);
761 const Array4<const Real>& mf_vx = mapfac[MapFac::vx]->const_array(mfi);
762 const Array4<const Real>& mf_vy = mapfac[MapFac::vy]->const_array(mfi);
764 u, cell_data, xmom_src_arr, mf_ux, mf_uy);
766 v, cell_data, ymom_src_arr, mf_vx, mf_vy);
777 z_cc_arr, xmom_src_arr, ymom_src_arr,
778 rho_u, rho_v, d_sponge_ptrs_at_lev);
783 xmom_src_arr, ymom_src_arr, zmom_src_arr, rho_u, rho_v, rho_w,
784 r0, z_nd_arr, z_cc_arr);
789 const Array4<const Real>& rho_u_forecast_state = (*forecast_state_at_lev)[
IntVars::xmom].array(mfi);
790 const Array4<const Real>& rho_v_forecast_state = (*forecast_state_at_lev)[
IntVars::ymom].array(mfi);
791 const Array4<const Real>& rho_w_forecast_state = (*forecast_state_at_lev)[
IntVars::zmom].array(mfi);
792 const Array4<const Real>& cons_forecast_state = (*forecast_state_at_lev)[
IntVars::cons].array(mfi);
794 xmom_src_arr, ymom_src_arr, zmom_src_arr,
796 rho_u_forecast_state, rho_v_forecast_state, rho_w_forecast_state,
797 cons_forecast_state);
805 ((is_slow_step && !use_canopy_fast) || (!is_slow_step && use_canopy_fast))) {
807 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
809 const Real ux = u(i, j, k);
810 const Real uy =
fourth * ( v(i, j , k ) + v(i-1, j , k )
811 + v(i, j+1, k ) + v(i-1, j+1, k ) );
812 const Real uz =
fourth * (
w(i, j , k ) +
w(i-1, j , k )
813 +
w(i, j , k+1) +
w(i-1, j , k+1) );
814 const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
815 const Real f_drag =
myhalf * (f_drag_arr(i, j, k) + f_drag_arr(i-1, j, k));
816 xmom_src_arr(i, j, k) -= f_drag * ux * windspeed;
818 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
820 const Real ux =
fourth * ( u(i , j , k ) + u(i , j-1, k )
821 + u(i+1, j , k ) + u(i+1, j-1, k ) );
822 const Real uy = v(i, j, k);
823 const Real uz =
fourth * (
w(i , j , k ) +
w(i , j-1, k )
824 +
w(i , j , k+1) +
w(i , j-1, k+1) );
825 const amrex::Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
826 const Real f_drag =
myhalf * (f_drag_arr(i, j, k) + f_drag_arr(i, j-1, k));
827 ymom_src_arr(i, j, k) -= f_drag * uy * windspeed;
829 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
832 + u(i , j , k-1) + u(i+1, j , k-1) );
834 + v(i , j , k-1) + v(i , j+1, k-1) );
836 const amrex::Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
837 const Real f_drag =
myhalf * (f_drag_arr(i, j, k) + f_drag_arr(i, j, k-1));
838 zmom_src_arr(i, j, k) -= f_drag * uz * windspeed;
844 if (solverChoice.
terrain_type == TerrainType::ImmersedForcing &&
845 ((is_slow_step && !use_ImmersedForcing_fast) || (!is_slow_step && use_ImmersedForcing_fast))) {
848 z_cc_arr, xmom_src_arr, geom, solverChoice, dt);
850 z_cc_arr, ymom_src_arr, geom, solverChoice, dt);
852 z_cc_arr, zmom_src_arr, geom, solverChoice, dt);
859 const Real* dx_arr = geom.CellSize();
860 const Real delta_xy = std::sqrt(dx_arr[0] * dx_arr[1]);
861 if ((solverChoice.
buildings_type == BuildingsType::ImmersedForcing) &&
862 ((is_slow_step && !use_ImmersedForcing_fast) || (!is_slow_step && use_ImmersedForcing_fast)) &&
863 (delta_xy <= 50.0)) {
866 z_cc_arr, xmom_src_arr, geom, solverChoice, dt);
868 z_cc_arr, ymom_src_arr, geom, solverChoice, dt);
870 z_cc_arr, zmom_src_arr, geom, solverChoice, dt);
876 if (is_slow_step && (enforce_massflux_x || enforce_massflux_y)) {
880 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
881 xmom_src_arr(i, j, k) += tau_inv * (rhoUA_target - rhoUA);
883 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
884 ymom_src_arr(i, j, k) += tau_inv * (rhoVA_target - rhoVA);
void ApplyBndryForcing_Forecast(const SolverChoice &solverChoice, const Geometry geom, const Box &tbx, const Box &tby, const Box &tbz, const Array4< const Real > &z_phys_nd, const Array4< Real > &rho_u_rhs, const Array4< Real > &rho_v_rhs, const Array4< Real > &rho_w_rhs, const Array4< const Real > &rho_u, const Array4< const Real > &rho_v, const Array4< const Real > &rho_w, const Array4< const Real > &rho_u_initial_state, const Array4< const Real > &rho_v_initial_state, const Array4< const Real > &rho_w_initial_state, const Array4< const Real > &cons_initial_state)
Definition: ERF_ApplyBndryForcing_Forecast.cpp:8
void ApplySpongeZoneBCsForMom(const SpongeChoice &spongeChoice, const Geometry geom, const Box &tbx, const Box &tby, const Box &tbz, const Array4< Real > &rho_u_rhs, const Array4< Real > &rho_v_rhs, const Array4< Real > &rho_w_rhs, const Array4< const Real > &rho_u, const Array4< const Real > &rho_v, const Array4< const Real > &rho_w, const Array4< const Real > &r0, const Array4< const Real > &z_phys_nd, const Array4< const Real > &z_phys_cc)
Apply sponge zone damping to momentum variables.
Definition: ERF_ApplySpongeZoneBCs.cpp:211
void ApplySpongeZoneBCsForMom_ReadFromFile(const SpongeChoice &spongeChoice, const Geometry geom, const Box &tbx, const Box &tby, const Array4< const Real > &cell_data, const Array4< const Real > &z_phys_cc, const Array4< Real > &rho_u_rhs, const Array4< Real > &rho_v_rhs, const Array4< const Real > &rho_u, const Array4< const Real > &rho_v, const Vector< Real * > d_sponge_ptrs_at_lev)
Definition: ERF_ApplySpongeZoneBCs_ReadFromFile.cpp:23
@ ubar
Definition: ERF_DataStruct.H:194
@ wbar
Definition: ERF_DataStruct.H:194
@ vbar
Definition: ERF_DataStruct.H:194
DirectionSelector< 2 > ZDir
Definition: ERF_DirectionSelector.H:55
void ImmersedForcingBuildings_Ymom(const Box &tby, const Array4< const Real > &u, const Array4< const Real > &v, const Array4< const Real > &w, const Array4< const Real > &cell_data, const Array4< const Real > &t_blank_arr, const Array4< const Real > &t_blank_yface_arr, const Array4< const Real > &z_cc_arr, const Array4< Real > &ymom_src_arr, const Geometry &geom, const SolverChoice &solverChoice, const Real fac)
Definition: ERF_ImmersedForcing.cpp:562
void ImmersedForcingTerrain_Ymom(const Box &tby, const Array4< const Real > &u, const Array4< const Real > &v, const Array4< const Real > &w, const Array4< const Real > &cell_data, const Array4< const Real > &t_blank_arr, const Array4< const Real > &t_blank_yface_arr, const Array4< const Real > &z_cc_arr, const Array4< Real > &ymom_src_arr, const Geometry &geom, const SolverChoice &solverChoice, const Real fac)
Definition: ERF_ImmersedForcing.cpp:194
void ImmersedForcingBuildings_Xmom(const Box &tbx, const Array4< const Real > &u, const Array4< const Real > &v, const Array4< const Real > &w, const Array4< const Real > &cell_data, const Array4< const Real > &t_blank_arr, const Array4< const Real > &t_blank_xface_arr, const Array4< const Real > &z_cc_arr, const Array4< Real > &xmom_src_arr, const Geometry &geom, const SolverChoice &solverChoice, const Real fac)
Definition: ERF_ImmersedForcing.cpp:363
void ImmersedForcingTerrain_Xmom(const Box &tbx, const Array4< const Real > &u, const Array4< const Real > &v, const Array4< const Real > &w, const Array4< const Real > &cell_data, const Array4< const Real > &t_blank_arr, const Array4< const Real > &t_blank_xface_arr, const Array4< const Real > &z_cc_arr, const Array4< Real > &xmom_src_arr, const Geometry &geom, const SolverChoice &solverChoice, const Real fac)
Definition: ERF_ImmersedForcing.cpp:79
void ImmersedForcingBuildings_Zmom(const Box &tbz, const Array4< const Real > &u, const Array4< const Real > &v, const Array4< const Real > &w, const Array4< const Real > &cell_data, const Array4< const Real > &t_blank_arr, const Array4< const Real > &t_blank_zface_arr, const Array4< const Real > &z_cc_arr, const Array4< Real > &zmom_src_arr, const Geometry &geom, const SolverChoice &solverChoice, const Real fac)
Definition: ERF_ImmersedForcing.cpp:760
void ImmersedForcingTerrain_Zmom(const Box &tbz, const Array4< const Real > &u, const Array4< const Real > &v, const Array4< const Real > &w, const Array4< const Real > &cell_data, const Array4< const Real > &t_blank_arr, const Array4< const Real > &t_blank_zface_arr, const Array4< const Real > &z_cc_arr, const Array4< Real > &zmom_src_arr, const Geometry &geom, const SolverChoice &solverChoice, const Real fac)
Definition: ERF_ImmersedForcing.cpp:308
#define Rho_comp
Definition: ERF_IndexDefines.H:42
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
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 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
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:46
void NumericalDiffusion_Ymom(const Box &bx, const double dt, const Real num_diff_coeff, const Array4< const Real > &prim_data, const Array4< const Real > &cell_data, const Array4< Real > &rhs, const Array4< const Real > &mfx_arr, const Array4< const Real > &mfy_arr)
Definition: ERF_NumericalDiffusion.cpp:151
void NumericalDiffusion_Xmom(const Box &bx, const double dt, const Real num_diff_coeff, const Array4< const Real > &prim_data, const Array4< const Real > &cell_data, const Array4< Real > &rhs, const Array4< const Real > &mfx_arr, const Array4< const Real > &mfy_arr)
Definition: ERF_NumericalDiffusion.cpp:85
Real w
Definition: ERF_Plotfile2DInterpolator.cpp:22
AMREX_FORCE_INLINE IntVect offset(const int face_dir, const int normal)
Definition: ERF_ReadBndryPlanes.cpp:32
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_PlaneAverage.H:14
eb_aux_ const * get_w_const_factory() const noexcept
Return the ERF auxiliary z-face EB factory.
Definition: ERF_EB.H:133
eb_aux_ const * get_v_const_factory() const noexcept
Return the ERF auxiliary y-face EB factory.
Definition: ERF_EB.H:131
eb_aux_ const * get_u_const_factory() const noexcept
Return the ERF auxiliary x-face EB factory.
Definition: ERF_EB.H:129
@ r0_comp
Definition: ERF_IndexDefines.H:79
@ ymom
Definition: ERF_IndexDefines.H:237
@ cons
Definition: ERF_IndexDefines.H:235
@ zmom
Definition: ERF_IndexDefines.H:238
@ xmom
Definition: ERF_IndexDefines.H:236
@ nr
Definition: ERF_Morrison.H:47
@ xvel
Definition: ERF_IndexDefines.H:218
@ cons
Definition: ERF_IndexDefines.H:217
@ yvel
Definition: ERF_IndexDefines.H:219
@ ww
Definition: ERF_AdvanceWSM6.cpp:107
real(c_double), private k1
Definition: ERF_module_mp_morr_two_moment.F90:213
real(kind=kind_phys), parameter, private r0
Definition: ERF_module_mp_wdm6.F90:75
RayleighDampingType rayleigh_damping_type
Selected Rayleigh damping time-integration treatment.
Definition: ERF_DampingStruct.H:111
amrex::Real rayleigh_dampcoef
Rayleigh damping inverse time scale [1/s].
Definition: ERF_DampingStruct.H:98
bool rayleigh_damp_U
Whether Rayleigh damping is applied to x-momentum.
Definition: ERF_DampingStruct.H:94
bool rayleigh_damp_V
Whether Rayleigh damping is applied to y-momentum.
Definition: ERF_DampingStruct.H:95
bool rayleigh_damp_W
Whether Rayleigh damping is applied to vertical momentum.
Definition: ERF_DampingStruct.H:96
void get_forcing_time_coeffs(const amrex::Real &time, int &curr, int &next, amrex::Real &coeff_curr, amrex::Real &coeff_next) const
Determine interpolation coefficients to apply tendencies for the given time.
Definition: ERF_LargeScaleForcingData.H:335
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > v_int_lsf_d
Definition: ERF_LargeScaleForcingData.H:457
amrex::Real tau_lsf
Definition: ERF_LargeScaleForcingData.H:407
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > u_int_lsf_d
Definition: ERF_LargeScaleForcingData.H:457
amrex::Real const_massflux_v
Target constant mass flux in the y direction.
Definition: ERF_DataStruct.H:2624
static InitType init_type
Initial-condition source selected for the run.
Definition: ERF_DataStruct.H:2218
amrex::Real coriolis_factor
Twice the planetary rotation rate used for Coriolis forcing.
Definition: ERF_DataStruct.H:2353
static bool flat_terrain
Permit fixed-index planar averages after validating a flat fitted mesh.
Definition: ERF_DataStruct.H:2227
bool variable_coriolis
Whether spatially varying Coriolis forcing is enabled.
Definition: ERF_DataStruct.H:2570
int ave_plane
Averaging plane index used by diagnostics.
Definition: ERF_DataStruct.H:2572
amrex::Real const_massflux_u
Target constant mass flux in the x direction.
Definition: ERF_DataStruct.H:2623
bool forest_substep
Whether canopy source terms are applied only during substeps.
Definition: ERF_DataStruct.H:2314
amrex::Real num_diff_coeff
Numerical diffusion coefficient after input scaling.
Definition: ERF_DataStruct.H:2521
bool hindcast_lateral_forcing
Whether hindcast lateral forcing is enabled.
Definition: ERF_DataStruct.H:2633
amrex::Real nudging_u_z2
Definition: ERF_DataStruct.H:2377
bool use_coriolis
Whether Coriolis forcing is enabled.
Definition: ERF_DataStruct.H:2307
static MeshType mesh_type
Vertical mesh representation.
Definition: ERF_DataStruct.H:2236
SpongeChoice spongeChoice
Sponge-layer options.
Definition: ERF_DataStruct.H:2251
bool have_geo_wind_profile
Whether a geostrophic wind profile has been configured.
Definition: ERF_DataStruct.H:2568
DampingChoice dampingChoice
Damping-related options.
Definition: ERF_DataStruct.H:2250
amrex::Real nudging_u_z1
Definition: ERF_DataStruct.H:2376
bool do_forest_drag
Whether forest canopy drag is enabled.
Definition: ERF_DataStruct.H:2615
int massflux_khi
Upper vertical index for constant-mass-flux forcing.
Definition: ERF_DataStruct.H:2629
bool large_scale_forcing
Definition: ERF_DataStruct.H:2387
static TerrainType terrain_type
Terrain or immersed-boundary representation.
Definition: ERF_DataStruct.H:2224
amrex::Real cosphi
Cosine of the latitude used for Coriolis forcing.
Definition: ERF_DataStruct.H:2354
static BuildingsType buildings_type
Building representation.
Definition: ERF_DataStruct.H:2230
int massflux_klo
Lower vertical index for constant-mass-flux forcing.
Definition: ERF_DataStruct.H:2628
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_geo_forcing
Applied geostrophic-wind forcing vector.
Definition: ERF_DataStruct.H:2566
bool custom_w_subsidence
Whether custom vertical subsidence is enabled.
Definition: ERF_DataStruct.H:2360
bool immersed_forcing_substep
Whether immersed-forcing source terms are applied only during substeps.
Definition: ERF_DataStruct.H:2313
amrex::Real const_massflux_tau
Relaxation time scale for constant-mass-flux forcing.
Definition: ERF_DataStruct.H:2625
amrex::Real sinphi
Sine of the latitude used for Coriolis forcing.
Definition: ERF_DataStruct.H:2355
bool do_mom_advection
Whether custom vertical subsidence is applied to momentum.
Definition: ERF_DataStruct.H:2362
bool custom_forcing_prim_vars
Whether custom forcing operates on primitive variables.
Definition: ERF_DataStruct.H:2364
bool nudging_u
Definition: ERF_DataStruct.H:2383
bool nudging_from_input_sounding
Whether solution fields are nudged toward input sounding data.
Definition: ERF_DataStruct.H:2370
static SpongeType sponge_type
Selected sponge damping model.
Definition: ERF_SpongeStruct.H:100