ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_PBLModels.H
Go to the documentation of this file.
1 #ifndef ERF_PBLMODELS_H_
2 #define ERF_PBLMODELS_H_
3 
4 #include <AMReX_Periodicity.H>
5 #include "ERF_Constants.H"
6 #include "ERF_DataStruct.H"
7 #include "ERF_MOSTUtils.H"
8 
9 /**
10  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
11  * Mellor-Yamada-Janjić (MYJ) boundary layer scheme.
12  * Reference: Janjić, Z. I., 1994: The Step-Mountain Eta Coordinate Model:
13  * Further Developments of the Convection, Viscous Sublayer, and Turbulence
14  * Closure Schemes. Monthly Weather Review, 122, 927–945.
15  * https://doi.org/10.1175/1520-0493(1994)122<0927:TSMECM>2.0.CO;2
16  *
17  * @param[in] xvel Velocity in x-dir
18  * @param[in] yvel Velocity in y-dir
19  * @param[in] cons_in Cell center conserved quantities
20  * @param[out] eddyViscosity Holds turbulent viscosity
21  * @param[in] geom Problem geometry
22  * @param[in] turbChoice Container with turbulence parameters
23  * @param[in] SurfLayer Pointer to Monin-Obukhov class if instantiated
24  * @param[in] use_moisture If we have microphysics enabled
25  * @param[in] level Current level
26  * @param[in] bc_ptr Pointer to array with boundary condition info
27  * @param[in] vert_only Only compute vertical eddy diffusivities
28  * @param[in] z_phys_nd Physical location of grid nodes, if terrain (or grid stretching) is enabled
29  * @param[in] z_phys_cc Physical location of cell centers
30  */
31 void
33  const amrex::MultiFab& xvel,
34  const amrex::MultiFab& yvel,
35  amrex::MultiFab& cons_in,
36  amrex::MultiFab& eddyViscosity,
37  const amrex::Geometry& geom,
38  const TurbChoice& turbChoice,
39  std::unique_ptr<SurfaceLayer>& SurfLayer,
40  bool use_terrain_fitted_coords,
41  bool use_moisture,
42  int level,
43  const amrex::BCRec* bc_ptr,
44  bool /*vert_only*/,
45  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
46  const std::unique_ptr<amrex::MultiFab>& z_phys_cc,
47  const MoistureComponentIndices& moisture_indices);
48 
49 /**
50  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
51  * Mellor-Yamada-Nakanishi-Niino Level amrex::Real(2.5) PBL scheme
52  *
53  * @param[in] xvel Velocity in x-dir
54  * @param[in] yvel Velocity in y-dir
55  * @param[in] cons_in Cell center conserved quantities
56  * @param[out] eddyViscosity Holds turbulent viscosity
57  * @param[in] geom Problem geometry
58  * @param[in] turbChoice Container with turbulence parameters
59  * @param[in] SurfLayer Pointer to Monin-Obukhov class if instantiated
60  * @param[in] use_moisture If we have microphysics enabled
61  * @param[in] level Current level
62  * @param[in] bc_ptr Pointer to array with boundary condition info
63  * @param[in] vert_only Only compute vertical eddy diffusivities
64  * @param[in] z_phys_nd Physical location of grid nodes, if terrain (or grid stretching) is enabled
65  * @param[in] z_phys_cc Physical location of cell centers
66  */
67 void
68 ComputeDiffusivityMYNN25 (const amrex::MultiFab& xvel,
69  const amrex::MultiFab& yvel,
70  const amrex::MultiFab& cons_in,
71  amrex::MultiFab& eddyViscosity,
72  const amrex::Geometry& geom,
73  const TurbChoice& turbChoice,
74  std::unique_ptr<SurfaceLayer>& SurfLayer,
75  bool use_terrain_fitted_coords,
76  bool use_moisture,
77  int level,
78  const amrex::BCRec* bc_ptr,
79  bool /*vert_only*/,
80  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
81  const std::unique_ptr<amrex::MultiFab>& z_phys_cc,
82  const MoistureComponentIndices& moisture_indices);
83 
84 /**
85  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
86  * Mellor-Yamada-Nakanishi-Niino Level amrex::Real(2.5) PBL scheme
87  *
88  * @param[in] xvel Velocity in x-dir
89  * @param[in] yvel Velocity in y-dir
90  * @param[in] cons_in Cell center conserved quantities
91  * @param[out] eddyViscosity Holds turbulent viscosity
92  * @param[in] geom Problem geometry
93  * @param[in] turbChoice Container with turbulence parameters
94  * @param[in] SurfLayer Pointer to Monin-Obukhov class if instantiated
95  * @param[in] use_moisture If we have microphysics enabled
96  * @param[in] level Current level
97  * @param[in] bc_ptr Pointer to array with boundary condition info
98  * @param[in] vert_only Only compute vertical eddy diffusivities
99  * @param[in] z_phys_nd Physical location of grid nodes, if terrain (or grid stretching) is enabled
100  * @param[in] z_phys_cc Physical location of cell centers
101  */
102 void
103 ComputeDiffusivityMYNNEDMF (const amrex::MultiFab& xvel,
104  const amrex::MultiFab& yvel,
105  const amrex::MultiFab& cons_in,
106  amrex::MultiFab& eddyViscosity,
107  const amrex::Geometry& geom,
108  const TurbChoice& turbChoice,
109  std::unique_ptr<SurfaceLayer>& SurfLayer,
110  bool use_terrain_fitted_coords,
111  bool use_moisture,
112  int level,
113  const amrex::BCRec* bc_ptr,
114  bool /*vert_only*/,
115  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
116  const std::unique_ptr<amrex::MultiFab>& z_phys_cc,
117  const MoistureComponentIndices& moisture_indices);
118 
119 /**
120  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
121  * Yonsei University PBL scheme
122  *
123  * @param[in] xvel Velocity in x-dir
124  * @param[in] yvel Velocity in y-dir
125  * @param[in] cons_in Cell center conserved quantities
126  * @param[out] eddyViscosity Holds turbulent viscosity
127  * @param[in] geom Problem geometry
128  * @param[in] turbChoice Container with turbulence parameters
129  * @param[in] SurfLayer Pointer to Monin-Obukhov class if instantiated
130  * @param[in] use_moisture If we have microphysics enabled
131  * @param[in] level Current level
132  * @param[in] bc_ptr Pointer to array with boundary condition info
133  * @param[in] vert_only Only compute vertical eddy diffusivities
134  * @param[in] z_phys_nd Physical location of grid nodes, if terrain (or grid stretching) is enabled
135  * @param[in] z_phys_cc Physical location of cell centers
136  */
137 void
138 ComputeDiffusivityYSU (const amrex::MultiFab& xvel,
139  const amrex::MultiFab& yvel,
140  const amrex::MultiFab& cons_in,
141  amrex::MultiFab& eddyViscosity,
142  const amrex::Geometry& geom,
143  const TurbChoice& turbChoice,
144  std::unique_ptr<SurfaceLayer>& SurfLayer,
145  bool use_terrain_fitted_coords,
146  bool use_moisture,
147  int level,
148  const amrex::BCRec* bc_ptr,
149  bool /*vert_only*/,
150  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
151  const std::unique_ptr<amrex::MultiFab>& z_phys_cc,
152  const MoistureComponentIndices& moisture_indices);
153 /**
154  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
155  * Medium Range Forecast (MRF) boundary layer scheme based on Hong and Pan (1996).
156  * Reference: Hong, S. Y., and H.-L. Pan, 1996: Nonlocal Boundary Layer Vertical
157  * Diffusion in a Medium-Range Forecast Model. Monthly Weather Review, 124,
158  * 2322-2339. https://doi.org/10.1175/1520-0493(1996)124<2322:NBLVDI>2.0.CO;2
159  *
160  * @param[in] xvel Velocity in x-dir
161  * @param[in] yvel Velocity in y-dir
162  * @param[in] cons_in Cell center conserved quantities
163  * @param[out] eddyViscosity Holds turbulent viscosity
164  * @param[in] geom Problem geometry
165  * @param[in] turbChoice Container with turbulence parameters
166  * @param[in] SurfLayer Pointer to Monin-Obukhov class if instantiated
167  * @param[in] use_moisture If we have microphysics enabled
168  * @param[in] level Current level
169  * @param[in] bc_ptr Pointer to array with boundary condition info
170  * @param[in] vert_only Only compute vertical eddy diffusivities
171  * @param[in] z_phys_nd Physical location of grid nodes, if terrain (or grid stretching) is enabled
172  * @param[in] z_phys_cc Physical location of cell centers
173  */
174 void
175 ComputeDiffusivityMRF (const amrex::MultiFab& xvel,
176  const amrex::MultiFab& yvel,
177  const amrex::MultiFab& cons_in,
178  amrex::MultiFab& eddyViscosity,
179  const amrex::Geometry& geom,
180  const TurbChoice& turbChoice,
181  std::unique_ptr<SurfaceLayer>& SurfLayer,
182  bool use_terrain_fitted_coords,
183  bool use_moisture,
184  int level,
185  const amrex::BCRec* bc_ptr,
186  bool /*vert_only*/,
187  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
188  const std::unique_ptr<amrex::MultiFab>& z_phys_cc,
189  const MoistureComponentIndices& moisture_indices,
190  const amrex::MultiFab* terrain_blank = nullptr);
191 
192 /**
193  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
194  * WRF Yonsei University (YSU) PBL scheme.
195  *
196  * Based on:
197  * Hong, Noh &amp; Dudhia (2006), MWR, https://doi.org/10.1175/MWR3250.1
198  * Hong (2010), QJRMS, https://doi.org/10.1002/qj.665
199  *
200  * Features: three-pass bulk-Richardson PBLH diagnosis, nonlocal
201  * countergradient fluxes, explicit entrainment at PBL top, and
202  * grid-adaptive Richardson-number mixing in free atmosphere.
203  *
204  * @param[in] xvel x-direction velocity
205  * @param[in] yvel y-direction velocity
206  * @param[in] cons_in cell-center conserved quantities
207  * @param[out] eddyViscosity turbulent eddy viscosity
208  * @param[in] geom problem geometry
209  * @param[in] turbChoice turbulence parameter container
210  * @param[in] SurfLayer Monin-Obukhov surface layer object
211  * @param[in] use_terrain_fitted_coords flag for terrain coordinates
212  * @param[in] use_moisture flag for moisture active
213  * @param[in] level AMR level
214  * @param[in] bc_ptr boundary condition array
215  * @param[in] vert_only compute vertical diffusivity only
216  * @param[in] z_phys_nd physical node heights (terrain)
217  * @param[in] z_phys_cc physical cell-center heights
218  * @param[in] moisture_indices component index mapping for moisture variables
219  * @param[in] qheating_rates radiation heating rates (SW, LW components); optional
220  */
221 void
222 ComputeDiffusivityYSUNew (const amrex::MultiFab& xvel,
223  const amrex::MultiFab& yvel,
224  const amrex::MultiFab& cons_in,
225  amrex::MultiFab& eddyViscosity,
226  const amrex::Geometry& geom,
227  const TurbChoice& turbChoice,
228  std::unique_ptr<SurfaceLayer>& SurfLayer,
229  bool use_terrain_fitted_coords,
230  bool use_moisture,
231  int level,
232  const amrex::BCRec* bc_ptr,
233  bool /*vert_only*/,
234  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
235  const std::unique_ptr<amrex::MultiFab>& z_phys_cc,
236  const MoistureComponentIndices& moisture_indices,
237  const amrex::MultiFab* qheating_rates = nullptr,
238  const amrex::MultiFab* terrain_blank = nullptr);
239 
240 /**
241  * Function for computing vertical derivatives for use in PBL model
242  *
243  * @param[in] u velocity in x-dir
244  * @param[in] v velocity in y-dir
245  * @param[in] cell_data conserved cell center vars
246  */
248 {
249  // Each value is the inverse physical distance between the two samples
250  // used by its corresponding derivative stencil.
254 };
255 
256 /**
257  * Compute vertical derivatives of potential temperature and velocity for PBL models.
258  *
259  * @param i x-index
260  * @param j y-index
261  * @param k z-index
262  * @param[in] uvel x-velocity
263  * @param[in] vvel y-velocity
264  * @param[in] cell_data conserved cell-center variables
265  * @param[in] izmin lower z-index limit
266  * @param[in] izmax upper z-index limit
267  * @param[in] dz_inv inverse physical distance spacings
268  * @param[in] c_ext_dir_on_zlo Dirichlet condition on z-low face for cell data
269  * @param[in] c_ext_dir_on_zhi Dirichlet condition on z-high face for cell data
270  * @param[in] u_ext_dir_on_zlo Dirichlet condition on z-low face for u-velocity
271  * @param[in] u_ext_dir_on_zhi Dirichlet condition on z-high face for u-velocity
272  * @param[in] v_ext_dir_on_zlo Dirichlet condition on z-low face for v-velocity
273  * @param[in] v_ext_dir_on_zhi Dirichlet condition on z-high face for v-velocity
274  * @param[out] dthetadz computed vertical derivative of potential temperature
275  * @param[out] dudz computed vertical derivative of x-velocity
276  * @param[out] dvdz computed vertical derivative of y-velocity
277  * @param[in] moisture_indices moisture variable component indices
278  */
279 /**
280  * Thermodynamic variable whose vertical gradient the PBL schemes use for
281  * buoyancy, selected by erf.thermal_stratification.
282  *
283  * @param[in] strat stratification variable to return
284  */
285 AMREX_GPU_DEVICE
286 AMREX_FORCE_INLINE
288 GetPBLStratVar (int i, int j, int k,
289  const StratType strat,
290  const amrex::Array4<const amrex::Real>& cell_data,
291  const MoistureComponentIndices& moisture_indices)
292 {
293  if (strat == StratType::theta) {
294  return cell_data(i,j,k,RhoTheta_comp) / cell_data(i,j,k,Rho_comp);
295  } else if (strat == StratType::thetal) {
296  return GetThetal(i,j,k,cell_data,moisture_indices);
297  }
298  return GetThetav(i,j,k,cell_data,moisture_indices);
299 }
300 
301 AMREX_GPU_DEVICE
302 AMREX_FORCE_INLINE
303 void
304 ComputeVerticalDerivativesPBL (int i, int j, int k,
305  const amrex::Array4<const amrex::Real>& uvel,
306  const amrex::Array4<const amrex::Real>& vvel,
307  const amrex::Array4<const amrex::Real>& cell_data,
308  const int izmin,
309  const int izmax,
310  const PBLDerivativeDzInv& dz_inv,
311  const bool c_ext_dir_on_zlo,
312  const bool c_ext_dir_on_zhi,
313  const bool u_ext_dir_on_zlo,
314  const bool u_ext_dir_on_zhi,
315  const bool v_ext_dir_on_zlo,
316  const bool v_ext_dir_on_zhi,
317  amrex::Real& dthetadz,
318  amrex::Real& dudz,
319  amrex::Real& dvdz,
320  const MoistureComponentIndices& moisture_indices,
321  const StratType strat = StratType::thetav)
322 {
323  // ext_dir ghost values hold the value at the physical boundary, which is
324  // half a ghost-center spacing from the adjacent cell center. Use a
325  // two-point, first-order boundary-to-center difference with inverse
326  // distance 2/dz.
327  if ( k==izmax && c_ext_dir_on_zhi ) {
328  dthetadz = ( GetPBLStratVar(i,j,k+1,strat,cell_data,moisture_indices)
329  -GetPBLStratVar(i,j,k ,strat,cell_data,moisture_indices) )*dz_inv.dirichlet_hi;
330  } else if ( k==izmin && c_ext_dir_on_zlo ) {
331  dthetadz = ( GetPBLStratVar(i,j,k ,strat,cell_data,moisture_indices)
332  -GetPBLStratVar(i,j,k-1,strat,cell_data,moisture_indices) )*dz_inv.dirichlet_lo;
333  } else {
334  dthetadz = ( GetPBLStratVar(i,j,k+1,strat,cell_data,moisture_indices)
335  -GetPBLStratVar(i,j,k-1,strat,cell_data,moisture_indices) )*dz_inv.interior;
336  }
337 
338  if ( k==izmax && u_ext_dir_on_zhi ) {
339  dudz = myhalf*( uvel(i ,j,k+1) - uvel(i ,j,k)
340  +uvel(i+1,j,k+1) - uvel(i+1,j,k) )*dz_inv.dirichlet_hi;
341  } else if ( k==izmin && u_ext_dir_on_zlo ) {
342  dudz = myhalf*( uvel(i ,j,k) - uvel(i ,j,k-1)
343  +uvel(i+1,j,k) - uvel(i+1,j,k-1) )*dz_inv.dirichlet_lo;
344  } else {
345  dudz = myhalf*( uvel(i ,j,k+1) - uvel(i ,j,k-1)
346  +uvel(i+1,j,k+1) - uvel(i+1,j,k-1) )*dz_inv.interior;
347  }
348 
349  if ( k==izmax && v_ext_dir_on_zhi ) {
350  dvdz = myhalf*( vvel(i,j ,k+1) - vvel(i,j ,k)
351  +vvel(i,j+1,k+1) - vvel(i,j+1,k) )*dz_inv.dirichlet_hi;
352  } else if ( k==izmin && v_ext_dir_on_zlo ) {
353  dvdz = myhalf*( vvel(i,j ,k) - vvel(i,j ,k-1)
354  +vvel(i,j+1,k) - vvel(i,j+1,k-1) )*dz_inv.dirichlet_lo;
355  } else {
356  dvdz = myhalf*( vvel(i,j ,k+1) - vvel(i,j ,k-1)
357  +vvel(i,j+1,k+1) - vvel(i,j+1,k-1) )*dz_inv.interior;
358  }
359 }
360 
361 /**
362  * Monin-Obukhov quantities needed to rebuild the vertical gradients in the first
363  * cell above a surface-layer boundary.
364  */
366 {
367  amrex::Real u_star {zero}; ///< friction velocity
368  amrex::Real tstar_v {zero}; ///< virtual temperature scale
369  amrex::Real zval {zero}; ///< height of the cell center above the surface
370  amrex::Real zeta {zero}; ///< stability coordinate z/L
371 };
372 
373 /**
374  * Virtual temperature scale, thetav_* = theta_*(1 + epsv qv) + epsv theta q_*.
375  * The surface virtual heat flux is <w'thetav'> = -u_* thetav_*.
376  *
377  * @param[in] t_star temperature scale
378  * @param[in] q_star moisture scale
379  * @param[in] theta potential temperature
380  * @param[in] qv water vapor mixing ratio
381  * @param[in] use_moisture whether the moisture term is active
382  */
383 AMREX_GPU_DEVICE
384 AMREX_FORCE_INLINE
387  amrex::Real q_star,
389  amrex::Real qv,
390  bool use_moisture)
391 {
392  amrex::Real tstar_v = t_star * (one + epsv*qv);
393  if (use_moisture) { tstar_v += epsv * theta * q_star; }
394  return tstar_v;
395 }
396 
397 /**
398  * Overwrite the vertical gradients in the first cell above the surface with the
399  * MOST profile gradients,
400  * |dU/dz| = u_* phi_m(zeta) / (kappa z)
401  * dthetav/dz = thetav_* phi_h(zeta) / (kappa z)
402  *
403  * With zlo.type = surface_layer the state carries foextrap and the velocities
404  * hoextrap at the lower boundary, so the centered stencil in
405  * ComputeVerticalDerivativesPBL reads ghost values that hold no surface
406  * information there: the potential-temperature gradient comes out half the
407  * one-sided value and the velocity gradient has no dependence on the friction
408  * velocity at all (ERF #4037). The MOST profile used here is the one the surface
409  * stress and heat flux were themselves derived from.
410  *
411  * Every PBL scheme that consumes these gradients uses only the shear magnitude
412  * dudz^2 + dvdz^2, so that magnitude is carried in dudz and dvdz is left at zero
413  * rather than being split by wind direction.
414  *
415  * @param[in] sl Monin-Obukhov inputs for this column
416  * @param[out] dthetadz vertical derivative of virtual potential temperature
417  * @param[out] dudz vertical derivative of x-velocity (carries the shear magnitude)
418  * @param[out] dvdz vertical derivative of y-velocity (set to zero)
419  */
420 AMREX_GPU_DEVICE
421 AMREX_FORCE_INLINE
422 void
424  amrex::Real& dthetadz,
425  amrex::Real& dudz,
426  amrex::Real& dvdz)
427 {
428  const similarity_funs sfuns{};
429  const amrex::Real inv_kappa_z = one / (KAPPA * sl.zval);
430  dudz = sl.u_star * sfuns.calc_phi_m(sl.zeta) * inv_kappa_z;
431  dvdz = zero;
432  dthetadz = sl.tstar_v * sfuns.calc_phi_h(sl.zeta) * inv_kappa_z;
433 }
434 
435 /**
436  * Function for computing the QKE source terms (NN09, Eqn. 5).
437  *
438  * @param[in] u velocity in x-dir
439  * @param[in] v velocity in y-dir
440  * @param[in] cell_data conserved cell center vars
441  * @param[in] cell_prim primitive cell center vars
442  * @param[in] K_turb turbulent viscosity
443  * @param[in] domain box of the whole domain
444  * @param[in] dz_inv inverse spacings for interior and Dirichlet-boundary differences
445  * @param[in] pbl_mynn_B1_l a parameter
446  * @param[in] theta_mean average theta
447  * @param[in] moisture_indices moisture variable component indices
448  * @param[in] tau13 rho<u'w'> on z-faces; the surface-layer stress at the zlo face
449  * @param[in] tau23 rho<v'w'> on z-faces; the surface-layer stress at the zlo face
450  * @param[in] hfx_z rho<w'theta'> on z-faces; the surface-layer heat flux at the zlo face
451  * @param[in] qfx1_z rho<w'qv'> on z-faces; the surface-layer moisture flux at the zlo face
452  * @param[in] surface_layer_on_zlo a SurfaceLayer supplies the fluxes through the zlo face
453  */
454 AMREX_GPU_DEVICE
455 AMREX_FORCE_INLINE
457 ComputeQKESourceTerms (int i, int j, int k,
458  const amrex::Array4<const amrex::Real>& uvel,
459  const amrex::Array4<const amrex::Real>& vvel,
460  const amrex::Array4<const amrex::Real>& cell_data,
461  const amrex::Array4<const amrex::Real>& cell_prim,
462  const amrex::Array4<const amrex::Real>& K_turb,
463  const amrex::Box& domain,
464  const PBLDerivativeDzInv dz_inv,
465  amrex::Real pbl_mynn_B1_l,
466  const amrex::Real theta_mean,
467  const MoistureComponentIndices& moisture_indices,
468  bool c_ext_dir_on_zlo,
469  bool c_ext_dir_on_zhi,
470  bool u_ext_dir_on_zlo,
471  bool u_ext_dir_on_zhi,
472  bool v_ext_dir_on_zlo,
473  bool v_ext_dir_on_zhi,
474  const amrex::Array4<const amrex::Real>& tau13,
475  const amrex::Array4<const amrex::Real>& tau23,
476  const amrex::Array4<const amrex::Real>& hfx_z,
477  const amrex::Array4<const amrex::Real>& qfx1_z,
478  bool surface_layer_on_zlo)
479 {
480  amrex::Real source_term = zero;
481 
482  int izmin = domain.smallEnd(2);
483  int izmax = domain.bigEnd(2);
484 
485  const amrex::Real rho = cell_data(i,j,k,Rho_comp);
486 
487  // Notes:
488  // - We transport TKE = myhalf*QKE rather than QKE, so the RHS terms do not
489  // have a factor of two.
490  // - Transport terms due to turbulence and pressure are included when
491  // DiffusionSrcForState_* is called from ERF_slow_rhs_post.
492  // - Eddy diffusivities are updated at the beginning of each time step only.
493 
494  const bool use_surface_fluxes = ( surface_layer_on_zlo && (k == izmin) &&
495  tau13 && tau23 && hfx_z );
496 
497  if (use_surface_fluxes)
498  {
499  // The first cell center lies inside the unresolved surface layer. With
500  // zlo.type = surface_layer the state carries foextrap and the velocities
501  // hoextrap at the lower boundary, so the stencil used below reads ghost
502  // values that hold no surface information: the resolved gradients there
503  // are not a discretization of anything (ERF #4037). Build the production
504  // terms from the fluxes the model actually carries instead:
505  //
506  // tau13, tau23 = rho<u'w'>, rho<v'w'> (z-faces, staggered in x,y)
507  // hfx_z, qfx1_z = rho<w'theta'>, rho<w'qv'> (z-faces)
508  //
509  // Two different heights are wanted here, so the two are kept apart:
510  // - u_*, thetav_* and L are surface-layer parameters and have no
511  // cell-centered counterpart, so they come from the zlo face alone;
512  // - the production terms belong at the cell center, so their flux
513  // factors average the two z-faces bounding this cell.
514  // Only the profile shape, phi(zeta_1)/(kappa z_1), ties the two together.
515 
516  const amrex::Real theta = cell_data(i,j,k,RhoTheta_comp) / rho;
517  const amrex::Real qv = (moisture_indices.qv >= 0) ?
518  cell_data(i,j,k,moisture_indices.qv) / rho : zero;
519 
520  // ---- Surface-layer parameters, on the zlo face ----
521 
522  // |tau|/rho = u_*^2
523  const amrex::Real t13_s = myhalf * ( tau13(i,j,k) + tau13(i+1,j,k) );
524  const amrex::Real t23_s = myhalf * ( tau23(i,j,k) + tau23(i,j+1,k) );
525  const amrex::Real tau_s = std::sqrt(t13_s*t13_s + t23_s*t23_s);
526  const amrex::Real ustar2 = tau_s / rho;
527  const amrex::Real ustar = std::sqrt(ustar2);
528 
529  // Surface virtual heat flux rho<w'theta_v'> (Stull Eqn. 4.4.5d)
530  amrex::Real hfxv_s = hfx_z(i,j,k) * (one + epsv*qv);
531  if (qfx1_z) { hfxv_s += epsv * theta * qfx1_z(i,j,k); }
532 
533  // Height of this cell center above the surface. dz_inv.dirichlet_lo is by
534  // construction the inverse of the boundary-to-first-center distance, so it
535  // carries the right height for uniform, stretched and terrain-fitted grids.
536  const amrex::Real z1 = one / dz_inv.dirichlet_lo;
537 
538  // Obukhov length, from the surface fluxes. A vanishing stress (a building
539  // face, say) leaves the shear production zero whatever zeta is, so the
540  // neutral value is the safe one to carry into phi_m there.
541  const amrex::Real thetav = theta * (one + epsv*qv);
543  amrex::Real zeta = zero;
544  if (std::abs(hfxv_s) > eps && ustar > eps) {
545  const amrex::Real l_obukhov = -( thetav * rho * ustar2 * ustar )
546  / ( KAPPA * CONST_GRAV * hfxv_s );
547  zeta = z1 / l_obukhov;
548  }
549 
550  // phi_m, the companion of the psi_m that SurfaceLayer uses
551  const similarity_funs sfuns{};
552  const amrex::Real phi_m = sfuns.calc_phi_m(zeta);
553 
554  // ---- Production terms, at the cell center ----
555 
556  // Cell-centered stress: average the two z-faces bounding this cell
557  const amrex::Real t13_c = fourth * ( tau13(i,j,k ) + tau13(i+1,j,k )
558  + tau13(i,j,k+1) + tau13(i+1,j,k+1) );
559  const amrex::Real t23_c = fourth * ( tau23(i,j ,k) + tau23(i,j ,k+1)
560  + tau23(i,j+1,k) + tau23(i,j+1,k+1) );
561 
562  // Cell-centered virtual heat flux. Both faces are from this stage: the
563  // QKE sources are added after RhoQ1 is diffused (see AddTurbKESources).
564  amrex::Real hfxv_c = myhalf * ( hfx_z(i,j,k) + hfx_z(i,j,k+1) ) * (one + epsv*qv);
565  if (qfx1_z) {
566  hfxv_c += epsv * theta * myhalf * ( qfx1_z(i,j,k) + qfx1_z(i,j,k+1) );
567  }
568 
569  // Shear production, -<u'w'> dU/dz - <v'w'> dV/dz. MOST sets the direction
570  // of the mean shear anti-parallel to the surface stress and its magnitude
571  // to u_* phi_m/(kappa z_1), so the dot product is the cell-centered stress
572  // projected onto the surface stress. This reduces to |tau| u_* phi_m /
573  // (kappa z_1) when the stress does not turn across the cell.
574  if (tau_s > eps) {
575  const amrex::Real tau_proj = (t13_c*t13_s + t23_c*t23_s) / tau_s;
576  source_term += std::max(tau_proj,amrex::Real(0.)) * ustar * phi_m / (KAPPA * z1);
577  }
578 
579  // Buoyancy production, which needs no gradient at all
580  source_term += (CONST_GRAV/theta_mean) * hfxv_c;
581  }
582  else
583  {
584  // Compute some relevant derivatives
585  amrex::Real dthetadz, dudz, dvdz;
587  uvel, vvel, cell_data, izmin, izmax, dz_inv,
588  c_ext_dir_on_zlo, c_ext_dir_on_zhi,
589  u_ext_dir_on_zlo, u_ext_dir_on_zhi,
590  v_ext_dir_on_zlo, v_ext_dir_on_zhi,
591  dthetadz, dudz, dvdz,
592  moisture_indices);
593 
594  // Second-order turbulent fluxes, e.g.:
595  // -<uw> = L q SM dU/dz (NN09, Eqn. 18)
596  // = Kmv/rho dU/dz
597 
598  // Shear Production
599  source_term += K_turb(i,j,k,EddyDiff::Mom_v) * (dudz*dudz + dvdz*dvdz);
600 
601  // Buoyancy Production
602  source_term -= (CONST_GRAV/theta_mean)*K_turb(i,j,k,EddyDiff::Theta_v)*dthetadz;
603  }
604 
605  // Dissipation (NN09, Eqn. 12)
606  amrex::Real qke = two * cell_prim(i,j,k,PrimKE_comp);
607  if (std::abs(qke) > zero) {
608  source_term -= rho * std::pow(qke,amrex::Real(1.5)) /
609  (pbl_mynn_B1_l * K_turb(i,j,k,EddyDiff::Turb_lengthscale));
610  }
611 
612  return source_term;
613 }
614 
615 /**
616  * @brief Functor for inverse vertical spacings with constant grid spacing.
617  */
619 {
621 
622  /**
623  * Return inverse vertical spacings for constant grid spacing.
624  * @return PBLDerivativeDzInv inverse spacing values
625  */
626  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
627  PBLDerivativeDzInv operator() (int, int, int) const noexcept
628  {
629  return {myhalf*value, two*value, two*value};
630  }
631 };
632 
633 /**
634  * @brief Functor for inverse vertical spacings for stretched grids using a spacing array.
635  */
637 {
638  const amrex::Real* dz;
639  int klo;
640  int khi;
641 
642  /**
643  * Return inverse vertical spacings for stretched grids.
644  * @param k z-index
645  * @return PBLDerivativeDzInv inverse spacing values
646  */
647  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
648  PBLDerivativeDzInv operator() (int, int, int k) const noexcept
649  {
650  // Adjacent cell centers are separated by half the sum of their widths.
651  const amrex::Real dz_lo = dz[(k > klo) ? k-1 : k];
652  const amrex::Real dz_hi = dz[(k < khi) ? k+1 : k];
653  return {two / (dz_lo + two*dz[k] + dz_hi),
654  two / dz[k],
655  two / dz[k]};
656  }
657 };
658 
659 /**
660  * @brief Functor for inverse vertical spacings for terrain-following grids using cell-center heights.
661  */
663 {
664  amrex::Array4<const amrex::Real> z_cc;
665 
666  /**
667  * Return inverse vertical spacings for terrain-following grids.
668  * @param i x-index
669  * @param j y-index
670  * @param k z-index
671  * @return PBLDerivativeDzInv inverse spacing values
672  */
673  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
674  PBLDerivativeDzInv operator() (int i, int j, int k) const noexcept
675  {
676  return {one / (z_cc(i,j,k+1) - z_cc(i,j,k-1)),
677  two / (z_cc(i,j,k ) - z_cc(i,j,k-1)),
678  two / (z_cc(i,j,k+1) - z_cc(i,j,k ))};
679  }
680 };
681 
682 /**
683  * @brief Apply spatial smoothing to PBLH field using 5-point stencil.
684  *
685  * Applies a simple 5-point spatial averaging to reduce grid-to-grid noise in
686  * the diagnosed PBLH field. This is standard post-processing practice for
687  * discrete Rib-crossing detection as described in Seibert et al. (2000):
688  * "Review and intercomparison of operational methods for the determination of
689  * the mixing height", Atmospheric Environment, 34, 1001-1027.
690  *
691  * Stencil: PBLH_smooth(i,j) = w * PBLH(i,j) + (1-w)/4 * [PBLH(i+-1,j) + PBLH(i,j+-1)]
692  *
693  * The stencil reads one column outside the region it writes, so the result on a
694  * cell depends on columns that a single tile -- or a single box -- does not own.
695  * The caller therefore names the region it wants smoothed (xybx_valid, normally
696  * the planar tile box) inside a work array carrying `passes` columns of halo
697  * around it, filled from the same inputs. Pass p writes the region grown by
698  * passes-1-p and reads the one grown by passes-p, so each pass consumes one
699  * column of halo and the last lands exactly on xybx_valid. Every read stays
700  * inside the array, and the result does not depend on how the domain is divided
701  * into boxes or tiles.
702  *
703  * At a non-periodic domain edge there is no column to read, so the stencil reuses
704  * the cell's own value (reflective/Neumann). Across a periodic edge the halo holds
705  * the wrapped columns and is read directly, which is why the periodicity has to be
706  * passed in: clamping there would fold an edge into a domain that has none.
707  *
708  * @param[in,out] pblh_fab FArrayBox holding the 2D PBLH field (component 0),
709  * sized to contain xybx_valid grown by `passes` in x and y
710  * @param[in] xybx_valid Region to smooth (x,y indices only)
711  * @param[in] weight Center cell weight in stencil (must be in [0,1])
712  * @param[in] passes Number of smoothing iterations
713  * @param[in] domain Domain box, for the reflective edge condition
714  * @param[in] periodicity Domain periodicity, so periodic edges read the halo
715  */
716 inline void
717 ApplyPBLHSmoothing (amrex::FArrayBox& pblh_fab,
718  const amrex::Box& xybx_valid,
719  const amrex::Real weight,
720  const int passes,
721  const amrex::Box& domain,
722  const amrex::Periodicity& periodicity)
723 {
724  if (passes <= 0) { return; }
725 
726  // The caller must supply the halo the passes will consume; see the note above.
728  pblh_fab.box().contains(amrex::grow(xybx_valid, amrex::IntVect(passes,passes,0))),
729  "ApplyPBLHSmoothing: the PBLH work array needs `passes` columns of halo "
730  "around the region being smoothed");
731 
732  // Use a temporary to hold intermediate results
733  amrex::FArrayBox pblh_temp(pblh_fab.box(), 1, amrex::The_Async_Arena());
734  auto pblh = pblh_fab.array();
735  auto pblh_tmp = pblh_temp.array();
736 
737  const auto& dom_lo = amrex::lbound(domain);
738  const auto& dom_hi = amrex::ubound(domain);
739 
740  const bool per_x = periodicity.isPeriodic(0);
741  const bool per_y = periodicity.isPeriodic(1);
742 
743  const amrex::Real wt_side = (one - weight) / four; // Weight for each of 4 neighbors
744 
745  // Apply smoothing passes
746  for (int pass = 0; pass < passes; ++pass) {
747  const int halo = passes - 1 - pass;
748  const amrex::Box bx = amrex::grow(xybx_valid, amrex::IntVect(halo,halo,0));
749 
750  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
751  {
752  // Reflective (Neumann) at a non-periodic domain edge: reuse the cell's
753  // own value. Everywhere else -- including across a periodic edge, where
754  // the halo holds the wrapped column -- read the neighbour.
755  const int i_xlo = (per_x || i > dom_lo.x) ? (i - 1) : i;
756  const int i_xhi = (per_x || i < dom_hi.x) ? (i + 1) : i;
757  const int j_ylo = (per_y || j > dom_lo.y) ? (j - 1) : j;
758  const int j_yhi = (per_y || j < dom_hi.y) ? (j + 1) : j;
759 
760  // 5-point stencil
761  pblh_tmp(i, j, 0) = weight * pblh(i, j, 0)
762  + wt_side * (pblh(i_xlo, j, 0) + pblh(i_xhi, j, 0) +
763  pblh(i, j_ylo, 0) + pblh(i, j_yhi, 0));
764  });
765 
766  // Copy back only what this pass computed: outside bx the array still holds
767  // the previous pass, which no later pass reads.
768  pblh_fab.copy<amrex::RunOn::Device>(pblh_temp, bx, 0, bx, 0, 1);
769  }
770 }
771 
772 #endif
constexpr amrex::Real epsv
Definition: ERF_Constants.H:52
constexpr amrex::Real KAPPA
Definition: ERF_Constants.H:67
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:68
@ tau23
Definition: ERF_DataStruct.H:48
@ tau13
Definition: ERF_DataStruct.H:48
#define Rho_comp
Definition: ERF_IndexDefines.H:42
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:43
#define PrimKE_comp
Definition: ERF_IndexDefines.H:62
const bool use_moisture
Definition: ERF_InitCustomPert_ABL.H:71
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
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 GetThetal(const int &i, const int &j, const int &k, const amrex::Array4< amrex::Real const > &cell_data, const MoistureComponentIndices &moisture_indices)
Definition: ERF_MoistUtils.H:130
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 four
Definition: ERF_NumericalConstants.H:40
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:38
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetPBLStratVar(int i, int j, int k, const StratType strat, const amrex::Array4< const amrex::Real > &cell_data, const MoistureComponentIndices &moisture_indices)
Definition: ERF_PBLModels.H:288
void ComputeDiffusivityYSU(const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices)
void ComputeDiffusivityMYNNEDMF(const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices)
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ComputeVerticalDerivativesPBL(int i, int j, int k, const amrex::Array4< const amrex::Real > &uvel, const amrex::Array4< const amrex::Real > &vvel, const amrex::Array4< const amrex::Real > &cell_data, const int izmin, const int izmax, const PBLDerivativeDzInv &dz_inv, const bool c_ext_dir_on_zlo, const bool c_ext_dir_on_zhi, const bool u_ext_dir_on_zlo, const bool u_ext_dir_on_zhi, const bool v_ext_dir_on_zlo, const bool v_ext_dir_on_zhi, amrex::Real &dthetadz, amrex::Real &dudz, amrex::Real &dvdz, const MoistureComponentIndices &moisture_indices, const StratType strat=StratType::thetav)
Definition: ERF_PBLModels.H:304
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeQKESourceTerms(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 amrex::Array4< const amrex::Real > &cell_prim, const amrex::Array4< const amrex::Real > &K_turb, const amrex::Box &domain, const PBLDerivativeDzInv dz_inv, amrex::Real pbl_mynn_B1_l, const amrex::Real theta_mean, const MoistureComponentIndices &moisture_indices, bool c_ext_dir_on_zlo, bool c_ext_dir_on_zhi, bool u_ext_dir_on_zlo, bool u_ext_dir_on_zhi, bool v_ext_dir_on_zlo, bool v_ext_dir_on_zhi, const amrex::Array4< const amrex::Real > &tau13, const amrex::Array4< const amrex::Real > &tau23, const amrex::Array4< const amrex::Real > &hfx_z, const amrex::Array4< const amrex::Real > &qfx1_z, bool surface_layer_on_zlo)
Definition: ERF_PBLModels.H:457
void ComputeDiffusivityMRF(const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices, const amrex::MultiFab *terrain_blank=nullptr)
void ComputeDiffusivityMYNN25(const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices)
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:717
void ComputeDiffusivityYSUNew(const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices, const amrex::MultiFab *qheating_rates=nullptr, const amrex::MultiFab *terrain_blank=nullptr)
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ApplySurfaceLayerGradientsPBL(const PBLSurfaceLayerGradient &sl, amrex::Real &dthetadz, amrex::Real &dudz, amrex::Real &dvdz)
Definition: ERF_PBLModels.H:423
void ComputeDiffusivityMYJ(double dt, const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices)
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeVirtualTStarPBL(amrex::Real t_star, amrex::Real q_star, amrex::Real theta, amrex::Real qv, bool use_moisture)
Definition: ERF_PBLModels.H:386
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ Theta_v
Definition: ERF_IndexDefines.H:253
@ Turb_lengthscale
Definition: ERF_IndexDefines.H:257
@ Mom_v
Definition: ERF_IndexDefines.H:252
@ ustar
Definition: ERF_SLM.H:28
@ rho
Definition: ERF_Kessler.H:25
@ theta
Definition: ERF_Kessler.H:26
@ qv
Definition: ERF_Kessler.H:31
@ xvel
Definition: ERF_IndexDefines.H:218
@ yvel
Definition: ERF_IndexDefines.H:219
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
The moisture data carried by the active microphysics scheme.
Definition: ERF_DataStruct.H:238
int qv
water vapor
Definition: ERF_DataStruct.H:249
Functor for inverse vertical spacings with constant grid spacing.
Definition: ERF_PBLModels.H:619
amrex::Real value
Definition: ERF_PBLModels.H:620
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE PBLDerivativeDzInv operator()(int, int, int) const noexcept
Definition: ERF_PBLModels.H:627
Functor for inverse vertical spacings for stretched grids using a spacing array.
Definition: ERF_PBLModels.H:637
const amrex::Real * dz
Definition: ERF_PBLModels.H:638
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE PBLDerivativeDzInv operator()(int, int, int k) const noexcept
Definition: ERF_PBLModels.H:648
int klo
Definition: ERF_PBLModels.H:639
int khi
Definition: ERF_PBLModels.H:640
Functor for inverse vertical spacings for terrain-following grids using cell-center heights.
Definition: ERF_PBLModels.H:663
amrex::Array4< const amrex::Real > z_cc
Definition: ERF_PBLModels.H:664
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE PBLDerivativeDzInv operator()(int i, int j, int k) const noexcept
Definition: ERF_PBLModels.H:674
Definition: ERF_PBLModels.H:248
amrex::Real dirichlet_hi
Definition: ERF_PBLModels.H:253
amrex::Real interior
Definition: ERF_PBLModels.H:251
amrex::Real dirichlet_lo
Definition: ERF_PBLModels.H:252
Definition: ERF_PBLModels.H:366
amrex::Real tstar_v
virtual temperature scale
Definition: ERF_PBLModels.H:368
amrex::Real zeta
stability coordinate z/L
Definition: ERF_PBLModels.H:370
amrex::Real u_star
friction velocity
Definition: ERF_PBLModels.H:367
amrex::Real zval
height of the cell center above the surface
Definition: ERF_PBLModels.H:369
Definition: ERF_TurbStruct.H:115
Definition: ERF_MOSTUtils.H:37