ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ComputeTurbulentViscosity.cpp File Reference
#include <ERF_ABLMost.H>
#include <ERF_EddyViscosity.H>
#include <ERF_Diffusion.H>
#include <ERF_PBLModels.H>
#include <ERF_TileNoZ.H>
#include <ERF_TerrainMetrics.H>
Include dependency graph for ERF_ComputeTurbulentViscosity.cpp:

Functions

void ComputeTurbulentViscosityLES (const MultiFab &Tau11, const MultiFab &Tau22, const MultiFab &Tau33, const MultiFab &Tau12, const MultiFab &Tau13, const MultiFab &Tau23, const MultiFab &cons_in, MultiFab &eddyViscosity, MultiFab &Hfx1, MultiFab &Hfx2, MultiFab &Hfx3, MultiFab &Diss, const Geometry &geom, const MultiFab &mapfac_u, const MultiFab &mapfac_v, const std::unique_ptr< MultiFab > &z_phys_nd, const TurbChoice &turbChoice, const Real const_grav, std::unique_ptr< ABLMost > &most, const bool &exp_most)
 
void ComputeTurbulentViscosity (const MultiFab &xvel, const MultiFab &yvel, const MultiFab &Tau11, const MultiFab &Tau22, const MultiFab &Tau33, const MultiFab &Tau12, const MultiFab &Tau13, const MultiFab &Tau23, const MultiFab &cons_in, MultiFab &eddyViscosity, MultiFab &Hfx1, MultiFab &Hfx2, MultiFab &Hfx3, MultiFab &Diss, const Geometry &geom, const MultiFab &mapfac_u, const MultiFab &mapfac_v, const std::unique_ptr< MultiFab > &z_phys_nd, const SolverChoice &solverChoice, std::unique_ptr< ABLMost > &most, const bool &exp_most, const bool &use_moisture, int level, const BCRec *bc_ptr, bool vert_only)
 

Function Documentation

◆ ComputeTurbulentViscosity()

void ComputeTurbulentViscosity ( const MultiFab &  xvel,
const MultiFab &  yvel,
const MultiFab &  Tau11,
const MultiFab &  Tau22,
const MultiFab &  Tau33,
const MultiFab &  Tau12,
const MultiFab &  Tau13,
const MultiFab &  Tau23,
const MultiFab &  cons_in,
MultiFab &  eddyViscosity,
MultiFab &  Hfx1,
MultiFab &  Hfx2,
MultiFab &  Hfx3,
MultiFab &  Diss,
const Geometry &  geom,
const MultiFab &  mapfac_u,
const MultiFab &  mapfac_v,
const std::unique_ptr< MultiFab > &  z_phys_nd,
const SolverChoice solverChoice,
std::unique_ptr< ABLMost > &  most,
const bool &  exp_most,
const bool &  use_moisture,
int  level,
const BCRec *  bc_ptr,
bool  vert_only 
)

Wrapper to compute turbulent viscosity with LES or PBL.

