ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ImplicitDiff_N.cpp File Reference
Include dependency graph for ERF_ImplicitDiff_N.cpp:

Macros

#define INSTANTIATE_IMPLICIT_DIFF_FOR_MOM_LU(STAGDIR)
 

Functions

void ImplicitDiffForStateLU_N (const Box &bx, const Box &domain, const int level, const int n, const double dt_d, const GpuArray< Real, AMREX_SPACEDIM *2 > &bc_neumann_vals, const Array4< Real > &cell_data, const GpuArray< Real, AMREX_SPACEDIM > &cellSizeInv, const Array4< const Real > &scalar_zflux, const Array4< const Real > &mu_turb, const SolverChoice &solverChoice, const BCRec *bc_ptr, const bool use_SurfLayer, const Real implicit_fac, const bool use_mrf_countergradient)
 
template<int stagdir>
void ImplicitDiffForMomLU_N (const Box &bx, const Box &, const int level, const double dt_d, const Array4< const Real > &cell_data, const Array4< Real > &face_data, const Array4< const Real > &tau, const Array4< const Real > &tau_corr, const GpuArray< Real, AMREX_SPACEDIM > &cellSizeInv, const Array4< const Real > &mu_turb, const SolverChoice &solverChoice, const BCRec *bc_ptr, const bool use_SurfLayer, const Real implicit_fac, const bool use_ysu_mom_countergradient)
 

Macro Definition Documentation

◆ INSTANTIATE_IMPLICIT_DIFF_FOR_MOM_LU

#define INSTANTIATE_IMPLICIT_DIFF_FOR_MOM_LU (   STAGDIR)
Value:
template void ImplicitDiffForMomLU_N<STAGDIR> ( \
const Box&, \
const Box&, \
const int, \
const double, \
const Array4<const Real>&, \
const Array4< Real>&, \
const Array4<const Real>&, \
const Array4<const Real>&, \
const GpuArray<Real, AMREX_SPACEDIM>&, \
const Array4<const Real>&, \
const SolverChoice&, \
const BCRec*, \
const bool, \
const Real, \
const bool);
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_DataStruct.H:241

Function Documentation

◆ ImplicitDiffForMomLU_N()

template<int stagdir>
void ImplicitDiffForMomLU_N ( const Box &  bx,
const Box &  ,
const int  level,
const double  dt_d,
const Array4< const Real > &  cell_data,
const Array4< Real > &  face_data,
const Array4< const Real > &  tau,
const Array4< const Real > &  tau_corr,
const GpuArray< Real, AMREX_SPACEDIM > &  cellSizeInv,
const Array4< const Real > &  mu_turb,
const SolverChoice solverChoice,
const BCRec *  bc_ptr,
const bool  use_SurfLayer,
const Real  implicit_fac,
const bool  use_ysu_mom_countergradient 
)

Function for computing the implicit contribution to the vertical diffusion of momentum, with a uniform grid and no terrain.

This function (explicitly instantiated below) handles staggering in x, y, or z through the template parameter, stagdir.

