ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ERF_PBLModels.H
Go to the documentation of this file.
1 #ifndef ERF_PBLMODELS_H_
2 #define ERF_PBLMODELS_H_
3 
4 #include <ERF_Thetav.H>
5 
6 /**
7  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
8  * Mellor-Yamada-Nakanishi-Niino Level 2.5 PBL scheme
9  *
10  * @param[in] xvel Velocity in x-dir
11  * @param[in] yvel Velocity in y-dir
12  * @param[in] cons_in Cell center conserved quantities
13  * @param[out] eddyViscosity Holds turbulent viscosity
14  * @param[in] geom Problem geometry
15  * @param[in] turbChoice Container with turbulence parameters
16  * @param[in] most Pointer to Monin-Obukhov class if instantiated
17  * @param[in] use_moisture If we have microphysics enabled
18  * @param[in] level Current level
19  * @param[in] bc_ptr Pointer to array with boundary condition info
20  * @param[in] vert_only Only compute vertical eddy diffusivities
21  * @param[in] z_phys_nd Physical location of grid nodes, if terrain (or grid stretching) is enabled
22  */
23 void
24 ComputeDiffusivityMYNN25 (const amrex::MultiFab& xvel,
25  const amrex::MultiFab& yvel,
26  const amrex::MultiFab& cons_in,
27  amrex::MultiFab& eddyViscosity,
28  const amrex::Geometry& geom,
29  const TurbChoice& turbChoice,
30  std::unique_ptr<ABLMost>& most,
31  bool use_terrain_fitted_coords,
32  bool use_moisture,
33  int level,
34  const amrex::BCRec* bc_ptr,
35  bool /*vert_only*/,
36  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
37  const int RhoQv_comp,
38  const int RhoQc_comp,
39  const int RhoQr_comp);
40 
41 /**
42  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
43  * Mellor-Yamada-Nakanishi-Niino Level 2.5 PBL scheme
44  *
45  * @param[in] xvel Velocity in x-dir
46  * @param[in] yvel Velocity in y-dir
47  * @param[in] cons_in Cell center conserved quantities
48  * @param[out] eddyViscosity Holds turbulent viscosity
49  * @param[in] geom Problem geometry
50  * @param[in] turbChoice Container with turbulence parameters
51  * @param[in] most Pointer to Monin-Obukhov class if instantiated
52  * @param[in] use_moisture If we have microphysics enabled
53  * @param[in] level Current level
54  * @param[in] bc_ptr Pointer to array with boundary condition info
55  * @param[in] vert_only Only compute vertical eddy diffusivities
56  * @param[in] z_phys_nd Physical location of grid nodes, if terrain (or grid stretching) is enabled
57  */
58 void
59 ComputeDiffusivityMYNNEDMF (const amrex::MultiFab& xvel,
60  const amrex::MultiFab& yvel,
61  const amrex::MultiFab& cons_in,
62  amrex::MultiFab& eddyViscosity,
63  const amrex::Geometry& geom,
64  const TurbChoice& turbChoice,
65  std::unique_ptr<ABLMost>& most,
66  bool use_terrain_fitted_coords,
67  bool use_moisture,
68  int level,
69  const amrex::BCRec* bc_ptr,
70  bool /*vert_only*/,
71  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
72  const int RhoQv_comp,
73  const int RhoQc_comp,
74  const int RhoQr_comp);
75 
76 /**
77  * Compute eddy diffusivities of momentum (eddy viscosity) and heat using the
78  * Yonsei University PBL scheme
79  *
80  * @param[in] xvel Velocity in x-dir
81  * @param[in] yvel Velocity in y-dir
82  * @param[in] cons_in Cell center conserved quantities
83  * @param[out] eddyViscosity Holds turbulent viscosity
84  * @param[in] geom Problem geometry
85  * @param[in] turbChoice Container with turbulence parameters
86  * @param[in] most Pointer to Monin-Obukhov class if instantiated
87  * @param[in] use_moisture If we have microphysics enabled
88  * @param[in] level Current level
89  * @param[in] bc_ptr Pointer to array with boundary condition info
90  * @param[in] vert_only Only compute vertical eddy diffusivities
91  * @param[in] z_phys_nd Physical location of grid nodes, if terrain (or grid stretching) is enabled
92  */
93 void
94 ComputeDiffusivityYSU (const amrex::MultiFab& xvel,
95  const amrex::MultiFab& yvel,
96  const amrex::MultiFab& cons_in,
97  amrex::MultiFab& eddyViscosity,
98  const amrex::Geometry& geom,
99  const TurbChoice& turbChoice,
100  std::unique_ptr<ABLMost>& most,
101  bool use_terrain_fitted_coords,
102  bool use_moisture,
103  int level,
104  const amrex::BCRec* bc_ptr,
105  bool /*vert_only*/,
106  const std::unique_ptr<amrex::MultiFab>& z_phys_nd);
107 
108 
109 /**
110  * Function for computing vertical derivatives for use in PBL model
111  *
112  * @param[in] u velocity in x-dir
113  * @param[in] v velocity in y-dir
114  * @param[in] cell_data conserved cell center vars
115  */
116 AMREX_GPU_DEVICE
117 AMREX_FORCE_INLINE
118 void
119 ComputeVerticalDerivativesPBL (int i, int j, int k,
120  const amrex::Array4<const amrex::Real>& uvel,
121  const amrex::Array4<const amrex::Real>& vvel,
122  const amrex::Array4<const amrex::Real>& cell_data,
123  const int izmin,
124  const int izmax,
125  const amrex::Real& dz_inv,
126  const bool c_ext_dir_on_zlo,
127  const bool c_ext_dir_on_zhi,
128  const bool u_ext_dir_on_zlo,
129  const bool u_ext_dir_on_zhi,
130  const bool v_ext_dir_on_zlo,
131  const bool v_ext_dir_on_zhi,
132  amrex::Real& dthetadz,
133  amrex::Real& dudz,
134  amrex::Real& dvdz,
135  const int RhoQv_comp,
136  const int RhoQc_comp,
137  const int RhoQr_comp,
138  const bool use_most=true)
139 {
140  if ( k==izmax && c_ext_dir_on_zhi ) {
141  dthetadz = (1.0/3.0)*( -Thetav(i,j,k-1,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp)
142  - 3.0 * Thetav(i,j,k ,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp)
143  + 4.0 * Thetav(i,j,k+1,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp) )*dz_inv;
144  } else if ( k==izmin && c_ext_dir_on_zlo ) {
145  dthetadz = (1.0/3.0)*( Thetav(i,j,k+1,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp)
146  + 3.0 * Thetav(i,j,k ,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp)
147  - 4.0 * Thetav(i,j,k-1,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp) )*dz_inv;
148  } else if ( k==izmin && use_most ) {
149  dthetadz = ( Thetav(i,j,k+1,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp)
150  - Thetav(i,j,k ,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp) )*dz_inv;
151  } else {
152  dthetadz = 0.5*( Thetav(i,j,k+1,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp)
153  - Thetav(i,j,k-1,cell_data,RhoQv_comp,RhoQc_comp,RhoQr_comp) )*dz_inv;
154  }
155 
156  if ( k==izmax && u_ext_dir_on_zhi ) {
157  dudz = (1.0/6.0)*( (-uvel(i ,j,k-1) - 3.0 * uvel(i ,j,k ) + 4.0 * uvel(i ,j,k+1))
158  + (-uvel(i+1,j,k-1) - 3.0 * uvel(i+1,j,k ) + 4.0 * uvel(i+1,j,k+1)) )*dz_inv;
159  } else if ( k==izmin && u_ext_dir_on_zlo ) {
160  dudz = (1.0/6.0)*( (uvel(i ,j,k+1) + 3.0 * uvel(i ,j,k ) - 4.0 * uvel(i ,j,k-1))
161  + (uvel(i+1,j,k+1) + 3.0 * uvel(i+1,j,k ) - 4.0 * uvel(i+1,j,k-1)) )*dz_inv;
162  } else if ( k==izmin && use_most ) {
163  dudz = 0.50*( uvel(i,j,k+1) - uvel(i,j,k ) + uvel(i+1,j,k+1) - uvel(i+1,j,k ) )*dz_inv;
164  } else {
165  dudz = 0.25*( uvel(i,j,k+1) - uvel(i,j,k-1) + uvel(i+1,j,k+1) - uvel(i+1,j,k-1) )*dz_inv;
166  }
167 
168  if ( k==izmax && v_ext_dir_on_zhi ) {
169  dvdz = (1.0/6.0)*( (-vvel(i,j ,k-1) - 3.0 * vvel(i,j ,k ) + 4.0 * vvel(i,j ,k+1))
170  + (-vvel(i,j+1,k-1) - 3.0 * vvel(i,j+1,k ) + 4.0 * vvel(i,j+1,k+1)) )*dz_inv;
171  } else if ( k==izmin && v_ext_dir_on_zlo ) {
172  dvdz = (1.0/6.0)*( (vvel(i,j ,k+1) + 3.0 * vvel(i,j ,k ) - 4.0 * vvel(i,j ,k-1))
173  + (vvel(i,j+1,k+1) + 3.0 * vvel(i,j+1,k ) - 4.0 * vvel(i,j+1,k-1)) )*dz_inv;
174  } else if ( k==izmin && use_most ) {
175  dvdz = 0.50*( vvel(i,j,k+1) - vvel(i,j,k ) + vvel(i,j+1,k+1) - vvel(i,j+1,k ) )*dz_inv;
176  } else {
177  dvdz = 0.25*( vvel(i,j,k+1) - vvel(i,j,k-1) + vvel(i,j+1,k+1) - vvel(i,j+1,k-1) )*dz_inv;
178  }
179 }
180 
181 /**
182  * Function for computing the QKE source terms (NN09, Eqn. 5).
183  *
184  * @param[in] u velocity in x-dir
185  * @param[in] v velocity in y-dir
186  * @param[in] cell_data conserved cell center vars
187  * @param[in] cell_prim primitive cell center vars
188  * @param[in] K_turb turbulent viscosity
189  * @param[in] cellSizeInv inverse cell size array
190  * @param[in] domain box of the whole domain
191  * @param[in] pbl_mynn_B1_l a parameter
192  * @param[in] theta_mean average theta
193  */
194 AMREX_GPU_DEVICE
195 AMREX_FORCE_INLINE
196 amrex::Real
197 ComputeQKESourceTerms (int i, int j, int k,
198  const amrex::Array4<const amrex::Real>& uvel,
199  const amrex::Array4<const amrex::Real>& vvel,
200  const amrex::Array4<const amrex::Real>& cell_data,
201  const amrex::Array4<const amrex::Real>& cell_prim,
202  const amrex::Array4<const amrex::Real>& K_turb,
203  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
204  const amrex::Box& domain,
205  amrex::Real pbl_mynn_B1_l,
206  const amrex::Real theta_mean,
207  const int RhoQv_comp,
208  const int RhoQc_comp,
209  const int RhoQr_comp,
210  bool c_ext_dir_on_zlo,
211  bool c_ext_dir_on_zhi,
212  bool u_ext_dir_on_zlo,
213  bool u_ext_dir_on_zhi,
214  bool v_ext_dir_on_zlo,
215  bool v_ext_dir_on_zhi,
216  const bool use_most=false,
217  const amrex::Real met_h_zeta=1.0)
218 {
219  // Compute some relevant derivatives
220  amrex::Real dthetadz, dudz, dvdz;
221  amrex::Real source_term = 0.0;
222 
223  amrex::Real dz_inv = cellSizeInv[2];
224  int izmin = domain.smallEnd(2);
225  int izmax = domain.bigEnd(2);
226 
227  // NOTE: With MOST, the ghost cells are filled AFTER k_turb is computed
228  // so that the non-explicit pathway works. Therefore, at this
229  // point we DO have valid ghost cells from MOST. We are passing
230  // the MOST flag to use one-sided diffs here to be consistent with
231  // the explicit pathway.
232 
234  uvel, vvel, cell_data, izmin, izmax, dz_inv/met_h_zeta,
235  c_ext_dir_on_zlo, c_ext_dir_on_zhi,
236  u_ext_dir_on_zlo, u_ext_dir_on_zhi,
237  v_ext_dir_on_zlo, v_ext_dir_on_zhi,
238  dthetadz, dudz, dvdz,
239  RhoQv_comp, RhoQc_comp, RhoQr_comp, use_most);
240 
241  // Note: Transport terms due to turbulence and pressure are included when
242  // DiffusionSrcForState_* is called from ERF_slow_rhs_post.
243 
244  // Shear Production
245  source_term += K_turb(i,j,k,EddyDiff::Mom_v) * (dudz*dudz + dvdz*dvdz);
246 
247  // Buoyancy Production
248  source_term -= (CONST_GRAV/theta_mean)*K_turb(i,j,k,EddyDiff::Theta_v)*dthetadz;
249 
250  // Dissipation
251  amrex::Real qke = 2.0 * cell_prim(i,j,k,PrimKE_comp);
252  if (std::abs(qke) > 0.0) {
253  source_term -= cell_data(i,j,k,Rho_comp) * std::pow(qke,1.5) /
254  (pbl_mynn_B1_l * K_turb(i,j,k,EddyDiff::Turb_lengthscale));
255  }
256 
257  return source_term;
258 }
259 #endif
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:21
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define PrimKE_comp
Definition: ERF_IndexDefines.H:51
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< ABLMost > &most, 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)
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::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Box &domain, amrex::Real pbl_mynn_B1_l, const amrex::Real theta_mean, const int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp, 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 bool use_most=false, const amrex::Real met_h_zeta=1.0)
Definition: ERF_PBLModels.H:197
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< ABLMost > &most, 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 int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp)
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< ABLMost > &most, 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 int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp)
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 amrex::Real &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 int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp, const bool use_most=true)
Definition: ERF_PBLModels.H:119
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Thetav(int i, int j, int k, const amrex::Array4< const amrex::Real > &cell_data, const int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp)
Definition: ERF_Thetav.H:10
@ Theta_v
Definition: ERF_IndexDefines.H:168
@ Turb_lengthscale
Definition: ERF_IndexDefines.H:172
@ Mom_v
Definition: ERF_IndexDefines.H:167
@ xvel
Definition: ERF_IndexDefines.H:141
@ yvel
Definition: ERF_IndexDefines.H:142
Definition: ERF_TurbStruct.H:31