Parameters
[in]xvelvelocity in x-dir
[in]yvelvelocity in y-dir
[in]Tau1111 strain
[in]Tau2222 strain
[in]Tau3333 strain
[in]Tau1212 strain
[in]Tau1313 strain
[in]Tau2323 strain
[in]cons_incell center conserved quantities
[out]eddyViscosityturbulent viscosity
[in]Hfx1heat flux in x-dir
[in]Hfx2heat flux in y-dir
[in]Hfx3heat flux in z-dir
[in]Dissdissipation of turbulent kinetic energy
[in]geomproblem geometry
[in]mapfac_umap factor at x-face
[in]mapfac_vmap factor at y-face
[in]turbChoicecontainer with turbulence parameters
[in]mostpointer to Monin-Obukhov class if instantiated
[in]vert_onlyflag for vertical components of eddyViscosity
452 {
453  BL_PROFILE_VAR("ComputeTurbulentViscosity()",ComputeTurbulentViscosity);
454  //
455  // In LES mode, the turbulent viscosity is isotropic, so the LES model sets both horizontal and vertical viscosities
456  // In PBL mode, the primary purpose of the PBL model is to control vertical transport, so the PBL model sets the vertical viscosity.
457  // Optionally, the PBL model can be run in conjunction with an LES model that sets the horizontal viscosity
458  // (this isn’t truly LES, but the model form is the same as Smagorinsky).
459  //
460  // ComputeTurbulentViscosityLES populates the LES viscosity for both horizontal and vertical components.
461  // ComputeTurbulentViscosityPBL computes the PBL viscosity just for the vertical component.
462  //
463 
464  TurbChoice turbChoice = solverChoice.turbChoice[level];
465  const Real const_grav = solverChoice.gravity;
466 
467  if (most) {
468  bool l_use_turb = ( turbChoice.les_type == LESType::Smagorinsky ||
469  turbChoice.les_type == LESType::Deardorff ||
470  turbChoice.pbl_type == PBLType::MYNN25 ||
471  turbChoice.pbl_type == PBLType::YSU );
472  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(l_use_turb,
473  "An LES or PBL model must be utilized with MOST boundaries to compute the turbulent viscosity");
474  } else {
475  AMREX_ALWAYS_ASSERT(!vert_only);
476  }
477 
478  if (turbChoice.les_type != LESType::None) {
479  ComputeTurbulentViscosityLES(Tau11, Tau22, Tau33,
480  Tau12, Tau13, Tau23,
481  cons_in, eddyViscosity,
482  Hfx1, Hfx2, Hfx3, Diss,
483  geom, mapfac_u, mapfac_v,
484  z_phys_nd, turbChoice, const_grav,
485  most, exp_most);
486  }
487 
488  if (turbChoice.pbl_type == PBLType::MYNN25) {
489  ComputeDiffusivityMYNN25(xvel, yvel, cons_in, eddyViscosity,
490  geom, turbChoice, most, use_moisture,
491  level, bc_ptr, vert_only, z_phys_nd,
492  solverChoice.RhoQv_comp, solverChoice.RhoQc_comp,
493  solverChoice.RhoQr_comp);
494  } else if (turbChoice.pbl_type == PBLType::YSU) {
495  ComputeDiffusivityYSU(xvel, yvel, cons_in, eddyViscosity,
496  geom, turbChoice, most, use_moisture,
497  level, bc_ptr, vert_only, z_phys_nd);
498  }
499 }
void ComputeDiffusivityMYNN25(const MultiFab &xvel, const MultiFab &yvel, const MultiFab &cons_in, MultiFab &eddyViscosity, const Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< ABLMost > &most, bool use_moisture, int level, const BCRec *bc_ptr, bool, const std::unique_ptr< MultiFab > &z_phys_nd, const int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp)
Definition: ERF_ComputeDiffusivityMYNN25.cpp:11
void ComputeDiffusivityYSU(const MultiFab &xvel, const MultiFab &yvel, const MultiFab &cons_in, MultiFab &eddyViscosity, const Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< ABLMost > &most, bool, int level, const BCRec *bc_ptr, bool, const std::unique_ptr< MultiFab > &z_phys_nd)
Definition: ERF_ComputeDiffusivityYSU.cpp:11
void ComputeTurbulentViscosity(const MultiFab &xvel, const MultiFab &yvel, const MultiFab &Tau11, const MultiFab &Tau22, const MultiFab &Tau33, const MultiFab &Tau12, const MultiFab &Tau13, const MultiFab &Tau23, const MultiFab &cons_in, MultiFab &eddyViscosity, MultiFab &Hfx1, MultiFab &Hfx2, MultiFab &Hfx3, MultiFab &Diss, const Geometry &geom, const MultiFab &mapfac_u, const MultiFab &mapfac_v, const std::unique_ptr< MultiFab > &z_phys_nd, const SolverChoice &solverChoice, std::unique_ptr< ABLMost > &most, const bool &exp_most, const bool &use_moisture, int level, const BCRec *bc_ptr, bool vert_only)
Definition: ERF_ComputeTurbulentViscosity.cpp:436
void ComputeTurbulentViscosityLES(const MultiFab &Tau11, const MultiFab &Tau22, const MultiFab &Tau33, const MultiFab &Tau12, const MultiFab &Tau13, const MultiFab &Tau23, const MultiFab &cons_in, MultiFab &eddyViscosity, MultiFab &Hfx1, MultiFab &Hfx2, MultiFab &Hfx3, MultiFab &Diss, const Geometry &geom, const MultiFab &mapfac_u, const MultiFab &mapfac_v, const std::unique_ptr< MultiFab > &z_phys_nd, const TurbChoice &turbChoice, const Real const_grav, std::unique_ptr< ABLMost > &most, const bool &exp_most)
Definition: ERF_ComputeTurbulentViscosity.cpp:32
@ xvel
Definition: ERF_IndexDefines.H:130
@ yvel
Definition: ERF_IndexDefines.H:131
int RhoQr_comp
Definition: ERF_DataStruct.H:687
amrex::Real gravity
Definition: ERF_DataStruct.H:617
int RhoQc_comp
Definition: ERF_DataStruct.H:681
int RhoQv_comp
Definition: ERF_DataStruct.H:680
amrex::Vector< TurbChoice > turbChoice
Definition: ERF_DataStruct.H:581
Definition: ERF_TurbStruct.H:31
PBLType pbl_type
Definition: ERF_TurbStruct.H:201
LESType les_type
Definition: ERF_TurbStruct.H:175

