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