Function for computing the slow RHS for the evolution equations for the density, potential temperature and momentum.
70 BL_PROFILE_REGION(
"erf_make_mom_sources()");
72 Real time =
static_cast<Real>(time_d);
74 Box domain(geom.Domain());
75 const GpuArray<Real, AMREX_SPACEDIM>
dxInv = geom.InvCellSizeArray();
109 if (solverChoice.
terrain_type == TerrainType::ImmersedForcing) {
111 amrex::Error(
" Currently forest canopy cannot be used with immersed forcing");
121 auto cosphi = solverChoice.
cosphi;
122 auto sinphi = solverChoice.
sinphi;
153 Real rhoUA_target{0};
154 Real rhoVA_target{0};
161 Table1D<Real> dptr_r_plane, dptr_u_plane, dptr_v_plane;
162 TableData<Real, 1> r_plane_tab, u_plane_tab, v_plane_tab;
165 enforce_massflux_x || enforce_massflux_y))
171 const int u_offset = 1;
172 const int v_offset = 1;
181 r_ave.compute_averages(
ZDir(), r_ave.field());
183 int ncell = r_ave.ncell_line();
184 Gpu::HostVector< Real> r_plane_h(ncell);
185 Gpu::DeviceVector< Real> r_plane_d(ncell);
187 r_ave.line_average(
Rho_comp, r_plane_h);
189 Gpu::copyAsync(Gpu::hostToDevice, r_plane_h.begin(), r_plane_h.end(), r_plane_d.begin());
191 Real* dptr_r = r_plane_d.data();
193 Box tdomain = domain; tdomain.grow(2,ng_c[2]);
194 r_plane_tab.resize({tdomain.smallEnd(2)}, {tdomain.bigEnd(2)});
196 dptr_r_plane = r_plane_tab.table();
197 ParallelFor(ncell, [=] AMREX_GPU_DEVICE (
int k) noexcept
199 dptr_r_plane(k-
offset) = dptr_r[k];
203 IntVect ng_u = S_data[
IntVars::xmom].nGrowVect(); ng_u[2] = u_offset;
206 IntVect ng_v = S_data[
IntVars::ymom].nGrowVect(); ng_v[2] = v_offset;
209 u_ave.compute_averages(
ZDir(), u_ave.field());
210 v_ave.compute_averages(
ZDir(), v_ave.field());
212 int u_ncell = u_ave.ncell_line();
213 int v_ncell = v_ave.ncell_line();
214 Gpu::HostVector< Real> u_plane_h(u_ncell), v_plane_h(v_ncell);
215 Gpu::DeviceVector< Real> u_plane_d(u_ncell), v_plane_d(v_ncell);
217 u_ave.line_average(0, u_plane_h);
218 v_ave.line_average(0, v_plane_h);
220 Gpu::copyAsync(Gpu::hostToDevice, u_plane_h.begin(), u_plane_h.end(), u_plane_d.begin());
221 Gpu::copyAsync(Gpu::hostToDevice, v_plane_h.begin(), v_plane_h.end(), v_plane_d.begin());
223 Real* dptr_u = u_plane_d.data();
224 Real* dptr_v = v_plane_d.data();
226 Box udomain = domain; udomain.grow(2,ng_u[2]);
227 Box vdomain = domain; vdomain.grow(2,ng_v[2]);
228 u_plane_tab.resize({udomain.smallEnd(2)}, {udomain.bigEnd(2)});
229 v_plane_tab.resize({vdomain.smallEnd(2)}, {vdomain.bigEnd(2)});
231 dptr_u_plane = u_plane_tab.table();
232 ParallelFor(u_ncell, [=] AMREX_GPU_DEVICE (
int k) noexcept
234 dptr_u_plane(k-u_offset) = dptr_u[k];
237 dptr_v_plane = v_plane_tab.table();
238 ParallelFor(v_ncell, [=] AMREX_GPU_DEVICE (
int k) noexcept
240 dptr_v_plane(k-v_offset) = dptr_v[k];
244 if (enforce_massflux_x || enforce_massflux_y) {
245 Real Lx = geom.ProbHi(0) - geom.ProbLo(0);
246 Real Ly = geom.ProbHi(1) - geom.ProbLo(1);
248 if (solverChoice.
mesh_type == MeshType::ConstantDz) {
250 rhoUA = std::accumulate(u_plane_h.begin() + u_offset + massflux_klo,
251 u_plane_h.begin() + u_offset + massflux_khi+1,
zero);
252 rhoVA = std::accumulate(v_plane_h.begin() + v_offset + massflux_klo,
253 v_plane_h.begin() + v_offset + massflux_khi+1,
zero);
254 rhoUA_target = std::accumulate(r_plane_h.begin() +
offset + massflux_klo,
255 r_plane_h.begin() +
offset + massflux_khi+1,
zero);
256 rhoVA_target = rhoUA_target;
258 rhoUA *= geom.CellSize(2) * Ly;
259 rhoVA *= geom.CellSize(2) * Lx;
260 rhoUA_target *= geom.CellSize(2) * Ly;
261 rhoVA_target *= geom.CellSize(2) * Lx;
263 }
else if (solverChoice.
mesh_type == MeshType::StretchedDz) {
265 for (
int k=massflux_klo; k < massflux_khi; ++k) {
266 rhoUA += u_plane_h[k + u_offset] * stretched_dz_h[k];
267 rhoVA += v_plane_h[k + v_offset] * stretched_dz_h[k];
268 rhoUA_target += r_plane_h[k +
offset] * stretched_dz_h[k];
270 rhoVA_target = rhoUA_target;
279 rhoUA_target *= U_target;
280 rhoVA_target *= V_target;
282 Print() <<
"Integrated mass flux : " << rhoUA <<
" " << rhoVA
283 <<
" (target: " << rhoUA_target <<
" " << rhoVA_target <<
")"
291 for ( MFIter mfi(S_data[
IntVars::cons]); mfi.isValid(); ++mfi)
293 Box tbx = mfi.nodaltilebox(0);
294 Box tby = mfi.nodaltilebox(1);
295 Box tbz = mfi.nodaltilebox(2);
296 if (tbz.bigEnd(2) == domain.bigEnd(2)+1) tbz.growHi(2,-1);
298 const Array4<const Real>& cell_data = S_data[
IntVars::cons].array(mfi);
299 const Array4<const Real>& rho_u = S_data[
IntVars::xmom].array(mfi);
300 const Array4<const Real>& rho_v = S_data[
IntVars::ymom].array(mfi);
301 const Array4<const Real>& rho_w = S_data[
IntVars::zmom].array(mfi);
303 const Array4<const Real>& u =
xvel.array(mfi);
304 const Array4<const Real>& v =
yvel.array(mfi);
305 const Array4<const Real>&
w = wvel.array(mfi);
307 const Array4< Real>& xmom_src_arr = xmom_src.array(mfi);
308 const Array4< Real>& ymom_src_arr = ymom_src.array(mfi);
309 const Array4< Real>& zmom_src_arr = zmom_src.array(mfi);
311 const Array4<const Real>&
r0 = r_hse.const_array(mfi);
313 const Array4<const Real>& f_drag_arr = (forest_drag) ? forest_drag->const_array(mfi) :
314 Array4<const Real>{};
315 const Array4<const Real>& t_blank_arr = (terrain_blank) ? terrain_blank->const_array(mfi) :
316 Array4<const Real>{};
318 const Array4<const Real>& cphi_arr = (cosPhi_mf) ? cosPhi_mf->const_array(mfi) :
319 Array4<const Real>{};
320 const Array4<const Real>& sphi_arr = (sinPhi_mf) ? sinPhi_mf->const_array(mfi) :
321 Array4<const Real>{};
323 const Array4<const Real>& z_nd_arr = z_phys_nd->const_array(mfi);
324 const Array4<const Real>& z_cc_arr = z_phys_cc->const_array(mfi);
330 if (use_coriolis && is_slow_step) {
331 if(solverChoice.
init_type == InitType::HindCast) {
332 const Array4<const Real>& latlon_arr = (*forecast_state_at_lev)[4].array(mfi);
334 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
337 Real v_loc =
fourth * (v(i,j+1,k) + v(i,j,k) + v(i-1,j+1,k) + v(i-1,j,k));
338 Real w_loc =
fourth * (
w(i,j,k+1) +
w(i,j,k) +
w(i,j-1,k+1) +
w(i,j-1,k));
339 Real latitude = latlon_arr(i,j,k,0);
340 Real sphi_loc = std::sin(latitude*
PI/
Real(180.0));
341 Real cphi_loc = std::cos(latitude*
PI/
Real(180.0));
342 xmom_src_arr(i, j, k) += coriolis_factor * rho_on_u_face * (v_loc * sphi_loc - w_loc * cphi_loc);
344 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
346 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j-1,k) + u(i,j-1,k));
347 Real latitude = latlon_arr(i,j,k,0);
348 Real sphi_loc = std::sin(latitude*
PI/
Real(180.0));
349 ymom_src_arr(i, j, k) += -coriolis_factor * rho_on_v_face * u_loc * sphi_loc;
351 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
353 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j,k-1) + u(i,j,k-1));
354 Real latitude = latlon_arr(i,j,k,0);
355 Real cphi_loc = std::cos(latitude*
PI/
Real(180.0));
356 zmom_src_arr(i, j, k) += coriolis_factor * rho_on_w_face * u_loc * cphi_loc;
359 else if (var_coriolis && (sinPhi_mf) && (cosPhi_mf)) {
361 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
364 Real v_loc =
fourth * (v(i,j+1,k) + v(i,j,k) + v(i-1,j+1,k) + v(i-1,j,k));
365 Real w_loc =
fourth * (
w(i,j,k+1) +
w(i,j,k) +
w(i-1,j,k+1) +
w(i-1,j,k));
366 Real sphi_loc =
myhalf * (sphi_arr(i,j,0) + sphi_arr(i-1,j,0));
367 Real cphi_loc =
myhalf * (cphi_arr(i,j,0) + cphi_arr(i-1,j,0));
368 xmom_src_arr(i, j, k) += coriolis_factor * rho_on_u_face * (v_loc * sphi_loc - w_loc * cphi_loc);
370 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
372 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j-1,k) + u(i,j-1,k));
373 Real sphi_loc =
myhalf * (sphi_arr(i,j,0) + sphi_arr(i,j-1,0));
374 ymom_src_arr(i, j, k) += -coriolis_factor * rho_on_v_face * u_loc * sphi_loc;
376 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
378 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j,k-1) + u(i,j,k-1));
379 zmom_src_arr(i, j, k) += coriolis_factor * rho_on_w_face * u_loc * cphi_arr(i,j,0);
383 Array4<const Real> u_volfrac = (ebfact.
get_u_const_factory())->getVolFrac().const_array(mfi);
384 Array4<const Real> v_volfrac = (ebfact.
get_v_const_factory())->getVolFrac().const_array(mfi);
385 Array4<const Real> w_volfrac = (ebfact.
get_w_const_factory())->getVolFrac().const_array(mfi);
386 ParallelFor(tbx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
389 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);
390 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);
393 v_loc = ( v_volfrac(i ,j+1,k) * v(i ,j+1,k) + v_volfrac(i ,j,k) * v(i ,j,k)
394 + 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;
397 w_loc = ( w_volfrac(i ,j,k+1) *
w(i ,j,k+1) + w_volfrac(i ,j,k) *
w(i ,j,k)
398 + 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;
400 xmom_src_arr(i, j, k) += coriolis_factor * rho_on_u_face * (v_loc * sinphi - w_loc * cosphi);
402 ParallelFor(tby, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
404 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);
407 u_loc = ( u_volfrac(i+1,j ,k) * u(i+1,j ,k) + u_volfrac(i,j ,k) * u(i,j ,k)
408 + 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;
410 ymom_src_arr(i, j, k) += -coriolis_factor * rho_on_v_face * u_loc * sinphi;
412 ParallelFor(tbz, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
414 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);
417 u_loc = ( u_volfrac(i+1,j,k ) * u(i+1,j,k ) + u_volfrac(i,j,k) * u(i,j,k )
418 + 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;
420 zmom_src_arr(i, j, k) += coriolis_factor * rho_on_w_face * u_loc * cosphi;
424 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
426 Real v_loc =
fourth * (v(i,j+1,k) + v(i,j,k) + v(i-1,j+1,k) + v(i-1,j,k));
427 Real w_loc =
fourth * (
w(i,j,k+1) +
w(i,j,k) +
w(i-1,j,k+1) +
w(i-1,j,k));
429 xmom_src_arr(i, j, k) += rho_on_u_face * ( coriolis_factor * (v_loc * sinphi - w_loc * cosphi) );
431 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
433 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j-1,k) + u(i,j-1,k));
434 ymom_src_arr(i, j, k) += rho_on_v_face * ( -coriolis_factor * u_loc * sinphi );
436 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
437 Real u_loc =
fourth * (u(i+1,j,k) + u(i,j,k) + u(i+1,j,k-1) + u(i,j,k-1));
439 zmom_src_arr(i, j, k) += rho_on_w_face * ( coriolis_factor * u_loc * cosphi );
450 if ( (is_slow_step && !use_Rayleigh_fast_uv) || (!is_slow_step && use_Rayleigh_fast_uv)) {
451 if (rayleigh_damp_U) {
452 ParallelFor(tbx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
455 Real uu = rho_u(i,j,k) / rho_on_u_face;
456 Real sinesq = d_sinesq_at_lev[k];
457 xmom_src_arr(i, j, k) -= dampcoef*sinesq * (uu -
ubar[k]) * rho_on_u_face;
461 if (rayleigh_damp_V) {
462 ParallelFor(tby, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
465 Real vv = rho_v(i,j,k) / rho_on_v_face;
466 Real sinesq = d_sinesq_at_lev[k];
467 ymom_src_arr(i, j, k) -= dampcoef*sinesq * (vv -
vbar[k]) * rho_on_v_face;
472 if ( (is_slow_step && !use_Rayleigh_fast_w) || (!is_slow_step && use_Rayleigh_fast_w)) {
473 if (rayleigh_damp_W) {
474 ParallelFor(tbz, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
477 Real ww = rho_w(i,j,k) / rho_on_w_face;
478 Real sinesq = d_sinesq_stag_at_lev[k];
479 zmom_src_arr(i, j, k) -= dampcoef*sinesq * (
ww -
wbar[k]) * rho_on_w_face;
489 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
492 xmom_src_arr(i, j, k) += rho_on_u_face * abl_geo_forcing[0];
494 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
497 ymom_src_arr(i, j, k) += rho_on_v_face * abl_geo_forcing[1];
499 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
502 zmom_src_arr(i, j, k) += rho_on_w_face * abl_geo_forcing[2];
509 if (geo_wind_profile && is_slow_step) {
511 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
514 xmom_src_arr(i, j, k) -= coriolis_factor * rho_on_u_face * dptr_v_geos[k] * sinphi;
516 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
519 ymom_src_arr(i, j, k) += coriolis_factor * rho_on_v_face * dptr_u_geos[k] * sinphi;
530 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
534 Real z_xf_lo =
fourth * ( z_nd_arr(i,j,k ) + z_nd_arr(i,j+1,k )
535 + z_nd_arr(i,j,k-1) + z_nd_arr(i,j+1,k-1) );
536 Real z_xf_hi =
fourth * ( z_nd_arr(i,j,k+1) + z_nd_arr(i,j+1,k+1)
537 + z_nd_arr(i,j,k+2) + z_nd_arr(i,j+1,k+2) );
538 dzInv =
one / (z_xf_hi - z_xf_lo);
540 Real rho_on_u_face =
myhalf * ( cell_data(i,j,k,
nr) + cell_data(i-1,j,k,
nr) );
541 Real U_hi = dptr_u_plane(k+1) / dptr_r_plane(k+1);
542 Real U_lo = dptr_u_plane(k-1) / dptr_r_plane(k-1);
543 Real wbar_xf =
myhalf * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
544 xmom_src_arr(i, j, k) -= rho_on_u_face * wbar_xf * (U_hi - U_lo) * dzInv;
546 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
550 Real z_yf_lo =
fourth * ( z_nd_arr(i,j,k ) + z_nd_arr(i+1,j,k )
551 + z_nd_arr(i,j,k-1) + z_nd_arr(i+1,j,k-1) );
552 Real z_yf_hi =
fourth * ( z_nd_arr(i,j,k+1) + z_nd_arr(i+1,j,k+1)
553 + z_nd_arr(i,j,k+2) + z_nd_arr(i+1,j,k+2) );
554 dzInv =
one / (z_yf_hi - z_yf_lo);
556 Real rho_on_v_face =
myhalf * ( cell_data(i,j,k,
nr) + cell_data(i,j-1,k,
nr) );
557 Real V_hi = dptr_v_plane(k+1) / dptr_r_plane(k+1);
558 Real V_lo = dptr_v_plane(k-1) / dptr_r_plane(k-1);
559 Real wbar_yf =
myhalf * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
560 ymom_src_arr(i, j, k) -= rho_on_v_face * wbar_yf * (V_hi - V_lo) * dzInv;
564 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
568 Real z_xf_lo =
fourth * ( z_nd_arr(i,j,k ) + z_nd_arr(i,j+1,k )
569 + z_nd_arr(i,j,k-1) + z_nd_arr(i,j+1,k-1) );
570 Real z_xf_hi =
fourth * ( z_nd_arr(i,j,k+1) + z_nd_arr(i,j+1,k+1)
571 + z_nd_arr(i,j,k+2) + z_nd_arr(i,j+1,k+2) );
572 dzInv =
one / (z_xf_hi - z_xf_lo);
574 Real U_hi = dptr_u_plane(k+1) / dptr_r_plane(k+1);
575 Real U_lo = dptr_u_plane(k-1) / dptr_r_plane(k-1);
576 Real wbar_xf =
myhalf * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
577 xmom_src_arr(i, j, k) -= wbar_xf * (U_hi - U_lo) * dzInv;
579 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
583 Real z_yf_lo =
fourth * ( z_nd_arr(i,j,k ) + z_nd_arr(i+1,j,k )
584 + z_nd_arr(i,j,k-1) + z_nd_arr(i+1,j,k-1) );
585 Real z_yf_hi =
fourth * ( z_nd_arr(i,j,k+1) + z_nd_arr(i+1,j,k+1)
586 + z_nd_arr(i,j,k+2) + z_nd_arr(i+1,j,k+2) );
587 dzInv =
one / (z_yf_hi - z_yf_lo);
589 Real V_hi = dptr_v_plane(k+1) / dptr_r_plane(k+1);
590 Real V_lo = dptr_v_plane(k-1) / dptr_r_plane(k-1);
591 Real wbar_yf =
myhalf * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
592 ymom_src_arr(i, j, k) -= wbar_yf * (V_hi - V_lo) * dzInv;
611 for (
int nt = 1; nt < n_sounding_times; nt++) {
614 if (itime_n == n_sounding_times-1) {
617 itime_np1 = itime_n+1;
620 coeff_n =
one - coeff_np1;
625 const Real* u_inp_sound_n = input_sounding_data.
U_inp_sound_d[itime_n].dataPtr();
626 const Real* u_inp_sound_np1 = input_sounding_data.
U_inp_sound_d[itime_np1].dataPtr();
627 const Real* v_inp_sound_n = input_sounding_data.
V_inp_sound_d[itime_n].dataPtr();
628 const Real* v_inp_sound_np1 = input_sounding_data.
V_inp_sound_d[itime_np1].dataPtr();
630 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
632 Real nudge_u = (coeff_n*u_inp_sound_n[k] + coeff_np1*u_inp_sound_np1[k]) - (dptr_u_plane(k)/dptr_r_plane(k));
634 xmom_src_arr(i, j, k) += cell_data(i, j, k,
nr) * nudge_u;
636 [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
638 Real nudge_v = (coeff_n*v_inp_sound_n[k] + coeff_np1*v_inp_sound_np1[k]) - (dptr_v_plane(k)/dptr_r_plane(k));
640 ymom_src_arr(i, j, k) += cell_data(i, j, k,
nr) * nudge_v;
649 const Array4<const Real>& mf_ux = mapfac[MapFac::ux]->const_array(mfi);
650 const Array4<const Real>& mf_uy = mapfac[MapFac::uy]->const_array(mfi);
651 const Array4<const Real>& mf_vx = mapfac[MapFac::vx]->const_array(mfi);
652 const Array4<const Real>& mf_vy = mapfac[MapFac::vy]->const_array(mfi);
654 u, cell_data, xmom_src_arr, mf_ux, mf_uy);
656 v, cell_data, ymom_src_arr, mf_vx, mf_vy);
667 z_cc_arr, xmom_src_arr, ymom_src_arr,
668 rho_u, rho_v, d_sponge_ptrs_at_lev);
673 xmom_src_arr, ymom_src_arr, zmom_src_arr, rho_u, rho_v, rho_w,
674 r0, z_nd_arr, z_cc_arr);
679 const Array4<const Real>& rho_u_forecast_state = (*forecast_state_at_lev)[
IntVars::xmom].array(mfi);
680 const Array4<const Real>& rho_v_forecast_state = (*forecast_state_at_lev)[
IntVars::ymom].array(mfi);
681 const Array4<const Real>& rho_w_forecast_state = (*forecast_state_at_lev)[
IntVars::zmom].array(mfi);
682 const Array4<const Real>& cons_forecast_state = (*forecast_state_at_lev)[
IntVars::cons].array(mfi);
684 xmom_src_arr, ymom_src_arr, zmom_src_arr,
686 rho_u_forecast_state, rho_v_forecast_state, rho_w_forecast_state,
687 cons_forecast_state);
690 const Array4<const Real>& surface_state_arr = (*surface_state_at_lev).array(mfi);
692 xmom_src_arr, ymom_src_arr,
703 ((is_slow_step && !use_canopy_fast) || (!is_slow_step && use_canopy_fast))) {
705 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
707 const Real ux = u(i, j, k);
708 const Real uy =
fourth * ( v(i, j , k ) + v(i-1, j , k )
709 + v(i, j+1, k ) + v(i-1, j+1, k ) );
710 const Real uz =
fourth * (
w(i, j , k ) +
w(i-1, j , k )
711 +
w(i, j , k+1) +
w(i-1, j , k+1) );
712 const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
713 const Real f_drag =
myhalf * (f_drag_arr(i, j, k) + f_drag_arr(i-1, j, k));
714 xmom_src_arr(i, j, k) -= f_drag * ux * windspeed;
716 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
718 const Real ux =
fourth * ( u(i , j , k ) + u(i , j-1, k )
719 + u(i+1, j , k ) + u(i+1, j-1, k ) );
720 const Real uy = v(i, j, k);
721 const Real uz =
fourth * (
w(i , j , k ) +
w(i , j-1, k )
722 +
w(i , j , k+1) +
w(i , j-1, k+1) );
723 const amrex::Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
724 const Real f_drag =
myhalf * (f_drag_arr(i, j, k) + f_drag_arr(i, j-1, k));
725 ymom_src_arr(i, j, k) -= f_drag * uy * windspeed;
727 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
730 + u(i , j , k-1) + u(i+1, j , k-1) );
732 + v(i , j , k-1) + v(i , j+1, k-1) );
734 const amrex::Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
735 const Real f_drag =
myhalf * (f_drag_arr(i, j, k) + f_drag_arr(i, j, k-1));
736 zmom_src_arr(i, j, k) -= f_drag * uz * windspeed;
742 if (solverChoice.
terrain_type == TerrainType::ImmersedForcing &&
743 ((is_slow_step && !use_ImmersedForcing_fast) || (!is_slow_step && use_ImmersedForcing_fast))) {
745 const Real* dx_arr = geom.CellSize();
746 const Real dx_x = dx_arr[0];
747 const Real dx_y = dx_arr[1];
748 const Real dx_z = dx_arr[2];
751 const Real drag_coefficient = alpha_m / std::pow(dx_x*dx_y*dx_z,
one/
three);
764 ParallelFor(tbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
766 const Real ux = u(i, j, k);
767 const Real uy =
fourth * ( v(i, j , k ) + v(i-1, j , k )
768 + v(i, j+1, k ) + v(i-1, j+1, k ) );
769 const Real uz =
fourth * (
w(i, j , k ) +
w(i-1, j , k )
770 +
w(i, j , k+1) +
w(i-1, j , k+1) );
771 const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
772 const Real t_blank =
myhalf * (t_blank_arr(i, j, k) + t_blank_arr(i-1, j, k));
773 const Real t_blank_above =
myhalf * (t_blank_arr(i, j, k+1) + t_blank_arr(i-1, j, k+1));
774 const Real CdM = std::min(drag_coefficient / (windspeed + tiny),
Real(1000.0));
777 if ((t_blank > 0 && (t_blank_above ==
zero)) && l_use_most) {
779 const Real ux2r = u(i, j, k+1) ;
780 const Real uy2r =
fourth * ( v(i, j , k+1) + v(i-1, j , k+1)
781 + v(i, j+1, k+1) + v(i-1, j+1, k+1) ) ;
782 const Real h_windspeed2r = std::sqrt(ux2r * ux2r + uy2r * uy2r);
788 const Real theta_surf = theta_xface_below;
792 Real ustar = h_windspeed2r * kappa / (std::log(
Real(1.5) * dx_z /
z0) - psi_m);
793 Real tflux = (tflux_in !=
Real(1e-8)) ? tflux_in : -(theta_xface - theta_surf) * ustar * kappa / (std::log(
Real(1.5) * dx_z /
z0) - psi_h);
794 Real Olen = (Olen_in !=
Real(1e-8)) ? Olen_in : -ustar * ustar * ustar * theta_xface / (kappa * ggg * tflux + tiny);
800 ustar = h_windspeed2r * kappa / (std::log(
Real(1.5) * dx_z /
z0) - psi_m);
803 if (!(ustar >
zero && !std::isnan(ustar))) { ustar =
zero; }
804 if (!(ustar <
two && !std::isnan(ustar))) { ustar =
two; }
805 if (psi_m > std::log(
myhalf * dx_z /
z0)) { psi_m = std::log(
myhalf * dx_z /
z0); }
808 const Real uTarget = ustar / kappa * (std::log(
myhalf * dx_z /
z0) - psi_m);
809 Real uxTarget = uTarget * ux2r / (tiny + h_windspeed2r);
810 const Real bc_forcing_x = -(uxTarget - ux);
811 xmom_src_arr(i, j, k) -= (1-t_blank) * rho_xface * CdM * U_s * bc_forcing_x;
813 xmom_src_arr(i, j, k) -= t_blank * rho_xface * CdM * ux * windspeed;
816 ParallelFor(tby, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
818 const Real ux =
fourth * ( u(i , j , k ) + u(i , j-1, k )
819 + u(i+1, j , k ) + u(i+1, j-1, k ) );
820 const Real uy = v(i, j, k);
821 const Real uz =
fourth * (
w(i , j , k ) +
w(i , j-1, k )
822 +
w(i , j , k+1) +
w(i , j-1, k+1) );
823 const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
824 const Real t_blank =
myhalf * (t_blank_arr(i, j, k) + t_blank_arr(i, j-1, k));
825 const Real t_blank_above =
myhalf * (t_blank_arr(i, j, k+1) + t_blank_arr(i, j-1, k+1));
826 const Real CdM = std::min(drag_coefficient / (windspeed + tiny),
Real(1000.0));
829 if ((t_blank > 0 && (t_blank_above ==
zero)) && l_use_most) {
831 const Real ux2r =
fourth * ( u(i , j , k+1) + u(i , j-1, k+1)
832 + u(i+1, j , k+1) + u(i+1, j-1, k+1) );
833 const Real uy2r = v(i, j, k+1) ;
834 const Real h_windspeed2r = std::sqrt(ux2r * ux2r + uy2r * uy2r);
840 const Real theta_surf = theta_yface_below;
844 Real ustar = h_windspeed2r * kappa / (std::log(
Real(1.5) * dx_z /
z0) - psi_m);
845 Real tflux = (tflux_in !=
Real(1e-8)) ? tflux_in : -(theta_yface - theta_surf) * ustar * kappa / (std::log(
Real(1.5) * dx_z /
z0) - psi_h);
846 Real Olen = (Olen_in !=
Real(1e-8)) ? Olen_in : -ustar * ustar * ustar * theta_yface / (kappa * ggg * tflux + tiny);
852 ustar = h_windspeed2r * kappa / (std::log(
Real(1.5) * dx_z /
z0) - psi_m);
855 if (!(ustar >
zero && !std::isnan(ustar))) { ustar =
zero; }
856 if (!(ustar <
two && !std::isnan(ustar))) { ustar =
two; }
857 if (psi_m > std::log(
myhalf * dx_z /
z0)) { psi_m = std::log(
myhalf * dx_z /
z0); }
860 const Real uTarget = ustar / kappa * (std::log(
myhalf * dx_z /
z0) - psi_m);
861 Real uyTarget = uTarget * uy2r / (tiny + h_windspeed2r);
862 const Real bc_forcing_y = -(uyTarget - uy);
863 ymom_src_arr(i, j, k) -= (1 - t_blank) * rho_yface * CdM * U_s * bc_forcing_y;
865 ymom_src_arr(i, j, k) -= t_blank * rho_yface * CdM * uy * windspeed;
868 ParallelFor(tbz, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
870 const Real ux =
fourth * ( u(i , j , k ) + u(i+1, j , k )
871 + u(i , j , k-1) + u(i+1, j , k-1) );
872 const Real uy =
fourth * ( v(i , j , k ) + v(i , j+1, k )
873 + v(i , j , k-1) + v(i , j+1, k-1) );
874 const Real uz =
w(i, j, k);
875 const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
876 const Real t_blank =
myhalf * (t_blank_arr(i, j, k) + t_blank_arr(i, j, k-1));
877 const Real CdM = std::min(drag_coefficient / (windspeed + tiny),
Real(1000.0));
879 zmom_src_arr(i, j, k) -= t_blank * rho_zface * CdM * uz * windspeed;
886 if ((solverChoice.
buildings_type == BuildingsType::ImmersedForcing ) &&
887 ((is_slow_step && !use_ImmersedForcing_fast) || (!is_slow_step && use_ImmersedForcing_fast)))
890 const Real* dx_arr = geom.CellSize();
891 const Real dx_x = dx_arr[0];
892 const Real dx_y = dx_arr[1];
896 const Real min_t_blank =
Real(0.005);
898 ParallelFor(tbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
900 const Real ux = u(i, j, k);
901 const Real uy =
fourth * ( v(i, j , k ) + v(i-1, j , k )
902 + v(i, j+1, k ) + v(i-1, j+1, k ) );
903 const Real uz =
fourth * (
w(i, j , k ) +
w(i-1, j , k )
904 +
w(i, j , k+1) +
w(i-1, j , k+1) );
905 const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
907 Real t_blank =
myhalf * (t_blank_arr(i, j, k) + t_blank_arr(i-1, j, k));
908 if (t_blank < min_t_blank) { t_blank =
zero; }
909 const Real dx_z = (z_cc_arr) ? (z_cc_arr(i,j,k) - z_cc_arr(i,j,k-1)) : dx_arr[2];
910 const Real drag_coefficient = alpha_m / std::pow(dx_x*dx_y*dx_z,
one/
three);
911 const Real CdM = std::min(drag_coefficient / (windspeed + tiny),
Real(1000.0));
913 xmom_src_arr(i, j, k) -= t_blank * rho_xface * CdM * ux * windspeed;
915 ParallelFor(tby, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
917 const Real ux =
fourth * ( u(i , j , k ) + u(i , j-1, k )
918 + u(i+1, j , k ) + u(i+1, j-1, k ) );
919 const Real uy = v(i, j, k);
920 const Real uz =
fourth * (
w(i , j , k ) +
w(i , j-1, k )
921 +
w(i , j , k+1) +
w(i , j-1, k+1) );
922 const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
924 Real t_blank =
myhalf * (t_blank_arr(i, j, k) + t_blank_arr(i, j-1, k));
925 if (t_blank < min_t_blank) { t_blank =
zero; }
926 const Real dx_z = (z_cc_arr) ? (z_cc_arr(i,j,k) - z_cc_arr(i,j,k-1)) : dx_arr[2];
927 const Real drag_coefficient = alpha_m / std::pow(dx_x*dx_y*dx_z,
one/
three);
928 const Real CdM = std::min(drag_coefficient / (windspeed + tiny),
Real(1000.0));
930 ymom_src_arr(i, j, k) -= t_blank * rho_yface * CdM * uy * windspeed;
932 ParallelFor(tbz, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
934 const Real ux =
fourth * ( u(i , j , k ) + u(i+1, j , k )
935 + u(i , j , k-1) + u(i+1, j , k-1) );
936 const Real uy =
fourth * ( v(i , j , k ) + v(i , j+1, k )
937 + v(i , j , k-1) + v(i , j+1, k-1) );
938 const Real uz =
w(i, j, k);
939 const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
941 Real t_blank =
myhalf * (t_blank_arr(i, j, k) + t_blank_arr(i, j, k-1));
942 if (t_blank < min_t_blank) { t_blank =
zero; }
943 const Real dx_z = (z_nd_arr) ? (z_nd_arr(i,j,k) - z_nd_arr(i,j,k-1)) : dx_arr[2];
944 const Real drag_coefficient = alpha_m / std::pow(dx_x*dx_y*dx_z,
one/
three);
945 const Real CdM = std::min(drag_coefficient / (windspeed + tiny),
Real(1000.0));
947 zmom_src_arr(i, j, k) -= t_blank * rho_zface * CdM * uz * windspeed;
954 if (is_slow_step && (enforce_massflux_x || enforce_massflux_y)) {
958 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
959 xmom_src_arr(i, j, k) += tau_inv * (rhoUA_target - rhoUA);
961 [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
962 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)
Definition: ERF_ApplySpongeZoneBCs.cpp:169
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:8
void ApplySurfaceTreatment_BulkCoeff_Mom(const Box &tbx, const Box &tby, 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 Array4< const Real > &cons_state, const Array4< const Real > &z_phys_nd, const Array4< const Real > &surface_state_arr)
Definition: ERF_ApplySurfaceTreatment_BulkCoeff.cpp:8
constexpr amrex::Real three
Definition: ERF_Constants.H:11
constexpr amrex::Real KAPPA
Definition: ERF_Constants.H:63
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real fourth
Definition: ERF_Constants.H:14
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
constexpr amrex::Real PI
Definition: ERF_Constants.H:42
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:64
@ ubar
Definition: ERF_DataStruct.H:98
@ wbar
Definition: ERF_DataStruct.H:98
@ vbar
Definition: ERF_DataStruct.H:98
DirectionSelector< 2 > ZDir
Definition: ERF_DirectionSelector.H:38
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:8
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
ParallelFor(grown_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);})
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:19
AMREX_FORCE_INLINE IntVect offset(const int face_dir, const int normal)
Definition: ERF_ReadBndryPlanes.cpp:28
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_PlaneAverage.H:14
eb_aux_ const * get_w_const_factory() const noexcept
Definition: ERF_EB.H:52
eb_aux_ const * get_v_const_factory() const noexcept
Definition: ERF_EB.H:51
eb_aux_ const * get_u_const_factory() const noexcept
Definition: ERF_EB.H:50
@ r0_comp
Definition: ERF_IndexDefines.H:73
@ ymom
Definition: ERF_IndexDefines.H:195
@ cons
Definition: ERF_IndexDefines.H:193
@ zmom
Definition: ERF_IndexDefines.H:196
@ xmom
Definition: ERF_IndexDefines.H:194
@ nr
Definition: ERF_Morrison.H:46
@ xvel
Definition: ERF_IndexDefines.H:176
@ cons
Definition: ERF_IndexDefines.H:175
@ yvel
Definition: ERF_IndexDefines.H:177
@ ww
Definition: ERF_AdvanceWSM6.cpp:105
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
real(kind=kind_phys), parameter, private r0
Definition: ERF_module_mp_wsm6.F90:21
bool rayleigh_damp_V
Definition: ERF_DampingStruct.H:85
amrex::Real rayleigh_dampcoef
Definition: ERF_DampingStruct.H:88
bool rayleigh_damp_W
Definition: ERF_DampingStruct.H:86
RayleighDampingType rayleigh_damping_type
Definition: ERF_DampingStruct.H:101
bool rayleigh_damp_U
Definition: ERF_DampingStruct.H:84
bool do_mom_advection
Definition: ERF_DataStruct.H:1346
amrex::Real coriolis_factor
Definition: ERF_DataStruct.H:1337
static MeshType mesh_type
Definition: ERF_DataStruct.H:1239
amrex::Real if_surf_temp_flux
Definition: ERF_DataStruct.H:1314
bool if_use_most
Definition: ERF_DataStruct.H:1318
DampingChoice dampingChoice
Definition: ERF_DataStruct.H:1249
amrex::Real const_massflux_v
Definition: ERF_DataStruct.H:1463
amrex::Real if_z0
Definition: ERF_DataStruct.H:1313
amrex::Real cosphi
Definition: ERF_DataStruct.H:1338
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_geo_forcing
Definition: ERF_DataStruct.H:1432
bool hindcast_lateral_forcing
Definition: ERF_DataStruct.H:1472
int massflux_klo
Definition: ERF_DataStruct.H:1467
bool custom_w_subsidence
Definition: ERF_DataStruct.H:1344
bool nudging_from_input_sounding
Definition: ERF_DataStruct.H:1354
bool immersed_forcing_substep
Definition: ERF_DataStruct.H:1306
amrex::Real sinphi
Definition: ERF_DataStruct.H:1339
bool have_geo_wind_profile
Definition: ERF_DataStruct.H:1434
amrex::Real const_massflux_u
Definition: ERF_DataStruct.H:1462
amrex::Real if_Olen_in
Definition: ERF_DataStruct.H:1317
bool use_coriolis
Definition: ERF_DataStruct.H:1300
amrex::Real num_diff_coeff
Definition: ERF_DataStruct.H:1421
bool variable_coriolis
Definition: ERF_DataStruct.H:1436
amrex::Real if_Cd_momentum
Definition: ERF_DataStruct.H:1310
bool custom_forcing_prim_vars
Definition: ERF_DataStruct.H:1348
static BuildingsType buildings_type
Definition: ERF_DataStruct.H:1233
static TerrainType terrain_type
Definition: ERF_DataStruct.H:1230
SpongeChoice spongeChoice
Definition: ERF_DataStruct.H:1250
static InitType init_type
Definition: ERF_DataStruct.H:1224
bool hindcast_surface_bcs
Definition: ERF_DataStruct.H:1473
bool do_forest_drag
Definition: ERF_DataStruct.H:1459
amrex::Real const_massflux_tau
Definition: ERF_DataStruct.H:1464
int massflux_khi
Definition: ERF_DataStruct.H:1468
bool forest_substep
Definition: ERF_DataStruct.H:1307
int ave_plane
Definition: ERF_DataStruct.H:1438
static SpongeType sponge_type
Definition: ERF_SpongeStruct.H:90
Definition: ERF_MOSTStress.H:40
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real calc_psi_m(amrex::Real zeta) const
Definition: ERF_MOSTStress.H:90
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real calc_psi_h(amrex::Real zeta) const
Definition: ERF_MOSTStress.H:104