Parameters
[in]bxcell-centered box to loop over
[in]levelAMR level
[in]dt_dtime step
[in]cell_dataconserved cell-centered rho
[in,out]face_dataconserved momentum
[in]taustress contribution to momentum
[in]tau_corrstress contribution to momentum that will be corrected by the implicit solve
[in]cellSizeInvinverse cell size array
[in]mu_turbturbulent viscosity
[in]solverChoicecontainer of parameters
[in]bc_ptrcontainer with boundary conditions
[in]use_SurfLayerwhether we have turned on subgrid diffusion
[in]implicit_facif 1 then fully implicit; if 0 then fully explicit
[in]use_ysu_mom_countergradientwhether to include YSU momentum countergradient correction
246 {
247  BL_PROFILE_VAR("ImplicitDiffForMom_N()",ImplicitDiffForMom_N);
248 
249  Real dt = static_cast<Real>(dt_d);
250 
251  // setup quantities for getRhoAlphaAtFaces()
252  DiffChoice dc = solverChoice.diffChoice;
253  TurbChoice tc = solverChoice.turbChoice[level];
254  bool l_consA = (dc.molec_diff_type == MolecDiffType::ConstantAlpha);
255  bool l_turb = tc.use_kturb;
256  // The off-diagonal correction strains for u/v contain a factor of 1/2,
257  // while the diagonal correction strain for w does not.
258  constexpr Real molec_fac = (stagdir == 2) ? two : one;
259  Real mu_eff = (l_consA) ? molec_fac * dc.dynamic_viscosity / dc.rho0_trans
260  : molec_fac * dc.dynamic_viscosity;
261 
262  // g(S*) coefficient
263  // stagdir==0: tau_corr = myhalf * du/dz * mu_tot
264  // stagdir==1: tau_corr = myhalf * dv/dz * mu_tot
265  // stagdir==2: tau_corr = dw/dz * mu_tot
266  constexpr Real gfac = (stagdir == 2) ? two/three : one;
267 
268  // offsets used to average to faces
269  constexpr int ioff = (stagdir == 0) ? 1 : 0;
270  constexpr int joff = (stagdir == 1) ? 1 : 0;
271 
272  // Box bounds
273  int ilo = bx.smallEnd(0);
274  int ihi = bx.bigEnd(0);
275  int jlo = bx.smallEnd(1);
276  int jhi = bx.bigEnd(1);
277  int klo = bx.smallEnd(2);
278  int khi = bx.bigEnd(2);
279  amrex::ignore_unused(ilo, ihi, jlo, jhi);
280 
281  // Temporary FABs for tridiagonal solve (allocated on column)
282  // A[k] * x[k-1] + B[k] * x[k] + C[k+1] = RHS[k]
283  amrex::FArrayBox RHS_fab, soln_fab, coeffG_fab;
284  RHS_fab.resize(bx,1, amrex::The_Async_Arena());
285  soln_fab.resize(bx,1, amrex::The_Async_Arena());
286  coeffG_fab.resize(bx,1, amrex::The_Async_Arena());
287  auto const& RHS_a = RHS_fab.array();
288  auto const& soln_a = soln_fab.array();
289  auto const& coeffG_a = coeffG_fab.array();
290 
291  Real dz_inv = cellSizeInv[2];
292 
293  int bc_comp = BCVars::xvel_bc + stagdir;
294  bool ext_dir_on_zlo = (bc_ptr[bc_comp].lo(2) == ERFBCType::ext_dir ||
295  bc_ptr[bc_comp].lo(2) == ERFBCType::ext_dir_prim);
296  bool ext_dir_on_zhi = (bc_ptr[bc_comp].hi(2) == ERFBCType::ext_dir ||
297  bc_ptr[bc_comp].hi(2) == ERFBCType::ext_dir_prim);
298  bool foextrap_on_zlo = (bc_ptr[bc_comp].lo(2) == ERFBCType::foextrap);
299  bool foextrap_on_zhi = (bc_ptr[bc_comp].hi(2) == ERFBCType::foextrap);
300  amrex::ignore_unused(foextrap_on_zlo,foextrap_on_zhi);
301 
302  AMREX_ASSERT_WITH_MESSAGE(foextrap_on_zlo || ext_dir_on_zlo || use_SurfLayer,
303  "Unexpected lower BC for momentum used with implicit vertical diffusion");
304  AMREX_ASSERT_WITH_MESSAGE(foextrap_on_zhi || ext_dir_on_zhi,
305  "Unexpected upper BC for momentum used with implicit vertical diffusion");
306 
307  Real Fact = implicit_fac * dt * dz_inv;
308 
309 #ifdef AMREX_USE_GPU
310  ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int)
311  {
312 #else
313  for (int j(jlo); j<=jhi; ++j) {
314  for (int i(ilo); i<=ihi; ++i) {
315 #endif
316  // Notes:
317  //
318  // - In DiffusionSrcForMom (e.g., for x-mom)
319  //
320  // Real diffContrib = ...
321  // + (tau13(i,j,k+1) - tau13(i,j,k)) / dzinv
322  // rho_u_rhs(i,j,k) -= diffContrib; // note the negative sign
323  //
324  // - We need to scale the explicit _part_ of `tau13` (for x-mom) by (1 - implicit_fac)
325  // The part that needs to be scaled is stored in `tau_corr`.
326  // E.g., tau13 = 0.5 * (du/dz + dw/dx)
327  // tau13_corr = 0.5 * du/dz
328  //
329  // - The momentum (`face_data`) was set to `S_old + S_rhs * dt`
330  // prior to including "ERF_Implicit.H". Recall that S_rhs includes
331  // sources from advection and other forcings, not just diffusion.
332  //
333  // - To correct momentum, we need to subtract `implicit_fac * diffContrib_corr`
334  // from S_rhs to recover `(1 - implicit_fac) * diffContrib_corr`,
335  // where `diffContrib_corr = -d(tau_corr)/dz`. The negative sign
336  // comes from our convention for the RHS diffusion source.
337  //
338  // Subtracting a negative gives the += below; multiply by dt to
339  // get the intermediate momentum on the RHS of the tridiagonal
340  // system.
341  //
342  // - With a surface_layer BC, tau13/23 holds the vertical flux -d_z(k*u_i)
343  // directly. We must use tau at klo (not tau_corr) with SL BCs.
344  //
345  // - Finally, the terms ~ RHS += (tau_corr_hi - tau_corr_lo) / dz (below)
346  // essentially undo the explicit diffusion update that will be
347  // handled here implicitly.
348 
349  // Bottom boundary coefficients and RHS for L decomp
350  //===================================================
351  Real rhoface, rhoAlpha_lo, rhoAlpha_hi;
352  Real a_tmp, b_tmp, c_tmp, inv_b2_tmp;
353  {
354  rhoface = myhalf * (cell_data(i,j,klo,Rho_comp) + cell_data(i-ioff,j-joff,klo,Rho_comp));
355  getRhoAlphaForFaces(i, j, klo, ioff, joff, rhoAlpha_lo, rhoAlpha_hi,
356  cell_data, mu_turb, mu_eff,
357  l_consA, l_turb);
358 
359  a_tmp = zero;
360  c_tmp = -Fact * gfac * rhoAlpha_hi * dz_inv;
361 
362  RHS_a(i,j,klo) = face_data(i,j,klo); // NOTE: this is momenta; solution is velocity
363 
364  // BCs: Dirichlet (u_i = val), slip wall (w = 0), or surface layer (w = 0)
365  if (ext_dir_on_zlo) {
366  RHS_a(i,j,klo) += Fact * gfac * (tau_corr(i,j,klo+1) - tau_corr(i,j,klo));
367  if (stagdir==2) {
368  c_tmp = zero;
369  RHS_a(i,j,klo) = zero;
370  } else {
371  // NOTE: wall is 1/2 dz away (2 dz_inv)
372  a_tmp = -two * Fact * rhoAlpha_lo * dz_inv;
373  const Real rho_wall = myhalf * ( cell_data(i ,j ,klo-1,Rho_comp)
374  + cell_data(i-ioff,j-joff,klo-1,Rho_comp) );
375  const Real wall_velocity = face_data(i,j,klo-1) / rho_wall;
376  RHS_a(i,j,klo) -= a_tmp * wall_velocity;
377  }
378  } else if (use_SurfLayer) {
379  // NOTE: tau = -mu*d_z(u_i) w/ SL
380  RHS_a(i,j,klo) += Fact * gfac * (tau_corr(i,j,klo+1) - tau(i,j,klo));
381  RHS_a(i,j,klo) += Fact * tau(i,j,klo);
382  } else {
383  // NOTE: FOEXTRAP has zero lower flux (nothing to add to RHS)
384  RHS_a(i,j,klo) += Fact * gfac * (tau_corr(i,j,klo+1) - tau_corr(i,j,klo));
385  }
386 
387  // Add YSU momentum countergradient correction at bottom boundary
388  if (use_ysu_mom_countergradient && stagdir < 2) {
389  const int hgam_comp = (stagdir == 0) ? EddyDiff::HGAMU_v : EddyDiff::HGAMV_v;
390  const Real gam_hi = myhalf * (mu_turb(i,j,klo,hgam_comp) + mu_turb(i,j,klo+1,hgam_comp));
391  RHS_a(i,j,klo) += Fact * gfac * dz_inv * rhoAlpha_hi * gam_hi;
392  }
393 
394  b_tmp = rhoface - a_tmp - c_tmp;
395  inv_b2_tmp = one;
396 
397  RHS_a(i,j,klo) /= b_tmp; // NOTE: this is now "rho"
398  coeffG_a(i,j,klo) = c_tmp / b_tmp; // NOTE: this is now "gamma"
399  }
400 
401  // Build the coefficients and RHS for L decomp
402  //===================================================
403  for (int k(klo+1); k < khi; k++) {
404  rhoface = myhalf * (cell_data(i,j,k,Rho_comp) + cell_data(i-ioff,j-joff,k,Rho_comp));
405  getRhoAlphaForFaces(i, j, k, ioff, joff, rhoAlpha_lo, rhoAlpha_hi,
406  cell_data, mu_turb, mu_eff,
407  l_consA, l_turb);
408 
409  a_tmp = -Fact * rhoAlpha_lo * dz_inv;
410  c_tmp = -Fact * rhoAlpha_hi * dz_inv;
411  b_tmp = rhoface - a_tmp - c_tmp;
412  inv_b2_tmp = one/ (b_tmp - a_tmp * coeffG_a(i,j,k-1));
413 
414  RHS_a(i,j,k) = face_data(i,j,k); // NOTE: this is momenta; solution is velocity
415  RHS_a(i,j,k) += Fact * gfac * (tau_corr(i,j,k+1) - tau_corr(i,j,k));
416 
417  // Add YSU momentum countergradient correction
418  if (use_ysu_mom_countergradient && stagdir < 2) {
419  const int hgam_comp = (stagdir == 0) ? EddyDiff::HGAMU_v : EddyDiff::HGAMV_v;
420  const Real gam_k = mu_turb(i, j, k, hgam_comp);
421  const Real gam_km1 = mu_turb(i, j, k-1, hgam_comp);
422  const Real gam_kp1 = mu_turb(i, j, k+1, hgam_comp);
423  const Real gam_hi = myhalf * (gam_k + gam_kp1);
424  const Real gam_lo = myhalf * (gam_k + gam_km1);
425  RHS_a(i,j,k) += Fact * gfac * dz_inv * (rhoAlpha_hi * gam_hi - rhoAlpha_lo * gam_lo);
426  }
427 
428  RHS_a(i,j,k) = (RHS_a(i,j,k) - a_tmp * RHS_a(i,j,k-1)) * inv_b2_tmp; // NOTE: This is now "rho"
429  coeffG_a(i,j,k) = c_tmp * inv_b2_tmp; // NOTE: this is now "gamma"
430  } // k
431 
432  // Top boundary coefficients and RHS for L decomp
433  //===================================================
434  {
435  rhoface = myhalf * (cell_data(i,j,khi,Rho_comp) + cell_data(i-ioff,j-joff,khi,Rho_comp));
436  getRhoAlphaForFaces(i, j, khi, ioff, joff, rhoAlpha_lo, rhoAlpha_hi,
437  cell_data, mu_turb, mu_eff,
438  l_consA, l_turb);
439 
440  a_tmp = -Fact * gfac * rhoAlpha_lo * dz_inv;
441  c_tmp = zero;
442 
443  RHS_a(i,j,khi) = face_data(i,j,khi); // NOTE: this is momenta; solution is velocity
444  RHS_a(i,j,khi) += Fact * gfac * (tau_corr(i,j,khi+1) - tau_corr(i,j,khi));
445 
446  // BCs: Dirichlet (u_i = val), slip wall (w = 0)
447  if (ext_dir_on_zhi) {
448  if (stagdir==2) {
449  a_tmp = zero;
450  RHS_a(i,j,khi) = zero;
451  } else {
452  // NOTE: wall is 1/2 dz away (2 dz_inv)
453  c_tmp = -two * Fact * rhoAlpha_hi * dz_inv;
454  const Real rho_wall = myhalf * ( cell_data(i ,j ,khi+1,Rho_comp)
455  + cell_data(i-ioff,j-joff,khi+1,Rho_comp) );
456  const Real wall_velocity = face_data(i,j,khi+1) / rho_wall;
457  RHS_a(i,j,khi) -= c_tmp * wall_velocity;
458  }
459  }
460 
461  b_tmp = rhoface - a_tmp - c_tmp;
462  inv_b2_tmp = one/ (b_tmp - a_tmp * coeffG_a(i,j,khi-1));
463 
464  // First solve
465  soln_a(i,j,khi) = (RHS_a(i,j,khi) - a_tmp * RHS_a(i,j,khi-1)) * inv_b2_tmp;
466  }
467 
468  // Back sweep the U decomp solution
469  //===================================================
470  for (int k(khi-1); k>=klo; --k) {
471  soln_a(i,j,k) = RHS_a(i,j,k) - coeffG_a(i,j,k) * soln_a(i,j,k+1);
472  }
473 
474  // Convert back to momenta
475  //===================================================
476  for (int k(klo); k<=khi; ++k) {
477  rhoface = myhalf * (cell_data(i,j,k,Rho_comp) + cell_data(i-ioff,j-joff,k,Rho_comp));
478  face_data(i,j,k) = rhoface * soln_a(i,j,k);
479  }
480 
481 #ifdef AMREX_USE_GPU
482  });
483 #else
484  } // i
485  } // j
486 #endif
487 }
constexpr amrex::Real three
Definition: ERF_Constants.H:11
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void getRhoAlphaForFaces(int i, int j, int k, int ioff, int joff, amrex::Real &rhoAlpha_lo, amrex::Real &rhoAlpha_hi, const amrex::Array4< const amrex::Real > &cell_data, const amrex::Array4< const amrex::Real > &mu_turb, const amrex::Real mu_eff, bool l_consA, bool l_turb)
Definition: ERF_GetRhoAlphaForFaces.H:22
#define Rho_comp
Definition: ERF_IndexDefines.H:36
const int khi
Definition: ERF_InitCustomPert_Bubble.H:21
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);})
AMREX_ASSERT_WITH_MESSAGE(wbar_cutoff_min > wbar_cutoff_max, "ERROR: wbar_cutoff_min < wbar_cutoff_max")
@ xvel_bc
Definition: ERF_IndexDefines.H:102
@ foextrap
Definition: ERF_IndexDefines.H:248
@ ext_dir
Definition: ERF_IndexDefines.H:249
@ ext_dir_prim
Definition: ERF_IndexDefines.H:252
@ HGAMU_v
Definition: ERF_IndexDefines.H:219
@ HGAMV_v
Definition: ERF_IndexDefines.H:220
Definition: ERF_DiffStruct.H:22
MolecDiffType molec_diff_type
Selected molecular transport model.
Definition: ERF_DiffStruct.H:94
amrex::Real dynamic_viscosity
Dynamic viscosity for momentum diffusion [kg/(m-s)].
Definition: ERF_DiffStruct.H:106
amrex::Real rho0_trans
Reference density used to compute dynamic diffusion coefficients [kg/m3].
Definition: ERF_DiffStruct.H:101
amrex::Vector< TurbChoice > turbChoice
Turbulence options for each AMR level.
Definition: ERF_DataStruct.H:1393
DiffChoice diffChoice
Diffusion-related options.
Definition: ERF_DataStruct.H:1390
Definition: ERF_TurbStruct.H:114
bool use_kturb
Whether any turbulence model is active.
Definition: ERF_TurbStruct.H:660
Here is the call graph for this function:

◆ ImplicitDiffForStateLU_N()

void ImplicitDiffForStateLU_N ( const Box &  bx,
const Box &  domain,
const int  level,
const int  n,
const double  dt_d,
const GpuArray< Real, AMREX_SPACEDIM *2 > &  bc_neumann_vals,
const Array4< Real > &  cell_data,
const GpuArray< Real, AMREX_SPACEDIM > &  cellSizeInv,
const Array4< const Real > &  scalar_zflux,
const Array4< const Real > &  mu_turb,
const SolverChoice solverChoice,
const BCRec *  bc_ptr,
const bool  use_SurfLayer,
const Real  implicit_fac,
const bool  use_mrf_countergradient 
)

Function for computing the implicit contribution to the vertical diffusion of theta, with a uniform grid, no terrain, and LU decomposition.

Parameters
[in]bxcell-centered box to loop over
[in]levelAMR level
[in]domainbox of the whole domain
[in]nconserved component index
[in]dt_dtime step
[in]bc_neumann_valsvalues of derivatives if bc_type == Neumann
[in,out]cell_dataconserved cell-centered rho, rho theta
[in]cellSizeInvinverse cell size array
[in]scalar_zfluxscalar vertical flux in z-dir
[in]mu_turbturbulent viscosity
[in]solverChoicecontainer of parameters
[in]bc_ptrcontainer with boundary conditions
[in]use_SurfLayerwhether we have turned on subgrid diffusion
[in]implicit_facif 1 then fully implicit; if 0 then fully explicit
[in]use_mrf_countergradientwhether to include MRF countergradient correction
46 {
47  BL_PROFILE_VAR("ImplicitDiffForState_N()",ImplicitDiffForState_N);
48 
49  Real dt = static_cast<Real>(dt_d);
50 
51  // setup quantities for getRhoAlpha()
52 #include "ERF_SetupVertDiff.H"
53  const int qty_index = n;
54  const int prim_index = qty_index - 1;
55  const int prim_scal_index = (qty_index >= RhoScalar_comp && qty_index < RhoScalar_comp+NSCALARS) ? PrimScalar_comp : prim_index;
56 
57  // Box bounds
58  int ilo = bx.smallEnd(0);
59  int ihi = bx.bigEnd(0);
60  int jlo = bx.smallEnd(1);
61  int jhi = bx.bigEnd(1);
62  int klo = bx.smallEnd(2);
63  int khi = bx.bigEnd(2);
64  amrex::ignore_unused(ilo, ihi, jlo, jhi);
65 
66  // Temporary FABs for tridiagonal solve (allocated on column)
67  // A[k] * x[k-1] + B[k] * x[k] + C[k+1] = RHS[k]
68 
69  // With LU decomposition, M * x = r is written as L * U * x = r with U * x = rho
70  // We then first have L * rho = r and U * x = rho
71  amrex::FArrayBox RHS_fab, soln_fab, coeffG_fab;
72  RHS_fab.resize(bx,1, amrex::The_Async_Arena());
73  soln_fab.resize(bx,1, amrex::The_Async_Arena());
74  coeffG_fab.resize(bx,1, amrex::The_Async_Arena());
75  auto const& RHS_a = RHS_fab.array();
76  auto const& soln_a = soln_fab.array();
77  auto const& coeffG_a = coeffG_fab.array();
78 
79  Real dz_inv = cellSizeInv[2];
80 
81  int bc_comp = qty_index;
82  bool foextrap_on_zlo = (bc_ptr[bc_comp].lo(2) == ERFBCType::foextrap);
83  bool foextrap_on_zhi = (bc_ptr[bc_comp].hi(2) == ERFBCType::foextrap);
84  bool neumann_on_zlo = (bc_ptr[bc_comp].lo(2) == ERFBCType::neumann);
85  bool neumann_on_zhi = (bc_ptr[bc_comp].hi(2) == ERFBCType::neumann);
86  amrex::ignore_unused(foextrap_on_zlo, foextrap_on_zhi);
87 
88  AMREX_ASSERT_WITH_MESSAGE(foextrap_on_zlo || neumann_on_zlo || use_SurfLayer,
89  "Unexpected lower BC for scalars used with implicit vertical diffusion");
90  AMREX_ASSERT_WITH_MESSAGE(foextrap_on_zhi || neumann_on_zhi,
91  "Unexpected upper BC for scalars used with implicit vertical diffusion");
92 
93  Real Fact = implicit_fac * dt * dz_inv;
94 
95 #ifdef AMREX_USE_GPU
96  ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int)
97  {
98 #else
99  for (int j(jlo); j<=jhi; ++j) {
100  for (int i(ilo); i<=ihi; ++i) {
101 #endif
102  // Bottom boundary coefficients and RHS for L decomp
103  //===================================================
104  Real rhoAlpha_lo, rhoAlpha_hi;
105  Real a_tmp, b_tmp, c_tmp, inv_b2_tmp;
106  {
107  getRhoAlpha(i, j, klo, rhoAlpha_lo, rhoAlpha_hi,
108  cell_data, mu_turb, d_alpha_eff, d_eddy_diff_idz,
109  prim_index, prim_scal_index, l_consA, l_turb);
110 
111  a_tmp = zero;
112  c_tmp = -Fact * rhoAlpha_hi * dz_inv;
113  b_tmp = cell_data(i,j,klo,Rho_comp) - a_tmp - c_tmp;
114  inv_b2_tmp = one;
115 
116  RHS_a(i,j,klo) = cell_data(i,j,klo,n); // NOTE: this is rho*phi; solution is phi
117  if (use_SurfLayer && scalar_zflux) {
118  RHS_a(i,j,klo) += Fact * scalar_zflux(i,j,klo); // NOTE: scalar_zflux = -K*d_z(\phi)
119  } else if (neumann_on_zlo) {
120  RHS_a(i,j,klo) += -Fact * rhoAlpha_lo * bc_neumann_vals[2]; // NOTE: N_val = d_z(\phi)
121  }
122 
123  // Add countergradient correction to RHS at bottom boundary
124  // Only upper face contributes (no flux below surface)
125  if (use_mrf_countergradient && (n == RhoTheta_comp || n == RhoQ1_comp)) {
126  const int gam_comp = (n == RhoTheta_comp) ? EddyDiff::HGAMT_v : EddyDiff::HGAMQ_v;
127  const Real gam_hi = myhalf * (mu_turb(i, j, klo, gam_comp) + mu_turb(i, j, klo+1, gam_comp));
128  RHS_a(i,j,klo) -= Fact * rhoAlpha_hi * gam_hi;
129  }
130 
131  RHS_a(i,j,klo) /= b_tmp; // NOTE: this is now "rho"
132  coeffG_a(i,j,klo) = c_tmp / b_tmp; // NOTE: this is now "gamma"
133  }
134 
135  // Build the coefficients and RHS for L decomp
136  //===================================================
137  for (int k(klo+1); k < khi; k++) {
138  getRhoAlpha(i, j, k, rhoAlpha_lo, rhoAlpha_hi,
139  cell_data, mu_turb, d_alpha_eff, d_eddy_diff_idz,
140  prim_index, prim_scal_index, l_consA, l_turb);
141 
142  a_tmp = -Fact * rhoAlpha_lo * dz_inv;
143  c_tmp = -Fact * rhoAlpha_hi * dz_inv;
144  b_tmp = cell_data(i,j,k,Rho_comp) - a_tmp - c_tmp;
145  inv_b2_tmp = one / (b_tmp - a_tmp * coeffG_a(i,j,k-1));
146 
147  RHS_a(i,j,k) = cell_data(i,j,k,n); // NOTE: this is rho*phi; solution is phi
148 
149  // Add countergradient correction to RHS in interior
150  if (use_mrf_countergradient && (n == RhoTheta_comp || n == RhoQ1_comp)) {
151  const int gam_comp = (n == RhoTheta_comp) ? EddyDiff::HGAMT_v : EddyDiff::HGAMQ_v;
152  const Real gam_k = mu_turb(i, j, k, gam_comp);
153  const Real gam_km1 = mu_turb(i, j, k-1, gam_comp);
154  const Real gam_kp1 = mu_turb(i, j, k+1, gam_comp);
155  const Real gam_hi = myhalf * (gam_k + gam_kp1); // at k+½
156  const Real gam_lo = myhalf * (gam_k + gam_km1); // at k-½
157  // Countergradient flux divergence (implicit contribution to RHS):
158  // -Fact * [ρα_{k+½}·γ_{k+½} - ρα_{k-½}·γ_{k-½}]
159  RHS_a(i,j,k) -= Fact * (rhoAlpha_hi * gam_hi - rhoAlpha_lo * gam_lo);
160  }
161 
162  RHS_a(i,j,k) = (RHS_a(i,j,k) - a_tmp * RHS_a(i,j,k-1)) * inv_b2_tmp; // NOTE: This is now "rho"
163  coeffG_a(i,j,k) = c_tmp * inv_b2_tmp; // NOTE: this is now "gamma"
164  } // k
165 
166  // Top boundary coefficients and RHS for L decomp
167  //===================================================
168  {
169  getRhoAlpha(i, j, khi, rhoAlpha_lo, rhoAlpha_hi,
170  cell_data, mu_turb, d_alpha_eff, d_eddy_diff_idz,
171  prim_index, prim_scal_index, l_consA, l_turb);
172 
173  a_tmp = -Fact * rhoAlpha_lo * dz_inv;
174  c_tmp = zero;
175  b_tmp = cell_data(i,j,khi,Rho_comp) - a_tmp - c_tmp;
176  inv_b2_tmp = one / (b_tmp - a_tmp * coeffG_a(i,j,khi-1));
177 
178  RHS_a(i,j,khi) = cell_data(i,j,khi,n); // NOTE: this is rho*phi; solution is phi
179  if (neumann_on_zhi) {
180  RHS_a(i,j,khi) -= -Fact * rhoAlpha_hi * bc_neumann_vals[5]; // NOTE: N_val = d_z(\phi)
181  }
182 
183  // First solve
184  soln_a(i,j,khi) = (RHS_a(i,j,khi) - a_tmp * RHS_a(i,j,khi-1)) * inv_b2_tmp;
185  }
186 
187  // Back sweep the U decomp solution
188  //===================================================
189  for (int k(khi-1); k>=klo; --k) {
190  soln_a(i,j,k) = RHS_a(i,j,k) - coeffG_a(i,j,k) * soln_a(i,j,k+1);
191  }
192 
193  // Convert back to rho*theta
194  //===================================================
195  for (int k(klo); k<=khi; ++k) {
196  cell_data(i,j,k,n) = cell_data(i,j,k,Rho_comp) * soln_a(i,j,k);
197  }
198 
199 #ifdef AMREX_USE_GPU
200  });
201 #else
202  } // i
203  } // j
204 #endif
205 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void getRhoAlpha(int i, int j, int k, amrex::Real &rhoAlpha_lo, amrex::Real &rhoAlpha_hi, const amrex::Array4< const amrex::Real > &cell_data, const amrex::Array4< const amrex::Real > &mu_turb, const amrex::Real *d_alpha_eff, const int *d_eddy_diff_idz, int prim_index, int prim_scal_index, bool l_consA, bool l_turb)
Definition: ERF_GetRhoAlpha.H:20
#define RhoScalar_comp
Definition: ERF_IndexDefines.H:40
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
#define NSCALARS
Definition: ERF_IndexDefines.H:16
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42
#define PrimScalar_comp
Definition: ERF_IndexDefines.H:57
@ neumann
Definition: ERF_IndexDefines.H:254
@ HGAMQ_v
Definition: ERF_IndexDefines.H:218
@ HGAMT_v
Definition: ERF_IndexDefines.H:217
Here is the call graph for this function: