ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_AddTKESources.H
Go to the documentation of this file.
1  // Using Deardorff (see Sullivan et al 1994)
2  // or k-eqn RANS (see Axell & Liungman 2001)
3  //
4  // Note: At this point, the thermal diffusivity ("Khv" field in ERF) and the
5  // subgrid dissipation ("diss" here) have been updated by the closure
6  // at the beginning of each timestep.
7  // The strain rate magnitude is updated at the beginning of the first
8  // RK stage only, therefore the shear production term also does not
9  // change between RK stages.
10  // hfx_z (Hfx3) is z-nodal, (0,0,1): it lives at the w-faces, not at the
11  // cell centre, so a single hfx_z(i,j,k) is the flux at the LOWER face of
12  // the cell and using it as the cell-centred value is not formally correct.
13  // hfx_z holds the face fluxes of the theta diffusion of this stage
14  // (the full flux, independent of the implicit/explicit split); at the
15  // bottom face of the domain that is the surface-layer flux when a
16  // surface layer is used. The buoyancy production therefore averages the
17  // two faces of every cell, the first cell included, for the cell-centred
18  // vertical heat flux. The first cell is not special-cased to the surface
19  // flux alone: that would again place a w-face value at the cell centre
20  // (a MOST-profile gradient evaluated at the first cell centre would be
21  // the consistent alternative).
22  // On a terrain-fitted mesh hfx_z holds the flux along zeta only: the slope
23  // corrections and the Jacobian are applied where the fluxes enter the RHS, so
24  // over sloping terrain this source omits those terms (as does the hfx3 output).
25  // REQUIRED WRITER: the RhoTheta call of DiffusionSrcForState_{N,S,T}
26  // in erf_slow_rhs_pre, on the same RK stage, which writes every z-face
27  // of each valid box (zbx = surroundingNodes(bx,2), top face included).
28  // Running the RhoKE source without that same-stage theta pass would
29  // read stale faces.
30  if (l_use_keqn && (start_comp <= RhoKE_comp) && (end_comp >= RhoKE_comp)) {
31  int qty_index = RhoKE_comp;
32  // The source reads hfx_z at k+1: the z-faces of bx must be in hfx_z
33  AMREX_ASSERT(hfx_z.contains(bx.smallEnd(0), bx.smallEnd(1), bx.smallEnd(2)) &&
34  hfx_z.contains(bx.bigEnd(0), bx.bigEnd(1), bx.bigEnd(2)+1));
35  ParallelFor(bx,[=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
36  {
37  // Add Buoyancy Source
38  // where the SGS buoyancy flux tau_{theta,i} = -KH * dtheta/dx_i,
39  // such that for dtheta/dz < 0, there is a positive (upward) heat
40  // flux; the TKE buoyancy production is then
41  // B = g/theta_0 * tau_{theta,w}
42  // for a dry atmosphere.
43  // TODO: To account for moisture, the Brunt-Vaisala frequency,
44  // N^2 = g[1/theta * dtheta/dz + ...]
45  // **should** be a function of the water vapor and total water
46  // mixing ratios, depending on whether conditions are saturated or
47  // not (see the WRF model description, Skamarock et al 2019).
48  // NOTE: reads hfx_z at k+1, one face above bx; Hfx3 is z-nodal and
49  // the theta diffusion writes every face of its valid box, top included.
50  const amrex::Real hfx_cc = amrex::Real(0.5) * ( hfx_z(i,j,k) + hfx_z(i,j,k+1) );
51  amrex::Real buoyancy_src = l_abs_g * l_inv_theta0 * hfx_cc;
52  if (!use_ref_theta) {
53  // l_inv_theta0 == 1, divide by actual theta
54  buoyancy_src /= cell_prim(i,j,k,PrimTheta_comp);
55  }
56  cell_rhs(i,j,k,qty_index) += buoyancy_src;
57 
58  // TKE shear production
59  // P = -tau_ij * S_ij = 2 * mu_turb * S_ij * S_ij
60  // Note: This assumes that the horizontal and vertical diffusivities
61  // of momentum are equal
62  cell_rhs(i,j,k,qty_index) += two*mu_turb(i,j,k,EddyDiff::Mom_v) * SmnSmn_a(i,j,k);
63 
64  // TKE dissipation (explicit); with erf.implicit_tke_dissipation the
65  // sink is folded into the update in erf_slow_rhs_post instead
66  if (!l_implicit_diss) {
67  cell_rhs(i,j,k,qty_index) -= diss(i,j,k);
68  }
69  });
70  }
#define PrimTheta_comp
Definition: ERF_IndexDefines.H:58
#define RhoKE_comp
Definition: ERF_IndexDefines.H:41
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
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ Mom_v
Definition: ERF_IndexDefines.H:249