Referenced by ERF::advance_dycore().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ComputeTurbulentViscosityLES()

void ComputeTurbulentViscosityLES ( const MultiFab &  Tau11,
const MultiFab &  Tau22,
const MultiFab &  Tau33,
const MultiFab &  Tau12,
const MultiFab &  Tau13,
const MultiFab &  Tau23,
const MultiFab &  cons_in,
MultiFab &  eddyViscosity,
MultiFab &  Hfx1,
MultiFab &  Hfx2,
MultiFab &  Hfx3,
MultiFab &  Diss,
const Geometry &  geom,
const MultiFab &  mapfac_u,
const MultiFab &  mapfac_v,
const std::unique_ptr< MultiFab > &  z_phys_nd,
const TurbChoice turbChoice,
const Real  const_grav,
std::unique_ptr< ABLMost > &  most,
const bool &  exp_most 
)

Function for computing the turbulent viscosity with LES.

Parameters
[in]Tau1111 strain
[in]Tau2222 strain
[in]Tau3333 strain
[in]Tau1212 strain
[in]Tau1313 strain
[in]Tau2323 strain
[in]cons_incell center conserved quantities
[out]eddyViscosityturbulent viscosity
[in]Hfx1heat flux in x-dir
[in]Hfx2heat flux in y-dir
[in]Hfx3heat flux in z-dir
[in]Dissdissipation of turbulent kinetic energy
[in]geomproblem geometry
[in]mapfac_umap factor at x-face
[in]mapfac_vmap factor at y-face
[in]turbChoicecontainer with turbulence parameters
41 {
42  const GpuArray<Real, AMREX_SPACEDIM> cellSizeInv = geom.InvCellSizeArray();
43  const Box& domain = geom.Domain();
44  const int& klo = domain.smallEnd(2);
45  const bool use_most = (most != nullptr);
46  const bool use_terrain = (z_phys_nd != nullptr);
47 
48  Real inv_Pr_t = turbChoice.Pr_t_inv;
49  Real inv_Sc_t = turbChoice.Sc_t_inv;
50  Real inv_sigma_k = 1.0 / turbChoice.sigma_k;
51 
52  // SMAGORINSKY: Fill Kturb for momentum in horizontal and vertical
53  //***********************************************************************************
54  if (turbChoice.les_type == LESType::Smagorinsky)
55  {
56  Real Cs = turbChoice.Cs;
57 
58 #ifdef _OPENMP
59 #pragma omp parallel if (Gpu::notInLaunchRegion())
60 #endif
61  for (MFIter mfi(eddyViscosity,TilingIfNotGPU()); mfi.isValid(); ++mfi)
62  {
63  // NOTE: This gets us the lateral ghost cells for lev>0; which
64  // have been filled from FP Two Levels.
65  Box bxcc = mfi.growntilebox(1) & domain;
66 
67  const Array4<Real>& mu_turb = eddyViscosity.array(mfi);
68  const Array4<Real>& hfx_x = Hfx1.array(mfi);
69  const Array4<Real>& hfx_y = Hfx2.array(mfi);
70  const Array4<Real>& hfx_z = Hfx3.array(mfi);
71  const Array4<Real const > &cell_data = cons_in.array(mfi);
72 
73  Array4<Real const> tau11 = Tau11.array(mfi);
74  Array4<Real const> tau22 = Tau22.array(mfi);
75  Array4<Real const> tau33 = Tau33.array(mfi);
76  Array4<Real const> tau12 = Tau12.array(mfi);
77  Array4<Real const> tau13 = Tau13.array(mfi);
78  Array4<Real const> tau23 = Tau23.array(mfi);
79 
80  Array4<Real const> mf_u = mapfac_u.array(mfi);
81  Array4<Real const> mf_v = mapfac_v.array(mfi);
82 
83  Array4<Real const> z_nd_arr = (use_terrain) ? z_phys_nd->const_array(mfi) : Array4<Real const>{};
84 
85  ParallelFor(bxcc, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
86  {
87  Real SmnSmn = ComputeSmnSmn(i,j,k,tau11,tau22,tau33,tau12,tau13,tau23,klo,use_most,exp_most);
88  Real dxInv = cellSizeInv[0];
89  Real dyInv = cellSizeInv[1];
90  Real dzInv = cellSizeInv[2];
91  if (use_terrain) {
92  // the terrain grid is only deformed in z for now
93  dzInv /= Compute_h_zeta_AtCellCenter(i,j,k, cellSizeInv, z_nd_arr);
94  }
95  Real cellVolMsf = 1.0 / (dxInv * mf_u(i,j,0) * dyInv * mf_v(i,j,0) * dzInv);
96  Real DeltaMsf = std::pow(cellVolMsf,1.0/3.0);
97  Real CsDeltaSqrMsf = Cs*Cs*DeltaMsf*DeltaMsf;
98 
99  mu_turb(i, j, k, EddyDiff::Mom_h) = CsDeltaSqrMsf * cell_data(i, j, k, Rho_comp) * std::sqrt(2.0*SmnSmn);
100  mu_turb(i, j, k, EddyDiff::Mom_v) = mu_turb(i, j, k, EddyDiff::Mom_h);
101 
102  // Calculate SFS quantities
103  Real dtheta_dz;
104  if (use_most && k==klo) {
105  if (exp_most) {
106  dtheta_dz = ( cell_data(i,j,k+1,RhoTheta_comp)/cell_data(i,j,k+1,Rho_comp)
107  - cell_data(i,j,k ,RhoTheta_comp)/cell_data(i,j,k ,Rho_comp) )*dzInv;
108  } else {
109  dtheta_dz = 0.5 * (-3 * cell_data(i,j,k ,RhoTheta_comp)
110  / cell_data(i,j,k ,Rho_comp)
111  + 4 * cell_data(i,j,k+1,RhoTheta_comp)
112  / cell_data(i,j,k+1,Rho_comp)
113  - cell_data(i,j,k+2,RhoTheta_comp)
114  / cell_data(i,j,k+2,Rho_comp) ) * dzInv;
115  }
116  } else {
117  dtheta_dz = 0.5 * ( cell_data(i,j,k+1,RhoTheta_comp)/cell_data(i,j,k+1,Rho_comp)
118  - cell_data(i,j,k-1,RhoTheta_comp)/cell_data(i,j,k-1,Rho_comp) )*dzInv;
119  }
120  // - heat flux
121  // (Note: If using ERF_EXPLICIT_MOST_STRESS, the value at k=0 will
122  // be overwritten when BCs are applied)
123  hfx_x(i,j,k) = 0.0;
124  hfx_y(i,j,k) = 0.0;
125  hfx_z(i,j,k) = -inv_Pr_t*mu_turb(i,j,k,EddyDiff::Mom_v) * dtheta_dz; // (rho*w)' theta' [kg m^-2 s^-1 K]
126  });
127  }
128  }
129  // DEARDORFF: Fill Kturb for momentum in horizontal and vertical
130  //***********************************************************************************
131  else if (turbChoice.les_type == LESType::Deardorff)
132  {
133  const Real l_C_k = turbChoice.Ck;
134  const Real l_C_e = turbChoice.Ce;
135  const Real l_C_e_wall = turbChoice.Ce_wall;
136  const Real Ce_lcoeff = amrex::max(0.0, l_C_e - 1.9*l_C_k);
137  const Real l_abs_g = const_grav;
138  const Real l_inv_theta0 = 1.0 / turbChoice.theta_ref;
139 
140 #ifdef _OPENMP
141 #pragma omp parallel if (Gpu::notInLaunchRegion())
142 #endif
143  for ( MFIter mfi(eddyViscosity,TilingIfNotGPU()); mfi.isValid(); ++mfi)
144  {
145  Box bxcc = mfi.tilebox();
146 
147  const Array4<Real>& mu_turb = eddyViscosity.array(mfi);
148  const Array4<Real>& hfx_x = Hfx1.array(mfi);
149  const Array4<Real>& hfx_y = Hfx2.array(mfi);
150  const Array4<Real>& hfx_z = Hfx3.array(mfi);
151  const Array4<Real>& diss = Diss.array(mfi);
152 
153  const Array4<Real const > &cell_data = cons_in.array(mfi);
154 
155  Array4<Real const> mf_u = mapfac_u.array(mfi);
156  Array4<Real const> mf_v = mapfac_v.array(mfi);
157 
158  Array4<Real const> z_nd_arr = (use_terrain) ? z_phys_nd->const_array(mfi) : Array4<Real const>{};
159 
160  ParallelFor(bxcc, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
161  {
162  Real dxInv = cellSizeInv[0];
163  Real dyInv = cellSizeInv[1];
164  Real dzInv = cellSizeInv[2];
165  if (use_terrain) {
166  // the terrain grid is only deformed in z for now
167  dzInv /= Compute_h_zeta_AtCellCenter(i,j,k, cellSizeInv, z_nd_arr);
168  }
169  Real cellVolMsf = 1.0 / (dxInv * mf_u(i,j,0) * dyInv * mf_v(i,j,0) * dzInv);
170  Real DeltaMsf = std::pow(cellVolMsf,1.0/3.0);
171 
172  // Calculate stratification-dependent mixing length (Deardorff 1980)
173  Real eps = std::numeric_limits<Real>::epsilon();
174  Real dtheta_dz;
175  if (use_most && k==klo) {
176  if (exp_most) {
177  dtheta_dz = ( cell_data(i,j,k+1,RhoTheta_comp)/cell_data(i,j,k+1,Rho_comp)
178  - cell_data(i,j,k ,RhoTheta_comp)/cell_data(i,j,k ,Rho_comp) )*dzInv;
179  } else {
180  dtheta_dz = 0.5 * (-3 * cell_data(i,j,k ,RhoTheta_comp)
181  / cell_data(i,j,k ,Rho_comp)
182  + 4 * cell_data(i,j,k+1,RhoTheta_comp)
183  / cell_data(i,j,k+1,Rho_comp)
184  - cell_data(i,j,k+2,RhoTheta_comp)
185  / cell_data(i,j,k+2,Rho_comp) ) * dzInv;
186  }
187  } else {
188  dtheta_dz = 0.5 * ( cell_data(i,j,k+1,RhoTheta_comp)/cell_data(i,j,k+1,Rho_comp)
189  - cell_data(i,j,k-1,RhoTheta_comp)/cell_data(i,j,k-1,Rho_comp) )*dzInv;
190  }
191  Real E = amrex::max(cell_data(i,j,k,RhoKE_comp)/cell_data(i,j,k,Rho_comp),Real(0.0));
192  Real stratification = l_abs_g * dtheta_dz * l_inv_theta0;
193  Real length;
194  if (stratification <= eps) {
195  length = DeltaMsf;
196  } else {
197  length = 0.76 * std::sqrt(E / amrex::max(stratification,eps));
198  // mixing length should be _reduced_ for stable stratification
199  length = amrex::min(length, DeltaMsf);
200  // following WRF, make sure the mixing length isn't too small
201  length = amrex::max(length, 0.001 * DeltaMsf);
202  }
203 
204  // Calculate eddy diffusivities
205  // K = rho * C_k * l * KE^(1/2)
206  mu_turb(i,j,k,EddyDiff::Mom_h) = cell_data(i,j,k,Rho_comp) * l_C_k * length * std::sqrt(E);
207  mu_turb(i,j,k,EddyDiff::Mom_v) = mu_turb(i,j,k,EddyDiff::Mom_h);
208  // KH = (1 + 2*l/delta) * mu_turb
209  mu_turb(i,j,k,EddyDiff::Theta_v) = (1.+2.*length/DeltaMsf) * mu_turb(i,j,k,EddyDiff::Mom_v);
210  // Store lengthscale for TKE source terms
211  mu_turb(i,j,k,EddyDiff::Turb_lengthscale) = length;
212 
213  // Calculate SFS quantities
214  // - dissipation
215  Real Ce;
216  if ((l_C_e_wall > 0) && (k==0)) {
217  Ce = l_C_e_wall;
218  } else {
219  Ce = 1.9*l_C_k + Ce_lcoeff*length / DeltaMsf;
220  }
221  diss(i,j,k) = cell_data(i,j,k,Rho_comp) * Ce * std::pow(E,1.5) / length;
222 
223  // - heat flux
224  // (Note: If using ERF_EXPLICIT_MOST_STRESS, the value at k=0 will
225  // be overwritten when BCs are applied)
226  hfx_x(i,j,k) = 0.0;
227  hfx_y(i,j,k) = 0.0;
228  hfx_z(i,j,k) = -mu_turb(i,j,k,EddyDiff::Theta_v) * dtheta_dz; // (rho*w)' theta' [kg m^-2 s^-1 K]
229  });
230  }
231  }
232 
233  // Extrapolate Kturb in x/y, fill remaining elements (relevant to lev==0)
234  //***********************************************************************************
235  int ngc(1);
236  // EddyDiff mapping : Theta_h KE_h Scalar_h Q_h
237  Vector<Real> Factors = {inv_Pr_t, inv_sigma_k, inv_Sc_t, inv_Sc_t}; // alpha = mu/Pr
238  Gpu::AsyncVector<Real> d_Factors; d_Factors.resize(Factors.size());
239  Gpu::copy(Gpu::hostToDevice, Factors.begin(), Factors.end(), d_Factors.begin());
240  Real* fac_ptr = d_Factors.data();
241 
242  const bool use_KE = ( (turbChoice.les_type == LESType::Deardorff) ||
243  (turbChoice.pbl_type == PBLType::MYNN25) );
244 
245 #ifdef _OPENMP
246 #pragma omp parallel if (Gpu::notInLaunchRegion())
247 #endif
248  for ( MFIter mfi(eddyViscosity,TilingIfNotGPU()); mfi.isValid(); ++mfi)
249  {
250  Box bxcc = mfi.tilebox();
251  Box planex = bxcc; planex.setSmall(0, 1); planex.setBig(0, ngc); planex.grow(1,1);
252  Box planey = bxcc; planey.setSmall(1, 1); planey.setBig(1, ngc); planey.grow(0,1);
253  int i_lo = bxcc.smallEnd(0); int i_hi = bxcc.bigEnd(0);
254  int j_lo = bxcc.smallEnd(1); int j_hi = bxcc.bigEnd(1);
255  bxcc.growLo(0,ngc); bxcc.growHi(0,ngc);
256  bxcc.growLo(1,ngc); bxcc.growHi(1,ngc);
257 
258  const Array4<Real>& mu_turb = eddyViscosity.array(mfi);
259 
260  // Extrapolate outside the domain in lateral directions (planex owns corner cells)
261  if (i_lo == domain.smallEnd(0)) {
262  ParallelFor(planex, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
263  {
264  int lj = amrex::min(amrex::max(j, domain.smallEnd(1)), domain.bigEnd(1));
265  mu_turb(i_lo-i, j, k, EddyDiff::Mom_h) = mu_turb(i_lo, lj, k, EddyDiff::Mom_h);
266  mu_turb(i_lo-i, j, k, EddyDiff::Mom_v) = mu_turb(i_lo, lj, k, EddyDiff::Mom_v);
267  });
268  }
269  if (i_hi == domain.bigEnd(0)) {
270  ParallelFor(planex, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
271  {
272  int lj = amrex::min(amrex::max(j, domain.smallEnd(1)), domain.bigEnd(1));
273  mu_turb(i_hi+i, j, k, EddyDiff::Mom_h) = mu_turb(i_hi, lj, k, EddyDiff::Mom_h);
274  mu_turb(i_hi+i, j, k, EddyDiff::Mom_v) = mu_turb(i_hi, lj, k, EddyDiff::Mom_v);
275  });
276  }
277  if (j_lo == domain.smallEnd(1)) {
278  ParallelFor(planey, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
279  {
280  int li = amrex::min(amrex::max(i, domain.smallEnd(0)), domain.bigEnd(0));
281  mu_turb(i, j_lo-j, k, EddyDiff::Mom_h) = mu_turb(li, j_lo, k, EddyDiff::Mom_h);
282  mu_turb(i, j_lo-j, k, EddyDiff::Mom_v) = mu_turb(li, j_lo, k, EddyDiff::Mom_v);
283  });
284  }
285  if (j_hi == domain.bigEnd(1)) {
286  ParallelFor(planey, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
287  {
288  int li = amrex::min(amrex::max(i, domain.smallEnd(0)), domain.bigEnd(0));
289  mu_turb(i, j_hi+j, k, EddyDiff::Mom_h) = mu_turb(li, j_hi, k, EddyDiff::Mom_h);
290  mu_turb(i, j_hi+j, k, EddyDiff::Mom_v) = mu_turb(li, j_hi, k, EddyDiff::Mom_v);
291  });
292  }
293 
294  // Copy Theta_v component into lateral ghost cells if using Deardorff (populated above)
295  if (use_KE) {
296  if (i_lo == domain.smallEnd(0)) {
297  ParallelFor(planex, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
298  {
299  int lj = amrex::min(amrex::max(j, domain.smallEnd(1)), domain.bigEnd(1));
300  mu_turb(i_lo-i, j, k, EddyDiff::Theta_v) = mu_turb(i_lo, lj, k, EddyDiff::Theta_v);
301  });
302  }
303  if (i_hi == domain.bigEnd(0)) {
304  ParallelFor(planex, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
305  {
306  int lj = amrex::min(amrex::max(j, domain.smallEnd(1)), domain.bigEnd(1));
307  mu_turb(i_hi+i, j, k, EddyDiff::Theta_v) = mu_turb(i_hi, lj, k, EddyDiff::Theta_v);
308  });
309  }
310  if (j_lo == domain.smallEnd(1)) {
311  ParallelFor(planey, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
312  {
313  int li = amrex::min(amrex::max(i, domain.smallEnd(0)), domain.bigEnd(0));
314  mu_turb(i, j_lo-j, k, EddyDiff::Theta_v) = mu_turb(li, j_lo, k, EddyDiff::Theta_v);
315  });
316  }
317  if (j_hi == domain.bigEnd(1)) {
318  ParallelFor(planey, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
319  {
320  int li = amrex::min(amrex::max(i, domain.smallEnd(0)), domain.bigEnd(0));
321  mu_turb(i, j_hi+j, k, EddyDiff::Theta_v) = mu_turb(li, j_hi, k, EddyDiff::Theta_v);
322  });
323  }
324  }
325 
326  for (auto n = 1; n < (EddyDiff::NumDiffs-1)/2; ++n) {
327  int offset = (EddyDiff::NumDiffs-1)/2;
328  switch (n)
329  {
330  case EddyDiff::KE_h:
331  if (use_KE) {
332  ParallelFor(bxcc, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
333  {
334  int indx = n;
335  int indx_v = indx + offset;
336  mu_turb(i,j,k,indx) = mu_turb(i,j,k,EddyDiff::Mom_h) * fac_ptr[indx-1];
337  mu_turb(i,j,k,indx_v) = mu_turb(i,j,k,indx);
338  });
339  }
340  break;
341  default:
342  ParallelFor(bxcc, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
343  {
344  int indx = n;
345  int indx_v = indx + offset;
346 
347  mu_turb(i,j,k,indx) = mu_turb(i,j,k,EddyDiff::Mom_h) * fac_ptr[indx-1];
348 
349  // NOTE: Theta_v has already been set for Deardorff
350  if (!(indx_v == EddyDiff::Theta_v && use_KE)) {
351  mu_turb(i,j,k,indx_v) = mu_turb(i,j,k,indx);
352  }
353  });
354  break;
355  }
356  }
357  }
358 
359  // Fill interior ghost cells and any ghost cells outside a periodic domain
360  //***********************************************************************************
361  eddyViscosity.FillBoundary(geom.periodicity());
362 
363 
364  // Extrapolate top & bottom
365  //***********************************************************************************
366 #ifdef _OPENMP
367 #pragma omp parallel if (Gpu::notInLaunchRegion())
368 #endif
369  for ( MFIter mfi(eddyViscosity,TileNoZ()); mfi.isValid(); ++mfi)
370  {
371  Box bxcc = mfi.tilebox();
372  Box planez = bxcc; planez.setSmall(2, 1); planez.setBig(2, ngc);
373  int k_lo = bxcc.smallEnd(2); int k_hi = bxcc.bigEnd(2);
374  planez.growLo(0,ngc); planez.growHi(0,ngc);
375  planez.growLo(1,ngc); planez.growHi(1,ngc);
376 
377  const Array4<Real>& mu_turb = eddyViscosity.array(mfi);
378 
379  for (auto n = 0; n < (EddyDiff::NumDiffs-1)/2; ++n) {
380  int offset = (EddyDiff::NumDiffs-1)/2;
381  switch (n)
382  {
383  case EddyDiff::KE_h:
384  if (use_KE) {
385  ParallelFor(planez, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
386  {
387  int indx = n;
388  int indx_v = indx + offset;
389  mu_turb(i, j, k_lo-k, indx ) = mu_turb(i, j, k_lo, indx );
390  mu_turb(i, j, k_hi+k, indx ) = mu_turb(i, j, k_hi, indx );
391  mu_turb(i, j, k_lo-k, indx_v) = mu_turb(i, j, k_lo, indx_v);
392  mu_turb(i, j, k_hi+k, indx_v) = mu_turb(i, j, k_hi, indx_v);
393  });
394  }
395  break;
396  default:
397  ParallelFor(planez, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
398  {
399  int indx = n;
400  int indx_v = indx + offset;
401  mu_turb(i, j, k_lo-k, indx ) = mu_turb(i, j, k_lo, indx );
402  mu_turb(i, j, k_hi+k, indx ) = mu_turb(i, j, k_hi, indx );
403  mu_turb(i, j, k_lo-k, indx_v) = mu_turb(i, j, k_lo, indx_v);
404  mu_turb(i, j, k_hi+k, indx_v) = mu_turb(i, j, k_hi, indx_v);
405  });
406  break;
407  }
408  }
409  }
410 }
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeSmnSmn(int &i, int &j, int &k, const amrex::Array4< amrex::Real const > &tau11, const amrex::Array4< amrex::Real const > &tau22, const amrex::Array4< amrex::Real const > &tau33, const amrex::Array4< amrex::Real const > &tau12, const amrex::Array4< amrex::Real const > &tau13, const amrex::Array4< amrex::Real const > &tau23, const int &klo, const bool &use_most, const bool &exp_most)
Definition: ERF_EddyViscosity.H:31
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
#define RhoKE_comp
Definition: ERF_IndexDefines.H:38
AMREX_FORCE_INLINE IntVect offset(const int face_dir, const int normal)
Definition: ERF_ReadBndryPlanes.cpp:28
AMREX_FORCE_INLINE AMREX_GPU_DEVICE amrex::Real Compute_h_zeta_AtCellCenter(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:39
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ Theta_v
Definition: ERF_IndexDefines.H:157
@ Turb_lengthscale
Definition: ERF_IndexDefines.H:161
@ Mom_h
Definition: ERF_IndexDefines.H:151
@ Mom_v
Definition: ERF_IndexDefines.H:156
@ NumDiffs
Definition: ERF_IndexDefines.H:162
@ KE_h
Definition: ERF_IndexDefines.H:153
amrex::Real sigma_k
Definition: ERF_TurbStruct.H:193
amrex::Real Sc_t_inv
Definition: ERF_TurbStruct.H:185
amrex::Real Ck
Definition: ERF_TurbStruct.H:191
amrex::Real Cs
Definition: ERF_TurbStruct.H:177
amrex::Real Pr_t_inv
Definition: ERF_TurbStruct.H:182
amrex::Real Ce_wall
Definition: ERF_TurbStruct.H:189
amrex::Real Ce
Definition: ERF_TurbStruct.H:188
amrex::Real theta_ref
Definition: ERF_TurbStruct.H:195

Referenced by ComputeTurbulentViscosity().

Here is the call graph for this function:
Here is the caller graph for this function: