ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ScalarDiffusion.H File Reference
#include <type_traits>
#include "AMReX_Box.H"
#include "AMReX_FArrayBox.H"
#include "AMReX_Gpu.H"
#include "ERF_DiffStruct.H"
#include "ERF_NumericalConstants.H"
#include "ERF_TerrainMetrics.H"
#include "ERF_TerrainImplicitMetric.H"
Include dependency graph for ERF_ScalarDiffusion.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  ScalarDiffusionCoefficients
 
struct  ScalarDiffusionFieldViews
 
struct  ScalarDiffusionCoefficientMode
 
struct  ScalarDiffusionPrescribedFluxes
 
struct  ScalarDiffusionRawFluxDiagnostic
 
struct  ScalarDiffusionSurfaceFaces
 
struct  ScalarDiffusionFluxPolicy
 
struct  StretchedDiffusionBoundaryWeights
 

Functions

template<bool MultiplyMolecularByDensity, bool AddTurbulence>
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFaceCoefficient (const amrex::Array4< const amrex::Real > &rho, const int rho_comp, const amrex::Array4< const amrex::Real > &mu_turb, const ScalarDiffusionCoefficients &coefficients, const int i, const int j, const int k, const int di, const int dj, const int dk, const int eddy_comp) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE StretchedDiffusionBoundaryWeights StretchedDiffusionDirichletWeights (const amrex::Real dz_near, const amrex::Real dz_next) noexcept
 
template<int Direction>
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_N (const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const int i, const int j, const int k, const amrex::Real coeff, const amrex::Real inv_spacing, const amrex::Real map_numerator, const amrex::Real map_denominator, const bool ext_dir_lo, const bool ext_dir_hi) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real StretchedScalarGradient (const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const int i, const int j, const int k, const amrex::Real *dz, const int klo, const int khi, const bool ext_dir_lo, const bool ext_dir_hi) noexcept
 
template<int Direction>
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_S_Horizontal (const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const int i, const int j, const int k, const amrex::Real coeff, const amrex::Real inv_spacing, const amrex::Real face_map) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_Tx (const amrex::Real coeff, const amrex::Real face_map, const amrex::Real grad_xi, const amrex::Real h_xi, const amrex::Real grad_z) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_Ty (const amrex::Real coeff, const amrex::Real face_map, const amrex::Real grad_eta, const amrex::Real h_eta, const amrex::Real grad_z) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtIFace (const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::Real coeff, const int i, const int j, const int k, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &z_cc, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_ux) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtJFace (const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::Real coeff, const int i, const int j, const int k, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &z_cc, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_vy) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtKFace (const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::Real coeff, const int i, const int j, const int kface, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const bool ext_dir_lo, const bool ext_dir_hi) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionGz (const amrex::Real raw_Fz, const amrex::Real mx, const amrex::Real h_xi, const amrex::Real Fbar_x, const amrex::Real my, const amrex::Real h_eta, const amrex::Real Fbar_y) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionMappedTx (const amrex::Real raw_Fx, const amrex::Real h_zeta, const amrex::Real my) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionMappedTy (const amrex::Real raw_Fy, const amrex::Real h_zeta, const amrex::Real mx) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedHorizontalTransfer (const amrex::Real raw_flux, const amrex::Real face_area) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedVerticalTransfer (const amrex::Real raw_flux, const amrex::Real mx, const amrex::Real my) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionGzAtKFace (const int i, const int j, const int kface, const amrex::Box &domain, const amrex::Array4< const amrex::Real > &raw_xflux, const amrex::Array4< const amrex::Real > &raw_yflux, const amrex::Array4< const amrex::Real > &raw_zflux, const int flux_comp, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionMappedTransferAtKFace (const int i, const int j, const int kface, const amrex::Box &domain, const amrex::Array4< const amrex::Real > &raw_xflux, const amrex::Array4< const amrex::Real > &raw_yflux, const amrex::Array4< const amrex::Real > &raw_zflux, const int flux_comp, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my, const bool suppress_transfer=false) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedFluxDivergence (const amrex::Real fx_hi, const amrex::Real fx_lo, const amrex::Real fy_hi, const amrex::Real fy_lo, const amrex::Real fz_hi, const amrex::Real fz_lo, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real dzeta_inv, const amrex::Real mx, const amrex::Real my, const amrex::Real detJ_cell) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionDivergence_T (const amrex::Real mapped_Fx_hi, const amrex::Real mapped_Fx_lo, const amrex::Real mapped_Fy_hi, const amrex::Real mapped_Fy_lo, const amrex::Real Gz_hi, const amrex::Real Gz_lo, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real dz_inv, const amrex::Real mfsq, const amrex::Real detJ_cell) noexcept
 
template<bool MultiplyMolecularByDensity, bool AddTurbulence>
void BuildScalarDiffusionFluxes_N_Impl (const amrex::Box &bx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const ScalarDiffusionFluxPolicy &policy, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &u, const amrex::Array4< const amrex::Real > &v, const amrex::Array4< const amrex::Real > &mf_ux, const amrex::Array4< const amrex::Real > &mf_uy, const amrex::Array4< const amrex::Real > &mf_vx, const amrex::Array4< const amrex::Real > &mf_vy, const amrex::BCRec *bc_ptr, const int bc_comp)
 
void BuildScalarDiffusionFluxes_N (const amrex::Box &bx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const ScalarDiffusionFluxPolicy &policy, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &u, const amrex::Array4< const amrex::Real > &v, const amrex::Array4< const amrex::Real > &mf_ux, const amrex::Array4< const amrex::Real > &mf_uy, const amrex::Array4< const amrex::Real > &mf_vx, const amrex::Array4< const amrex::Real > &mf_vy, const amrex::BCRec *bc_ptr, const int bc_comp)
 
template<bool MultiplyMolecularByDensity, bool AddTurbulence>
void BuildScalarDiffusionFluxes_S_Impl (const amrex::Box &bx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const ScalarDiffusionFluxPolicy &policy, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real *dz, const int klo, const int khi, const amrex::Array4< const amrex::Real > &mf_ux, const amrex::Array4< const amrex::Real > &mf_uy, const amrex::Array4< const amrex::Real > &mf_vx, const amrex::Array4< const amrex::Real > &mf_vy, const amrex::BCRec *bc_ptr, const int bc_comp)
 
void BuildScalarDiffusionFluxes_S (const amrex::Box &bx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const ScalarDiffusionFluxPolicy &policy, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real *dz, const int klo, const int khi, const amrex::Array4< const amrex::Real > &mf_ux, const amrex::Array4< const amrex::Real > &mf_uy, const amrex::Array4< const amrex::Real > &mf_vx, const amrex::Array4< const amrex::Real > &mf_vy, const amrex::BCRec *bc_ptr, const int bc_comp)
 
template<bool MultiplyMolecularByDensity, bool AddTurbulence>
void BuildScalarDiffusionFluxes_T_Impl (const amrex::Box &bx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const ScalarDiffusionFluxPolicy &policy, const bool rotate, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &z_cc, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_ux, const amrex::Array4< const amrex::Real > &mf_vy, const amrex::BCRec *bc_ptr, const int bc_comp)
 
void BuildScalarDiffusionFluxes_T (const amrex::Box &bx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const ScalarDiffusionFluxPolicy &policy, const bool rotate, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &z_cc, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_ux, const amrex::Array4< const amrex::Real > &mf_vy, const amrex::BCRec *bc_ptr, const int bc_comp)
 
void BuildScalarDiffusionMappedTransfers_N (const amrex::Box &bx, const amrex::Array4< const amrex::Real > &raw_x, const int raw_x_comp, const amrex::Array4< const amrex::Real > &raw_y, const int raw_y_comp, const amrex::Array4< const amrex::Real > &raw_z, const int raw_z_comp, const amrex::Array4< amrex::Real > &mapped_x, const int mapped_x_comp, const amrex::Array4< amrex::Real > &mapped_y, const int mapped_y_comp, const amrex::Array4< amrex::Real > &mapped_z, const int mapped_z_comp, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my)
 
void BuildScalarDiffusionMappedTransfers_S (const amrex::Box &bx, const amrex::Array4< const amrex::Real > &raw_x, const int raw_x_comp, const amrex::Array4< const amrex::Real > &raw_y, const int raw_y_comp, const amrex::Array4< const amrex::Real > &raw_z, const int raw_z_comp, const amrex::Array4< amrex::Real > &mapped_x, const int mapped_x_comp, const amrex::Array4< amrex::Real > &mapped_y, const int mapped_y_comp, const amrex::Array4< amrex::Real > &mapped_z, const int mapped_z_comp, const amrex::Array4< const amrex::Real > &ax, const amrex::Array4< const amrex::Real > &ay, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my)
 
void BuildScalarDiffusionMappedTransfers_T (const amrex::Box &bx, const amrex::Box &domain, const amrex::Array4< const amrex::Real > &raw_x, const amrex::Array4< const amrex::Real > &raw_y, const amrex::Array4< const amrex::Real > &raw_z, const int raw_flux_comp, const amrex::Array4< amrex::Real > &mapped_x, const int mapped_x_comp, const amrex::Array4< amrex::Real > &mapped_y, const int mapped_y_comp, const amrex::Array4< amrex::Real > &mapped_z, const int mapped_z_comp, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &ax, const amrex::Array4< const amrex::Real > &ay, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_uy, const amrex::Array4< const amrex::Real > &mf_my, const amrex::Array4< const amrex::Real > &mf_vx, const bool suppress_lower_surface_z_transfer)
 
void ApplyScalarMappedFluxDivergence (const amrex::Box &bx, const amrex::Array4< const amrex::Real > &mapped_x, const int mapped_x_comp, const amrex::Array4< const amrex::Real > &mapped_y, const int mapped_y_comp, const amrex::Array4< const amrex::Real > &mapped_z, const int mapped_z_comp, const amrex::Array4< amrex::Real > &rhs, const int rhs_comp, const amrex::Array4< const amrex::Real > &detJ, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my)
 
void ApplyScalarDiffusionMappedDivergence_T (const amrex::Box &bx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &ax, const amrex::Array4< const amrex::Real > &ay, const amrex::Array4< const amrex::Real > &detJ, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_uy, const amrex::Array4< const amrex::Real > &mf_my, const amrex::Array4< const amrex::Real > &mf_vx, const bool suppress_lower_surface_z_flux)
 
void ApplyScalarDiffusionFluxDivergence_N (const amrex::Box &bx, const amrex::Array4< const amrex::Real > &xflux, const amrex::Array4< const amrex::Real > &yflux, const amrex::Array4< const amrex::Real > &raw_Fz, const int flux_comp, const amrex::Array4< amrex::Real > &rhs, const int rhs_comp, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my)
 
void ApplyScalarDiffusionFluxDivergence_S (const amrex::Box &bx, const amrex::Array4< const amrex::Real > &xflux, const amrex::Array4< const amrex::Real > &yflux, const amrex::Array4< const amrex::Real > &raw_Fz, const int flux_comp, const amrex::Array4< amrex::Real > &rhs, const int rhs_comp, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real *dz)
 
template<bool MultiplyMolecularByDensity, bool AddTurbulence>
void SubtractTerrainMetricImplicitPart_T_Impl (const amrex::Box &zbx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const ScalarDiffusionCoefficients &coefficients, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my, const amrex::Real implicit_fac)
 
void SubtractTerrainMetricImplicitPart_T (const amrex::Box &bx, const amrex::Box &domain, const ScalarDiffusionFieldViews &field, const ScalarDiffusionFluxPolicy &policy, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my, const amrex::Real implicit_fac)
 
void ScaleScalarDiffusionVerticalFlux (const amrex::Box &zbx, const amrex::Array4< amrex::Real > &raw_Fz, const int flux_comp, const amrex::Real explicit_fac)
 

Function Documentation

◆ ApplyScalarDiffusionFluxDivergence_N()

void ApplyScalarDiffusionFluxDivergence_N ( const amrex::Box &  bx,
const amrex::Array4< const amrex::Real > &  xflux,
const amrex::Array4< const amrex::Real > &  yflux,
const amrex::Array4< const amrex::Real > &  raw_Fz,
const int  flux_comp,
const amrex::Array4< amrex::Real > &  rhs,
const int  rhs_comp,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my 
)
inline

Apply the conservative N-grid divergence to a separately selected RHS component. Face scratch is component-selected independently in each view.

1432 {
1433  const amrex::Real dx_inv = cellSizeInv[0];
1434  const amrex::Real dy_inv = cellSizeInv[1];
1435  const amrex::Real dz_inv = cellSizeInv[2];
1436  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1437  const amrex::Real mfsq = mf_mx(i, j, 0) * mf_my(i, j, 0);
1438  rhs(i, j, k, rhs_comp) -=
1439  (xflux(i + 1, j, k, flux_comp) - xflux(i, j, k, flux_comp)) * dx_inv *
1440  mfsq +
1441  (yflux(i, j + 1, k, flux_comp) - yflux(i, j, k, flux_comp)) * dy_inv *
1442  mfsq +
1443  (raw_Fz(i, j, k + 1, flux_comp) - raw_Fz(i, j, k, flux_comp)) * dz_inv;
1444  });
1445 }
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::Real Real
Definition: ERF_ShocInterface.H:19

Referenced by DiffusionSrcForState_N().

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

◆ ApplyScalarDiffusionFluxDivergence_S()

void ApplyScalarDiffusionFluxDivergence_S ( const amrex::Box &  bx,
const amrex::Array4< const amrex::Real > &  xflux,
const amrex::Array4< const amrex::Real > &  yflux,
const amrex::Array4< const amrex::Real > &  raw_Fz,
const int  flux_comp,
const amrex::Array4< amrex::Real > &  rhs,
const int  rhs_comp,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my,
const amrex::Real  dx_inv,
const amrex::Real  dy_inv,
const amrex::Real *  dz 
)
inline

S-grid conservative divergence; vertical cell width is the receiver's dz[k].

1463 {
1464  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1465  const amrex::Real mfsq = mf_mx(i, j, 0) * mf_my(i, j, 0);
1466  const amrex::Real dzk_inv = amrex::Real(1.0) / dz[k];
1467  const amrex::Real stateContrib =
1468  (xflux(i + 1, j, k, flux_comp) - xflux(i, j, k, flux_comp)) * dx_inv *
1469  mfsq +
1470  (yflux(i, j + 1, k, flux_comp) - yflux(i, j, k, flux_comp)) * dy_inv *
1471  mfsq +
1472  (raw_Fz(i, j, k + 1, flux_comp) - raw_Fz(i, j, k, flux_comp)) * dzk_inv;
1473  rhs(i, j, k, rhs_comp) -= stateContrib;
1474  });
1475 }
@ dz
Definition: ERF_AdvanceWDM6.cpp:272

Referenced by DiffusionSrcForState_S().

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

◆ ApplyScalarDiffusionMappedDivergence_T()

void ApplyScalarDiffusionMappedDivergence_T ( const amrex::Box &  bx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::Array4< const amrex::Real > &  ax,
const amrex::Array4< const amrex::Real > &  ay,
const amrex::Array4< const amrex::Real > &  detJ,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_uy,
const amrex::Array4< const amrex::Real > &  mf_my,
const amrex::Array4< const amrex::Real > &  mf_vx,
const bool  suppress_lower_surface_z_flux 
)
inline

Apply native terrain diffusion in one kernel, mapping each face inline.

1378 {
1379  using namespace amrex;
1380  const auto dom_lo = lbound(domain);
1381  const Real dx_inv = cellSizeInv[0];
1382  const Real dy_inv = cellSizeInv[1];
1383  const Real dz_inv = cellSizeInv[2];
1384  const Array4<const Real> xflux(field.xflux);
1385  const Array4<const Real> yflux(field.yflux);
1386  const Array4<const Real> zflux(field.zflux);
1387  const auto rhs = field.rhs;
1388  const int flux_comp = field.flux_comp;
1389  const int rhs_comp = field.rhs_comp;
1390 
1391  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1392  const Real mapped_Fx_lo = TerrainDiffusionMappedTx(
1393  xflux(i, j, k, flux_comp), ax(i, j, k), mf_uy(i, j, 0));
1394  const Real mapped_Fx_hi = TerrainDiffusionMappedTx(
1395  xflux(i + 1, j, k, flux_comp), ax(i + 1, j, k), mf_uy(i + 1, j, 0));
1396  const Real mapped_Fy_lo = TerrainDiffusionMappedTy(
1397  yflux(i, j, k, flux_comp), ay(i, j, k), mf_vx(i, j, 0));
1398  const Real mapped_Fy_hi = TerrainDiffusionMappedTy(
1399  yflux(i, j + 1, k, flux_comp), ay(i, j + 1, k), mf_vx(i, j + 1, 0));
1400  const Real Gz_lo = (suppress_lower_surface_z_flux && k == dom_lo.z)
1401  ? Real(0.0)
1403  i, j, k, domain, xflux, yflux, zflux, flux_comp,
1404  z_nd, cellSizeInv, mf_mx, mf_my);
1405  const Real Gz_hi = TerrainScalarDiffusionGzAtKFace(
1406  i, j, k + 1, domain, xflux, yflux, zflux, flux_comp, z_nd, cellSizeInv,
1407  mf_mx, mf_my);
1408  const Real mfsq = mf_mx(i, j, 0) * mf_my(i, j, 0);
1409  const Real stateContrib = TerrainDiffusionDivergence_T(
1410  mapped_Fx_hi, mapped_Fx_lo, mapped_Fy_hi, mapped_Fy_lo, Gz_hi, Gz_lo,
1411  dx_inv, dy_inv, dz_inv, mfsq, detJ(i, j, k));
1412  rhs(i, j, k, rhs_comp) -= stateContrib;
1413  });
1414 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionDivergence_T(const amrex::Real mapped_Fx_hi, const amrex::Real mapped_Fx_lo, const amrex::Real mapped_Fy_hi, const amrex::Real mapped_Fy_lo, const amrex::Real Gz_hi, const amrex::Real Gz_lo, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real dz_inv, const amrex::Real mfsq, const amrex::Real detJ_cell) noexcept
Definition: ERF_ScalarDiffusion.H:628
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionMappedTy(const amrex::Real raw_Fy, const amrex::Real h_zeta, const amrex::Real mx) noexcept
Definition: ERF_ScalarDiffusion.H:466
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionGzAtKFace(const int i, const int j, const int kface, const amrex::Box &domain, const amrex::Array4< const amrex::Real > &raw_xflux, const amrex::Array4< const amrex::Real > &raw_yflux, const amrex::Array4< const amrex::Real > &raw_zflux, const int flux_comp, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my) noexcept
Definition: ERF_ScalarDiffusion.H:503
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionMappedTx(const amrex::Real raw_Fx, const amrex::Real h_zeta, const amrex::Real my) noexcept
Definition: ERF_ScalarDiffusion.H:457
Definition: ERF_ConsoleIO.cpp:17
amrex::Array4< amrex::Real > xflux
Definition: ERF_ScalarDiffusion.H:39
amrex::Array4< amrex::Real > rhs
Definition: ERF_ScalarDiffusion.H:43
int rhs_comp
Definition: ERF_ScalarDiffusion.H:44
amrex::Array4< amrex::Real > yflux
Definition: ERF_ScalarDiffusion.H:40
int flux_comp
Definition: ERF_ScalarDiffusion.H:42
amrex::Array4< amrex::Real > zflux
Definition: ERF_ScalarDiffusion.H:41

Referenced by DiffusionSrcForState_T().

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

◆ ApplyScalarMappedFluxDivergence()

void ApplyScalarMappedFluxDivergence ( const amrex::Box &  bx,
const amrex::Array4< const amrex::Real > &  mapped_x,
const int  mapped_x_comp,
const amrex::Array4< const amrex::Real > &  mapped_y,
const int  mapped_y_comp,
const amrex::Array4< const amrex::Real > &  mapped_z,
const int  mapped_z_comp,
const amrex::Array4< amrex::Real > &  rhs,
const int  rhs_comp,
const amrex::Array4< const amrex::Real > &  detJ,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my 
)
inline

Add the divergence of caller-supplied mapped transfers to rhs. Inputs are only the accepted face arrays and the mapped cell geometry; in particular, this operation cannot reconstruct a raw or terrain diffusion candidate. The supplied face arrays and mapped-geometry convention are the same as ApplyScalarAdvectionFluxDivergence. This diffusion operation differs in RHS semantics: it accumulates -divergence into an existing RHS and leaves cells with nonpositive detJ unchanged, whereas advection assigns its output and zeroes such cells.

1343 {
1344  const amrex::Real dx_inv = cellSizeInv[0];
1345  const amrex::Real dy_inv = cellSizeInv[1];
1346  const amrex::Real dzeta_inv = cellSizeInv[2];
1348  bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1349  if (detJ(i, j, k) > amrex::Real(0.0)) {
1350  rhs(i, j, k, rhs_comp) -= ScalarDiffusionMappedFluxDivergence(
1351  mapped_x(i + 1, j, k, mapped_x_comp),
1352  mapped_x(i, j, k, mapped_x_comp),
1353  mapped_y(i, j + 1, k, mapped_y_comp),
1354  mapped_y(i, j, k, mapped_y_comp),
1355  mapped_z(i, j, k + 1, mapped_z_comp),
1356  mapped_z(i, j, k, mapped_z_comp), dx_inv, dy_inv, dzeta_inv,
1357  mf_mx(i, j, 0), mf_my(i, j, 0), detJ(i, j, k));
1358  }
1359  });
1360 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedFluxDivergence(const amrex::Real fx_hi, const amrex::Real fx_lo, const amrex::Real fy_hi, const amrex::Real fy_lo, const amrex::Real fz_hi, const amrex::Real fz_lo, const amrex::Real dx_inv, const amrex::Real dy_inv, const amrex::Real dzeta_inv, const amrex::Real mx, const amrex::Real my, const amrex::Real detJ_cell) noexcept
Definition: ERF_ScalarDiffusion.H:604
Here is the call graph for this function:

◆ BuildScalarDiffusionFluxes_N()

void BuildScalarDiffusionFluxes_N ( const amrex::Box &  bx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const ScalarDiffusionFluxPolicy &  policy,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  u,
const amrex::Array4< const amrex::Real > &  v,
const amrex::Array4< const amrex::Real > &  mf_ux,
const amrex::Array4< const amrex::Real > &  mf_uy,
const amrex::Array4< const amrex::Real > &  mf_vx,
const amrex::Array4< const amrex::Real > &  mf_vy,
const amrex::BCRec *  bc_ptr,
const int  bc_comp 
)
inline

Build all native N-grid face fluxes for any intensive scalar field.

827 {
828  const auto mode = policy.coefficient_mode;
829  if (mode.molecular_is_kinematic) {
830  if (mode.add_turbulence) {
831  BuildScalarDiffusionFluxes_N_Impl<true, true>(
832  bx, domain, field, policy, cellSizeInv, u, v, mf_ux, mf_uy, mf_vx,
833  mf_vy, bc_ptr, bc_comp);
834  } else {
835  BuildScalarDiffusionFluxes_N_Impl<true, false>(
836  bx, domain, field, policy, cellSizeInv, u, v, mf_ux, mf_uy, mf_vx,
837  mf_vy, bc_ptr, bc_comp);
838  }
839  } else if (mode.add_turbulence) {
840  BuildScalarDiffusionFluxes_N_Impl<false, true>(
841  bx, domain, field, policy, cellSizeInv, u, v, mf_ux, mf_uy, mf_vx,
842  mf_vy, bc_ptr, bc_comp);
843  } else {
844  BuildScalarDiffusionFluxes_N_Impl<false, false>(
845  bx, domain, field, policy, cellSizeInv, u, v, mf_ux, mf_uy, mf_vx,
846  mf_vy, bc_ptr, bc_comp);
847  }
848 }
ScalarDiffusionCoefficientMode coefficient_mode
Definition: ERF_ScalarDiffusion.H:94

Referenced by DiffusionSrcForState_N().

Here is the caller graph for this function:

◆ BuildScalarDiffusionFluxes_N_Impl()

template<bool MultiplyMolecularByDensity, bool AddTurbulence>
void BuildScalarDiffusionFluxes_N_Impl ( const amrex::Box &  bx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const ScalarDiffusionFluxPolicy &  policy,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  u,
const amrex::Array4< const amrex::Real > &  v,
const amrex::Array4< const amrex::Real > &  mf_ux,
const amrex::Array4< const amrex::Real > &  mf_uy,
const amrex::Array4< const amrex::Real > &  mf_vx,
const amrex::Array4< const amrex::Real > &  mf_vy,
const amrex::BCRec *  bc_ptr,
const int  bc_comp 
)
inline

Component-explicit N-grid face construction. Boundary-condition selection, map factors, prescribed surface fluxes and raw-flux diagnostics are explicit inputs; this operation does not inspect native conserved-state identity.

670 {
671  using namespace amrex;
672  const auto dom_lo = lbound(domain);
673  const auto dom_hi = ubound(domain);
674  const Box xbx = surroundingNodes(bx, 0);
675  const Box ybx = surroundingNodes(bx, 1);
676  const Box zbx = surroundingNodes(bx, 2);
677  const Real dx_inv = cellSizeInv[0];
678  const Real dy_inv = cellSizeInv[1];
679  const Real dz_inv = cellSizeInv[2];
680  const auto coefficients = policy.coefficients;
681  const auto prescribed = policy.prescribed;
682  const auto diagnostic = policy.diagnostic;
683  const auto surface = policy.surface;
684  const int scalar_comp = field.scalar_comp;
685  const int rho_comp = field.rho_comp;
686  const int flux_comp = field.flux_comp;
687  const auto scalar = field.scalar;
688  const auto density = field.density;
689  const auto mu_turb = field.mu_turb;
690  const auto xflux = field.xflux;
691  const auto yflux = field.yflux;
692  const auto zflux = field.zflux;
693 
694  ParallelFor(xbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
695  const Real coeff = ScalarDiffusionFaceCoefficient<
696  MultiplyMolecularByDensity, AddTurbulence>(
697  density, rho_comp, mu_turb, coefficients, i, j, k, 1, 0, 0,
698  coefficients.eddy_h_comp);
699  const bool ext_lo =
700  ((bc_ptr[bc_comp].lo(0) == ERFBCType::ext_dir) ||
701  (bc_ptr[bc_comp].lo(0) == ERFBCType::ext_dir_prim) ||
702  (bc_ptr[bc_comp].lo(0) == ERFBCType::ext_dir_upwind &&
703  u(dom_lo.x, j, k) >= Real(0.0))) &&
704  i == dom_lo.x;
705  const bool ext_hi =
706  ((bc_ptr[bc_comp].hi(0) == ERFBCType::ext_dir) ||
707  (bc_ptr[bc_comp].hi(0) == ERFBCType::ext_dir_prim) ||
708  (bc_ptr[bc_comp].hi(0) == ERFBCType::ext_dir_upwind &&
709  u(dom_hi.x + 1, j, k) <= Real(0.0))) &&
710  i == dom_hi.x + 1;
711  const bool on_surface =
712  (surface.xlo && i == dom_lo.x) ||
713  (surface.xhi && i == dom_hi.x + 1);
714 
715  if (ext_lo) {
716  xflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<0>(
717  scalar, scalar_comp, i, j, k, coeff, dx_inv,
718  mf_ux(i, j, 0), mf_uy(i, j, 0), true, false);
719  } else if (ext_hi) {
720  xflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<0>(
721  scalar, scalar_comp, i, j, k, coeff, dx_inv,
722  mf_ux(i, j, 0), mf_uy(i, j, 0), false, true);
723  } else if (on_surface && prescribed.use_x_on_side) {
724  xflux(i, j, k, flux_comp) = prescribed.x(i, j, k, prescribed.x_comp);
725  } else {
726  xflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<0>(
727  scalar, scalar_comp, i, j, k, coeff, dx_inv,
728  mf_ux(i, j, 0), mf_uy(i, j, 0), false, false);
729  }
730  });
731 
732  ParallelFor(ybx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
733  const Real coeff = ScalarDiffusionFaceCoefficient<
734  MultiplyMolecularByDensity, AddTurbulence>(
735  density, rho_comp, mu_turb, coefficients, i, j, k, 0, 1, 0,
736  coefficients.eddy_h_comp);
737  const bool ext_lo =
738  ((bc_ptr[bc_comp].lo(1) == ERFBCType::ext_dir) ||
739  (bc_ptr[bc_comp].lo(1) == ERFBCType::ext_dir_prim) ||
740  (bc_ptr[bc_comp].lo(1) == ERFBCType::ext_dir_upwind &&
741  v(i, dom_lo.y, k) >= Real(0.0))) &&
742  j == dom_lo.y;
743  const bool ext_hi =
744  ((bc_ptr[bc_comp].hi(1) == ERFBCType::ext_dir) ||
745  (bc_ptr[bc_comp].hi(1) == ERFBCType::ext_dir_prim) ||
746  (bc_ptr[bc_comp].hi(1) == ERFBCType::ext_dir_upwind &&
747  v(i, dom_hi.y + 1, k) <= Real(0.0))) &&
748  j == dom_hi.y + 1;
749  const bool on_surface =
750  (surface.ylo && j == dom_lo.y) ||
751  (surface.yhi && j == dom_hi.y + 1);
752 
753  if (ext_lo) {
754  yflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<1>(
755  scalar, scalar_comp, i, j, k, coeff, dy_inv,
756  mf_vy(i, j, 0), mf_vx(i, j, 0), true, false);
757  } else if (ext_hi) {
758  yflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<1>(
759  scalar, scalar_comp, i, j, k, coeff, dy_inv,
760  mf_vy(i, j, 0), mf_vx(i, j, 0), false, true);
761  } else if (on_surface && prescribed.use_y_on_side) {
762  yflux(i, j, k, flux_comp) = prescribed.y(i, j, k, prescribed.y_comp);
763  } else {
764  yflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<1>(
765  scalar, scalar_comp, i, j, k, coeff, dy_inv,
766  mf_vy(i, j, 0), mf_vx(i, j, 0), false, false);
767  }
768  });
769 
770  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
771  const Real coeff = ScalarDiffusionFaceCoefficient<
772  MultiplyMolecularByDensity, AddTurbulence>(
773  density, rho_comp, mu_turb, coefficients, i, j, k, 0, 0, 1,
774  coefficients.eddy_v_comp);
775  const bool ext_lo =
776  ((bc_ptr[bc_comp].lo(2) == ERFBCType::ext_dir) ||
777  (bc_ptr[bc_comp].lo(2) == ERFBCType::ext_dir_prim)) &&
778  k == dom_lo.z;
779  const bool ext_hi =
780  ((bc_ptr[bc_comp].hi(2) == ERFBCType::ext_dir) ||
781  (bc_ptr[bc_comp].hi(2) == ERFBCType::ext_dir_prim)) &&
782  k == dom_hi.z + 1;
783  const bool on_surface =
784  (surface.zlo && k == dom_lo.z) ||
785  (surface.zhi && k == dom_hi.z + 1);
786 
787  if (ext_lo) {
788  zflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<2>(
789  scalar, scalar_comp, i, j, k, coeff, dz_inv, Real(1.0), Real(1.0),
790  true, false);
791  } else if (ext_hi) {
792  zflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<2>(
793  scalar, scalar_comp, i, j, k, coeff, dz_inv, Real(1.0), Real(1.0),
794  false, true);
795  } else if (on_surface && prescribed.use_z_on_side) {
796  zflux(i, j, k, flux_comp) = prescribed.z(i, j, k, prescribed.z_comp);
797  } else if (on_surface) {
798  zflux(i, j, k, flux_comp) = Real(0.0);
799  } else {
800  zflux(i, j, k, flux_comp) = ScalarDiffusionFlux_N<2>(
801  scalar, scalar_comp, i, j, k, coeff, dz_inv, Real(1.0), Real(1.0),
802  false, false);
803  }
804 
805  if (diagnostic.enabled && (diagnostic.write_on_surface || !on_surface)) {
806  diagnostic.z(i, j, k, diagnostic.z_comp) = zflux(i, j, k, flux_comp);
807  }
808  });
809 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFaceCoefficient(const amrex::Array4< const amrex::Real > &rho, const int rho_comp, const amrex::Array4< const amrex::Real > &mu_turb, const ScalarDiffusionCoefficients &coefficients, const int i, const int j, const int k, const int di, const int dj, const int dk, const int eddy_comp) noexcept
Definition: ERF_ScalarDiffusion.H:113
@ ext_dir
Definition: ERF_IndexDefines.H:300
@ ext_dir_prim
Definition: ERF_IndexDefines.H:303
@ ext_dir_upwind
Definition: ERF_IndexDefines.H:308
int rho_comp
Definition: ERF_ScalarDiffusion.H:37
amrex::Array4< const amrex::Real > scalar
Definition: ERF_ScalarDiffusion.H:34
amrex::Array4< const amrex::Real > density
Definition: ERF_ScalarDiffusion.H:36
int scalar_comp
Definition: ERF_ScalarDiffusion.H:35
amrex::Array4< const amrex::Real > mu_turb
Definition: ERF_ScalarDiffusion.H:38
ScalarDiffusionRawFluxDiagnostic diagnostic
Definition: ERF_ScalarDiffusion.H:96
ScalarDiffusionPrescribedFluxes prescribed
Definition: ERF_ScalarDiffusion.H:95
ScalarDiffusionSurfaceFaces surface
Definition: ERF_ScalarDiffusion.H:97
ScalarDiffusionCoefficients coefficients
Definition: ERF_ScalarDiffusion.H:93
Here is the call graph for this function:

◆ BuildScalarDiffusionFluxes_S()

void BuildScalarDiffusionFluxes_S ( const amrex::Box &  bx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const ScalarDiffusionFluxPolicy &  policy,
const amrex::Real  dx_inv,
const amrex::Real  dy_inv,
const amrex::Real *  dz,
const int  klo,
const int  khi,
const amrex::Array4< const amrex::Real > &  mf_ux,
const amrex::Array4< const amrex::Real > &  mf_uy,
const amrex::Array4< const amrex::Real > &  mf_vx,
const amrex::Array4< const amrex::Real > &  mf_vy,
const amrex::BCRec *  bc_ptr,
const int  bc_comp 
)
inline

Build and map-adjust all native S-grid face fluxes for an intensive field.

979 {
980  const auto mode = policy.coefficient_mode;
981  if (mode.molecular_is_kinematic) {
982  if (mode.add_turbulence) {
983  BuildScalarDiffusionFluxes_S_Impl<true, true>(
984  bx, domain, field, policy, dx_inv, dy_inv, dz, klo, khi, mf_ux,
985  mf_uy, mf_vx, mf_vy, bc_ptr, bc_comp);
986  } else {
987  BuildScalarDiffusionFluxes_S_Impl<true, false>(
988  bx, domain, field, policy, dx_inv, dy_inv, dz, klo, khi, mf_ux,
989  mf_uy, mf_vx, mf_vy, bc_ptr, bc_comp);
990  }
991  } else if (mode.add_turbulence) {
992  BuildScalarDiffusionFluxes_S_Impl<false, true>(
993  bx, domain, field, policy, dx_inv, dy_inv, dz, klo, khi, mf_ux,
994  mf_uy, mf_vx, mf_vy, bc_ptr, bc_comp);
995  } else {
996  BuildScalarDiffusionFluxes_S_Impl<false, false>(
997  bx, domain, field, policy, dx_inv, dy_inv, dz, klo, khi, mf_ux,
998  mf_uy, mf_vx, mf_vy, bc_ptr, bc_comp);
999  }
1000 }
const int klo
Definition: ERF_InitCustomPert_ABL.H:75
const int khi
Definition: ERF_InitCustomPert_Bubble.H:21

Referenced by DiffusionSrcForState_S().

Here is the caller graph for this function:

◆ BuildScalarDiffusionFluxes_S_Impl()

template<bool MultiplyMolecularByDensity, bool AddTurbulence>
void BuildScalarDiffusionFluxes_S_Impl ( const amrex::Box &  bx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const ScalarDiffusionFluxPolicy &  policy,
const amrex::Real  dx_inv,
const amrex::Real  dy_inv,
const amrex::Real *  dz,
const int  klo,
const int  khi,
const amrex::Array4< const amrex::Real > &  mf_ux,
const amrex::Array4< const amrex::Real > &  mf_uy,
const amrex::Array4< const amrex::Real > &  mf_vx,
const amrex::Array4< const amrex::Real > &  mf_vy,
const amrex::BCRec *  bc_ptr,
const int  bc_comp 
)
inline
868 {
869  using namespace amrex;
870  const auto dom_lo = lbound(domain);
871  const auto dom_hi = ubound(domain);
872  const Box xbx = surroundingNodes(bx, 0);
873  const Box ybx = surroundingNodes(bx, 1);
874  const Box zbx = surroundingNodes(bx, 2);
875  const auto coefficients = policy.coefficients;
876  const auto prescribed = policy.prescribed;
877  const auto diagnostic = policy.diagnostic;
878  const auto surface = policy.surface;
879  const int scalar_comp = field.scalar_comp;
880  const int rho_comp = field.rho_comp;
881  const int flux_comp = field.flux_comp;
882  const auto scalar = field.scalar;
883  const auto density = field.density;
884  const auto mu_turb = field.mu_turb;
885  const auto xflux = field.xflux;
886  const auto yflux = field.yflux;
887  const auto zflux = field.zflux;
888 
889  ParallelFor(xbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
890  const Real coeff = ScalarDiffusionFaceCoefficient<
891  MultiplyMolecularByDensity, AddTurbulence>(
892  density, rho_comp, mu_turb, coefficients, i, j, k, 1, 0, 0,
893  coefficients.eddy_h_comp);
894  const bool on_surface =
895  (surface.xlo && i == dom_lo.x) ||
896  (surface.xhi && i == dom_hi.x + 1);
897  if (on_surface && prescribed.use_x_on_side) {
898  xflux(i, j, k, flux_comp) = prescribed.x(i, j, k, prescribed.x_comp);
899  } else {
900  xflux(i, j, k, flux_comp) = ScalarDiffusionFlux_S_Horizontal<0>(
901  scalar, scalar_comp, i, j, k, coeff, dx_inv, mf_ux(i, j, 0));
902  }
903  });
904 
905  ParallelFor(ybx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
906  const Real coeff = ScalarDiffusionFaceCoefficient<
907  MultiplyMolecularByDensity, AddTurbulence>(
908  density, rho_comp, mu_turb, coefficients, i, j, k, 0, 1, 0,
909  coefficients.eddy_h_comp);
910  const bool on_surface =
911  (surface.ylo && j == dom_lo.y) ||
912  (surface.yhi && j == dom_hi.y + 1);
913  if (on_surface && prescribed.use_y_on_side) {
914  yflux(i, j, k, flux_comp) = prescribed.y(i, j, k, prescribed.y_comp);
915  } else {
916  yflux(i, j, k, flux_comp) = ScalarDiffusionFlux_S_Horizontal<1>(
917  scalar, scalar_comp, i, j, k, coeff, dy_inv, mf_vy(i, j, 0));
918  }
919  });
920 
921  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
922  const Real coeff = ScalarDiffusionFaceCoefficient<
923  MultiplyMolecularByDensity, AddTurbulence>(
924  density, rho_comp, mu_turb, coefficients, i, j, k, 0, 0, 1,
925  coefficients.eddy_v_comp);
926  const bool ext_lo =
927  ((bc_ptr[bc_comp].lo(2) == ERFBCType::ext_dir) ||
928  (bc_ptr[bc_comp].lo(2) == ERFBCType::ext_dir_prim)) &&
929  k == dom_lo.z;
930  const bool ext_hi =
931  ((bc_ptr[bc_comp].hi(2) == ERFBCType::ext_dir) ||
932  (bc_ptr[bc_comp].hi(2) == ERFBCType::ext_dir_prim)) &&
933  k == dom_hi.z + 1;
934  const bool on_surface =
935  (surface.zlo && k == dom_lo.z) ||
936  (surface.zhi && k == dom_hi.z + 1);
937  const Real grad = StretchedScalarGradient(
938  scalar, scalar_comp, i, j, k, dz, klo, khi, ext_lo, ext_hi);
939  if (on_surface && prescribed.use_z_on_side) {
940  zflux(i, j, k, flux_comp) = prescribed.z(i, j, k, prescribed.z_comp);
941  } else if (on_surface) {
942  zflux(i, j, k, flux_comp) = Real(0.0);
943  } else {
944  zflux(i, j, k, flux_comp) = -coeff * grad;
945  }
946  if (diagnostic.enabled && (diagnostic.write_on_surface || !on_surface)) {
947  diagnostic.z(i, j, k, diagnostic.z_comp) = zflux(i, j, k, flux_comp);
948  }
949  });
950 
951  // S-grid raw horizontal fluxes are adjusted in the same separate kernels as
952  // the native implementation before scaling or applying divergence.
953  ParallelFor(xbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
954  xflux(i, j, k, flux_comp) /= mf_uy(i, j, 0);
955  });
956  ParallelFor(ybx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
957  yflux(i, j, k, flux_comp) /= mf_vx(i, j, 0);
958  });
959 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real StretchedScalarGradient(const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const int i, const int j, const int k, const amrex::Real *dz, const int klo, const int khi, const bool ext_dir_lo, const bool ext_dir_hi) noexcept
Definition: ERF_ScalarDiffusion.H:238
Here is the call graph for this function:

◆ BuildScalarDiffusionFluxes_T()

void BuildScalarDiffusionFluxes_T ( const amrex::Box &  bx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const ScalarDiffusionFluxPolicy &  policy,
const bool  rotate,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::Array4< const amrex::Real > &  z_cc,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_ux,
const amrex::Array4< const amrex::Real > &  mf_vy,
const amrex::BCRec *  bc_ptr,
const int  bc_comp 
)
inline

Build all native terrain-grid face fluxes, including the grown horizontal face regions needed by the mapped z-face transfer.

1134 {
1135  const auto mode = policy.coefficient_mode;
1136  if (mode.molecular_is_kinematic) {
1137  if (mode.add_turbulence) {
1138  BuildScalarDiffusionFluxes_T_Impl<true, true>(
1139  bx, domain, field, policy, rotate, z_nd, z_cc, cellSizeInv, mf_ux,
1140  mf_vy, bc_ptr, bc_comp);
1141  } else {
1142  BuildScalarDiffusionFluxes_T_Impl<true, false>(
1143  bx, domain, field, policy, rotate, z_nd, z_cc, cellSizeInv, mf_ux,
1144  mf_vy, bc_ptr, bc_comp);
1145  }
1146  } else if (mode.add_turbulence) {
1147  BuildScalarDiffusionFluxes_T_Impl<false, true>(
1148  bx, domain, field, policy, rotate, z_nd, z_cc, cellSizeInv, mf_ux,
1149  mf_vy, bc_ptr, bc_comp);
1150  } else {
1151  BuildScalarDiffusionFluxes_T_Impl<false, false>(
1152  bx, domain, field, policy, rotate, z_nd, z_cc, cellSizeInv, mf_ux,
1153  mf_vy, bc_ptr, bc_comp);
1154  }
1155 }

Referenced by DiffusionSrcForState_T().

Here is the caller graph for this function:

◆ BuildScalarDiffusionFluxes_T_Impl()

template<bool MultiplyMolecularByDensity, bool AddTurbulence>
void BuildScalarDiffusionFluxes_T_Impl ( const amrex::Box &  bx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const ScalarDiffusionFluxPolicy &  policy,
const bool  rotate,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::Array4< const amrex::Real > &  z_cc,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_ux,
const amrex::Array4< const amrex::Real > &  mf_vy,
const amrex::BCRec *  bc_ptr,
const int  bc_comp 
)
inline
1017 {
1018  using namespace amrex;
1019  const auto dom_lo = lbound(domain);
1020  const auto dom_hi = ubound(domain);
1021  Box xbx = surroundingNodes(bx, 0);
1022  Box ybx = surroundingNodes(bx, 1);
1023  const Box zbx = surroundingNodes(bx, 2);
1024  if (xbx.smallEnd(2) != dom_lo.z) xbx.growLo(2, 1);
1025  if (ybx.smallEnd(2) != dom_lo.z) ybx.growLo(2, 1);
1026  if (xbx.bigEnd(2) != dom_hi.z) xbx.growHi(2, 1);
1027  if (ybx.bigEnd(2) != dom_hi.z) ybx.growHi(2, 1);
1028 
1029  const auto coefficients = policy.coefficients;
1030  const auto prescribed = policy.prescribed;
1031  const auto diagnostic = policy.diagnostic;
1032  const auto surface = policy.surface;
1033  const int scalar_comp = field.scalar_comp;
1034  const int rho_comp = field.rho_comp;
1035  const int flux_comp = field.flux_comp;
1036  const auto scalar = field.scalar;
1037  const auto density = field.density;
1038  const auto mu_turb = field.mu_turb;
1039  const auto xflux = field.xflux;
1040  const auto yflux = field.yflux;
1041  const auto zflux = field.zflux;
1042 
1043  ParallelFor(xbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1044  const Real coeff = ScalarDiffusionFaceCoefficient<
1045  MultiplyMolecularByDensity, AddTurbulence>(
1046  density, rho_comp, mu_turb, coefficients, i, j, k, 1, 0, 0,
1047  coefficients.eddy_h_comp);
1048  const bool on_side =
1049  (surface.xlo && i == dom_lo.x) ||
1050  (surface.xhi && i == dom_hi.x + 1);
1051  const bool on_bottom_z =
1052  surface.zlo && rotate && k == dom_lo.z;
1053 
1054  if (on_side && prescribed.use_x_on_side) {
1055  xflux(i, j, k, flux_comp) = prescribed.x(i, j, k, prescribed.x_comp);
1056  } else if (on_bottom_z && prescribed.use_x_on_bottom_z) {
1057  xflux(i, j, k, flux_comp) = prescribed.x(i, j, 0, prescribed.x_comp);
1058  } else {
1059  xflux(i, j, k, flux_comp) = TerrainScalarDiffusionFluxAtIFace(
1060  scalar, scalar_comp, coeff, i, j, k, z_nd, z_cc, cellSizeInv, mf_ux);
1061  }
1062  });
1063 
1064  ParallelFor(ybx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1065  const Real coeff = ScalarDiffusionFaceCoefficient<
1066  MultiplyMolecularByDensity, AddTurbulence>(
1067  density, rho_comp, mu_turb, coefficients, i, j, k, 0, 1, 0,
1068  coefficients.eddy_h_comp);
1069  const bool on_side =
1070  (surface.ylo && j == dom_lo.y) ||
1071  (surface.yhi && j == dom_hi.y + 1);
1072  const bool on_bottom_z =
1073  surface.zlo && rotate && k == dom_lo.z;
1074 
1075  if (on_side && prescribed.use_y_on_side) {
1076  yflux(i, j, k, flux_comp) = prescribed.y(i, j, k, prescribed.y_comp);
1077  } else if (on_bottom_z && prescribed.use_y_on_bottom_z) {
1078  yflux(i, j, k, flux_comp) = prescribed.y(i, j, 0, prescribed.y_comp);
1079  } else {
1080  yflux(i, j, k, flux_comp) = TerrainScalarDiffusionFluxAtJFace(
1081  scalar, scalar_comp, coeff, i, j, k, z_nd, z_cc, cellSizeInv, mf_vy);
1082  }
1083  });
1084 
1085  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1086  const Real coeff = ScalarDiffusionFaceCoefficient<
1087  MultiplyMolecularByDensity, AddTurbulence>(
1088  density, rho_comp, mu_turb, coefficients, i, j, k, 0, 0, 1,
1089  coefficients.eddy_v_comp);
1090  const bool ext_lo =
1091  ((bc_ptr[bc_comp].lo(2) == ERFBCType::ext_dir) ||
1092  (bc_ptr[bc_comp].lo(2) == ERFBCType::ext_dir_prim)) &&
1093  k == dom_lo.z;
1094  const bool ext_hi =
1095  ((bc_ptr[bc_comp].hi(2) == ERFBCType::ext_dir) ||
1096  (bc_ptr[bc_comp].hi(2) == ERFBCType::ext_dir_prim)) &&
1097  k == dom_hi.z + 1;
1098  const bool on_surface =
1099  (surface.zlo && k == dom_lo.z) ||
1100  (surface.zhi && k == dom_hi.z + 1);
1101 
1102  const Real raw_flux = TerrainScalarDiffusionFluxAtKFace(
1103  scalar, scalar_comp, coeff, i, j, k, z_nd, cellSizeInv, ext_lo, ext_hi);
1104 
1105  if (on_surface && prescribed.use_z_on_side) {
1106  zflux(i, j, k, flux_comp) = prescribed.z(i, j, k, prescribed.z_comp);
1107  } else if (on_surface) {
1108  zflux(i, j, k, flux_comp) = Real(0.0);
1109  } else {
1110  zflux(i, j, k, flux_comp) = raw_flux;
1111  }
1112  if (diagnostic.enabled && (diagnostic.write_on_surface || !on_surface)) {
1113  diagnostic.z(i, j, k, diagnostic.z_comp) = zflux(i, j, k, flux_comp);
1114  }
1115  });
1116 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtJFace(const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::Real coeff, const int i, const int j, const int k, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &z_cc, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_vy) noexcept
Definition: ERF_ScalarDiffusion.H:355
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtKFace(const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::Real coeff, const int i, const int j, const int kface, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const bool ext_dir_lo, const bool ext_dir_hi) noexcept
Definition: ERF_ScalarDiffusion.H:389
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtIFace(const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::Real coeff, const int i, const int j, const int k, const amrex::Array4< const amrex::Real > &z_nd, const amrex::Array4< const amrex::Real > &z_cc, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_ux) noexcept
Definition: ERF_ScalarDiffusion.H:325
Here is the call graph for this function:

◆ BuildScalarDiffusionMappedTransfers_N()

void BuildScalarDiffusionMappedTransfers_N ( const amrex::Box &  bx,
const amrex::Array4< const amrex::Real > &  raw_x,
const int  raw_x_comp,
const amrex::Array4< const amrex::Real > &  raw_y,
const int  raw_y_comp,
const amrex::Array4< const amrex::Real > &  raw_z,
const int  raw_z_comp,
const amrex::Array4< amrex::Real > &  mapped_x,
const int  mapped_x_comp,
const amrex::Array4< amrex::Real > &  mapped_y,
const int  mapped_y_comp,
const amrex::Array4< amrex::Real > &  mapped_z,
const int  mapped_z_comp,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my 
)
inline

Materialize the canonical N-grid face transfers. N-grid x/y builder outputs already carry their map-factor ratios; only the vertical flux is divided by the cell-centered horizontal map-factor product.

1179 {
1180  const amrex::Box xbx = amrex::surroundingNodes(bx, 0);
1181  const amrex::Box ybx = amrex::surroundingNodes(bx, 1);
1182  const amrex::Box zbx = amrex::surroundingNodes(bx, 2);
1184  xbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1185  mapped_x(i, j, k, mapped_x_comp) =
1187  raw_x(i, j, k, raw_x_comp), amrex::Real(1.0));
1188  });
1190  ybx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1191  mapped_y(i, j, k, mapped_y_comp) =
1193  raw_y(i, j, k, raw_y_comp), amrex::Real(1.0));
1194  });
1196  zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1197  mapped_z(i, j, k, mapped_z_comp) =
1199  raw_z(i, j, k, raw_z_comp), mf_mx(i, j, 0), mf_my(i, j, 0));
1200  });
1201 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedHorizontalTransfer(const amrex::Real raw_flux, const amrex::Real face_area) noexcept
Definition: ERF_ScalarDiffusion.H:480
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedVerticalTransfer(const amrex::Real raw_flux, const amrex::Real mx, const amrex::Real my) noexcept
Definition: ERF_ScalarDiffusion.H:489
Here is the call graph for this function:

◆ BuildScalarDiffusionMappedTransfers_S()

void BuildScalarDiffusionMappedTransfers_S ( const amrex::Box &  bx,
const amrex::Array4< const amrex::Real > &  raw_x,
const int  raw_x_comp,
const amrex::Array4< const amrex::Real > &  raw_y,
const int  raw_y_comp,
const amrex::Array4< const amrex::Real > &  raw_z,
const int  raw_z_comp,
const amrex::Array4< amrex::Real > &  mapped_x,
const int  mapped_x_comp,
const amrex::Array4< amrex::Real > &  mapped_y,
const int  mapped_y_comp,
const amrex::Array4< amrex::Real > &  mapped_z,
const int  mapped_z_comp,
const amrex::Array4< const amrex::Real > &  ax,
const amrex::Array4< const amrex::Real > &  ay,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my 
)
inline

Materialize the canonical S-grid face transfers. ax/ay restore the side Jacobian measure omitted by the native S-grid divergence; detJ and the computational z spacing are supplied separately to the mapped divergence.

1227 {
1228  const amrex::Box xbx = amrex::surroundingNodes(bx, 0);
1229  const amrex::Box ybx = amrex::surroundingNodes(bx, 1);
1230  const amrex::Box zbx = amrex::surroundingNodes(bx, 2);
1232  xbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1233  mapped_x(i, j, k, mapped_x_comp) =
1235  raw_x(i, j, k, raw_x_comp), ax(i, j, k));
1236  });
1238  ybx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1239  mapped_y(i, j, k, mapped_y_comp) =
1241  raw_y(i, j, k, raw_y_comp), ay(i, j, k));
1242  });
1244  zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1245  mapped_z(i, j, k, mapped_z_comp) =
1247  raw_z(i, j, k, raw_z_comp), mf_mx(i, j, 0), mf_my(i, j, 0));
1248  });
1249 }
Here is the call graph for this function:

◆ BuildScalarDiffusionMappedTransfers_T()

void BuildScalarDiffusionMappedTransfers_T ( const amrex::Box &  bx,
const amrex::Box &  domain,
const amrex::Array4< const amrex::Real > &  raw_x,
const amrex::Array4< const amrex::Real > &  raw_y,
const amrex::Array4< const amrex::Real > &  raw_z,
const int  raw_flux_comp,
const amrex::Array4< amrex::Real > &  mapped_x,
const int  mapped_x_comp,
const amrex::Array4< amrex::Real > &  mapped_y,
const int  mapped_y_comp,
const amrex::Array4< amrex::Real > &  mapped_z,
const int  mapped_z_comp,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::Array4< const amrex::Real > &  ax,
const amrex::Array4< const amrex::Real > &  ay,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_uy,
const amrex::Array4< const amrex::Real > &  mf_my,
const amrex::Array4< const amrex::Real > &  mf_vx,
const bool  suppress_lower_surface_z_transfer 
)
inline

Materialize the canonical terrain-following transfers using ERF's existing face mappings and authoritative Gz construction. The lower suppression switch zeros the complete lower transfer, including terrain cross terms.

Corresponding directional inputs and outputs may alias in place, including the same component. The z transfer is launched first on AMReX's ordered execution stream so it reads raw x/y fluxes before the x/y mapping launches can overwrite them. Cross-direction aliasing is not supported.

For each interior z face mapped from bx, raw_x and raw_y must be valid at both kface and kface-1. Thus, if bx.smallEnd(2) is above the domain bottom, raw_x/raw_y must include bx.smallEnd(2)-1; if bx.bigEnd(2) is below the domain top, they must include bx.bigEnd(2)+1. No outside-domain layer is required at a physical bottom/top face because the Gz helper uses one-sided extrapolation. Raw candidates produced by BuildScalarDiffusionFluxes_T already provide this z coverage.

1292 {
1293  const amrex::Box xbx = amrex::surroundingNodes(bx, 0);
1294  const amrex::Box ybx = amrex::surroundingNodes(bx, 1);
1295  const amrex::Box zbx = amrex::surroundingNodes(bx, 2);
1296  const amrex::Array4<const amrex::Real> xflux(raw_x);
1297  const amrex::Array4<const amrex::Real> yflux(raw_y);
1298  const amrex::Array4<const amrex::Real> zflux(raw_z);
1300  zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1301  const bool suppress = suppress_lower_surface_z_transfer &&
1302  k == domain.smallEnd(2);
1303  mapped_z(i, j, k, mapped_z_comp) =
1305  i, j, k, domain, xflux, yflux, zflux, raw_flux_comp, z_nd,
1306  cellSizeInv, mf_mx, mf_my, suppress);
1307  });
1308  amrex::ParallelFor(xbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1309  mapped_x(i, j, k, mapped_x_comp) = TerrainDiffusionMappedTx(
1310  raw_x(i, j, k, raw_flux_comp), ax(i, j, k), mf_uy(i, j, 0));
1311  });
1312  amrex::ParallelFor(ybx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1313  mapped_y(i, j, k, mapped_y_comp) = TerrainDiffusionMappedTy(
1314  raw_y(i, j, k, raw_flux_comp), ay(i, j, k), mf_vx(i, j, 0));
1315  });
1316 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionMappedTransferAtKFace(const int i, const int j, const int kface, const amrex::Box &domain, const amrex::Array4< const amrex::Real > &raw_xflux, const amrex::Array4< const amrex::Real > &raw_yflux, const amrex::Array4< const amrex::Real > &raw_zflux, const int flux_comp, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my, const bool suppress_transfer=false) noexcept
Definition: ERF_ScalarDiffusion.H:575
Here is the call graph for this function:

◆ ScalarDiffusionFaceCoefficient()

template<bool MultiplyMolecularByDensity, bool AddTurbulence>
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFaceCoefficient ( const amrex::Array4< const amrex::Real > &  rho,
const int  rho_comp,
const amrex::Array4< const amrex::Real > &  mu_turb,
const ScalarDiffusionCoefficients &  coefficients,
const int  i,
const int  j,
const int  k,
const int  di,
const int  dj,
const int  dk,
const int  eddy_comp 
)
noexcept

Density-weighted face transport coefficient. The booleans are compile-time choices for ConstantAlpha/Constant/None and turbulent/no-turbulence modes; turbulent coefficients are already density weighted and are never multiplied by rho here.

rho_comp and the eddy component are independent of the scalar component.

125 {
126  amrex::Real coeff = coefficients.molecular_coeff;
127  if constexpr (MultiplyMolecularByDensity) {
128  coeff *= amrex::Real(0.5) *
129  (rho(i, j, k, rho_comp) + rho(i - di, j - dj, k - dk, rho_comp));
130  }
131  if constexpr (AddTurbulence) {
132  coeff += amrex::Real(0.5) * (mu_turb(i, j, k, eddy_comp) +
133  mu_turb(i - di, j - dj, k - dk, eddy_comp));
134  }
135  return coeff;
136 }
@ rho
Definition: ERF_Kessler.H:25
real(c_double), private di
Definition: ERF_module_mp_morr_two_moment.F90:203
amrex::Real molecular_coeff
Definition: ERF_ScalarDiffusion.H:24

Referenced by BuildScalarDiffusionFluxes_N_Impl(), BuildScalarDiffusionFluxes_S_Impl(), BuildScalarDiffusionFluxes_T_Impl(), and SubtractTerrainMetricImplicitPart_T_Impl().

Here is the caller graph for this function:

◆ ScalarDiffusionFlux_N()

template<int Direction>
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_N ( const amrex::Array4< const amrex::Real > &  scalar,
const int  scalar_comp,
const int  i,
const int  j,
const int  k,
const amrex::Real  coeff,
const amrex::Real  inv_spacing,
const amrex::Real  map_numerator,
const amrex::Real  map_denominator,
const bool  ext_dir_lo,
const bool  ext_dir_hi 
)
noexcept

Compute the existing N-grid signed face flux, F^D=-K grad(chi). scalar_comp selects the intensive scalar and flux_comp is applied by the caller to its independent face-flux view. Horizontal map-factor numerator and denominator remain separate to preserve the native arithmetic association. Physical Dirichlet flags select the legacy one-sided stencil; ext_dir_upwind selection stays in the adapter.

176 {
177  static_assert(Direction >= 0 && Direction < 3);
178  amrex::Real grad;
179  if constexpr (Direction == 0) {
180  if (ext_dir_lo) {
181  grad = -(amrex::Real(8.0) / amrex::Real(3.0)) *
182  scalar(i - 1, j, k, scalar_comp) +
183  amrex::Real(3.0) * scalar(i, j, k, scalar_comp) -
184  (amrex::Real(1.0) / amrex::Real(3.0)) *
185  scalar(i + 1, j, k, scalar_comp);
186  } else if (ext_dir_hi) {
187  grad =
188  (amrex::Real(8.0) / amrex::Real(3.0)) * scalar(i, j, k, scalar_comp) -
189  amrex::Real(3.0) * scalar(i - 1, j, k, scalar_comp) +
190  (amrex::Real(1.0) / amrex::Real(3.0)) *
191  scalar(i - 2, j, k, scalar_comp);
192  } else {
193  grad = scalar(i, j, k, scalar_comp) - scalar(i - 1, j, k, scalar_comp);
194  }
195  } else if constexpr (Direction == 1) {
196  if (ext_dir_lo) {
197  grad = -(amrex::Real(8.0) / amrex::Real(3.0)) *
198  scalar(i, j - 1, k, scalar_comp) +
199  amrex::Real(3.0) * scalar(i, j, k, scalar_comp) -
200  (amrex::Real(1.0) / amrex::Real(3.0)) *
201  scalar(i, j + 1, k, scalar_comp);
202  } else if (ext_dir_hi) {
203  grad =
204  (amrex::Real(8.0) / amrex::Real(3.0)) * scalar(i, j, k, scalar_comp) -
205  amrex::Real(3.0) * scalar(i, j - 1, k, scalar_comp) +
206  (amrex::Real(1.0) / amrex::Real(3.0)) *
207  scalar(i, j - 2, k, scalar_comp);
208  } else {
209  grad = scalar(i, j, k, scalar_comp) - scalar(i, j - 1, k, scalar_comp);
210  }
211  } else {
212  if (ext_dir_lo) {
213  grad = -(amrex::Real(8.0) / amrex::Real(3.0)) *
214  scalar(i, j, k - 1, scalar_comp) +
215  amrex::Real(3.0) * scalar(i, j, k, scalar_comp) -
216  (amrex::Real(1.0) / amrex::Real(3.0)) *
217  scalar(i, j, k + 1, scalar_comp);
218  } else if (ext_dir_hi) {
219  grad =
220  (amrex::Real(8.0) / amrex::Real(3.0)) * scalar(i, j, k, scalar_comp) -
221  amrex::Real(3.0) * scalar(i, j, k - 1, scalar_comp) +
222  (amrex::Real(1.0) / amrex::Real(3.0)) *
223  scalar(i, j, k - 2, scalar_comp);
224  } else {
225  grad = scalar(i, j, k, scalar_comp) - scalar(i, j, k - 1, scalar_comp);
226  }
227  }
228  if constexpr (Direction == 2) {
229  return -coeff * grad * inv_spacing;
230  } else {
231  return -coeff * grad * inv_spacing * map_numerator / map_denominator;
232  }
233 }

◆ ScalarDiffusionFlux_S_Horizontal()

template<int Direction>
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_S_Horizontal ( const amrex::Array4< const amrex::Real > &  scalar,
const int  scalar_comp,
const int  i,
const int  j,
const int  k,
const amrex::Real  coeff,
const amrex::Real  inv_spacing,
const amrex::Real  face_map 
)
noexcept

Existing S-grid horizontal raw flux before its separate map-factor adjustment kernel.

286 {
287  static_assert(Direction == 0 || Direction == 1);
288  const amrex::Real delta =
289  Direction == 0
290  ? scalar(i, j, k, scalar_comp) - scalar(i - 1, j, k, scalar_comp)
291  : scalar(i, j, k, scalar_comp) - scalar(i, j - 1, k, scalar_comp);
292  const amrex::Real gradient = inv_spacing * delta;
293  return -coeff * face_map * gradient;
294 }

◆ ScalarDiffusionFlux_Tx()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_Tx ( const amrex::Real  coeff,
const amrex::Real  face_map,
const amrex::Real  grad_xi,
const amrex::Real  h_xi,
const amrex::Real  grad_z 
)
noexcept
303 {
304  return -coeff * face_map * (grad_xi - h_xi * grad_z);
305 }

Referenced by TerrainScalarDiffusionFluxAtIFace().

Here is the caller graph for this function:

◆ ScalarDiffusionFlux_Ty()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_Ty ( const amrex::Real  coeff,
const amrex::Real  face_map,
const amrex::Real  grad_eta,
const amrex::Real  h_eta,
const amrex::Real  grad_z 
)
noexcept
314 {
315  return -coeff * face_map * (grad_eta - h_eta * grad_z);
316 }

Referenced by TerrainScalarDiffusionFluxAtJFace().

Here is the caller graph for this function:

◆ ScalarDiffusionMappedFluxDivergence()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedFluxDivergence ( const amrex::Real  fx_hi,
const amrex::Real  fx_lo,
const amrex::Real  fy_hi,
const amrex::Real  fy_lo,
const amrex::Real  fz_hi,
const amrex::Real  fz_lo,
const amrex::Real  dx_inv,
const amrex::Real  dy_inv,
const amrex::Real  dzeta_inv,
const amrex::Real  mx,
const amrex::Real  my,
const amrex::Real  detJ_cell 
)
noexcept

Return the positive geometry-weighted mapped flux divergence. For detJ_cell <= 0, return zero without dividing. The diffusion array wrapper subtracts this value from the existing RHS.

617 {
618  if (detJ_cell <= amrex::Real(0.0))
619  return amrex::Real(0.0);
620  const amrex::Real map_over_jacobian = (mx * my) / detJ_cell;
621  return map_over_jacobian *
622  ((fx_hi - fx_lo) * dx_inv + (fy_hi - fy_lo) * dy_inv +
623  (fz_hi - fz_lo) * dzeta_inv);
624 }

Referenced by ApplyScalarMappedFluxDivergence().

Here is the caller graph for this function:

◆ ScalarDiffusionMappedHorizontalTransfer()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedHorizontalTransfer ( const amrex::Real  raw_flux,
const amrex::Real  face_area 
)
noexcept

Pointwise conversion to ERF's mapped conservative face-transfer convention. The transfer is an instantaneous rate and includes the supplied face-area measure; callers must not apply that measure again in the divergence.

483 {
484  return raw_flux * face_area;
485 }

Referenced by BuildScalarDiffusionMappedTransfers_N(), and BuildScalarDiffusionMappedTransfers_S().

Here is the caller graph for this function:

◆ ScalarDiffusionMappedVerticalTransfer()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionMappedVerticalTransfer ( const amrex::Real  raw_flux,
const amrex::Real  mx,
const amrex::Real  my 
)
noexcept

Convert a raw vertical diffusion flux to the mapped face-transfer space.

493 {
494  return raw_flux / (mx * my);
495 }

Referenced by BuildScalarDiffusionMappedTransfers_N(), BuildScalarDiffusionMappedTransfers_S(), and TerrainScalarDiffusionMappedTransferAtKFace().

Here is the caller graph for this function:

◆ ScaleScalarDiffusionVerticalFlux()

void ScaleScalarDiffusionVerticalFlux ( const amrex::Box &  zbx,
const amrex::Array4< amrex::Real > &  raw_Fz,
const int  flux_comp,
const amrex::Real  explicit_fac 
)
inline

Scale only raw F_z for the explicit integration fraction.

1563 {
1564  amrex::ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1565  raw_Fz(i, j, k, flux_comp) *= explicit_fac;
1566  });
1567 }

Referenced by DiffusionSrcForState_N(), DiffusionSrcForState_S(), and DiffusionSrcForState_T().

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

◆ StretchedDiffusionDirichletWeights()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE StretchedDiffusionBoundaryWeights StretchedDiffusionDirichletWeights ( const amrex::Real  dz_near,
const amrex::Real  dz_next 
)
noexcept
147 {
148  const amrex::Real f = dz_next / dz_near + amrex::Real(2.0);
149  const amrex::Real f2 = f * f;
150  const amrex::Real c3 = amrex::Real(2.0) / (f - f2);
151  return {-(amrex::Real(1.0) - f2) * c3, -f2 * c3, c3};
152 }

Referenced by StretchedScalarGradient().

Here is the caller graph for this function:

◆ StretchedScalarGradient()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real StretchedScalarGradient ( const amrex::Array4< const amrex::Real > &  scalar,
const int  scalar_comp,
const int  i,
const int  j,
const int  k,
const amrex::Real *  dz,
const int  klo,
const int  khi,
const bool  ext_dir_lo,
const bool  ext_dir_hi 
)
noexcept

Existing S-grid vertical-center gradient, including boundary and tile-edge spacing.

249 {
250  if (ext_dir_lo) {
251  const auto w = StretchedDiffusionDirichletWeights(dz[k], dz[k + 1]);
252  return (amrex::Real(1.0) / dz[k]) *
253  (w.c1 * scalar(i, j, k - 1, scalar_comp) +
254  w.c2 * scalar(i, j, k, scalar_comp) +
255  w.c3 * scalar(i, j, k + 1, scalar_comp));
256  }
257  if (ext_dir_hi) {
258  const auto w = StretchedDiffusionDirichletWeights(dz[k - 1], dz[k - 2]);
259  return (amrex::Real(1.0) / dz[k - 1]) *
260  (-(
261  w.c1 * scalar(i, j, k, scalar_comp) +
262  w.c2 * scalar(i, j, k - 1, scalar_comp) +
263  w.c3 * scalar(i, j, k - 2, scalar_comp)));
264  }
265  const amrex::Real inv = (k == klo) ? amrex::Real(1.0) / dz[k]
266  : (k == khi + 1)
267  ? amrex::Real(1.0) / dz[k - 1]
268  : amrex::Real(2.0) / (dz[k] + dz[k - 1]);
269  return inv *
270  (scalar(i, j, k, scalar_comp) - scalar(i, j, k - 1, scalar_comp));
271 }
Real w
Definition: ERF_Plotfile2DInterpolator.cpp:22
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE StretchedDiffusionBoundaryWeights StretchedDiffusionDirichletWeights(const amrex::Real dz_near, const amrex::Real dz_next) noexcept
Definition: ERF_ScalarDiffusion.H:145

Referenced by BuildScalarDiffusionFluxes_S_Impl().

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

◆ SubtractTerrainMetricImplicitPart_T()

void SubtractTerrainMetricImplicitPart_T ( const amrex::Box &  bx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const ScalarDiffusionFluxPolicy &  policy,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my,
const amrex::Real  implicit_fac 
)
inline

Dispatch SubtractTerrainMetricImplicitPart_T_Impl on the coefficient mode.

1536 {
1537  const amrex::Box zbx = amrex::surroundingNodes(bx, 2);
1538  const auto mode = policy.coefficient_mode;
1539  if (mode.molecular_is_kinematic) {
1540  if (mode.add_turbulence) {
1541  SubtractTerrainMetricImplicitPart_T_Impl<true, true>(
1542  zbx, domain, field, policy.coefficients, z_nd, cellSizeInv, mf_mx, mf_my, implicit_fac);
1543  } else {
1544  SubtractTerrainMetricImplicitPart_T_Impl<true, false>(
1545  zbx, domain, field, policy.coefficients, z_nd, cellSizeInv, mf_mx, mf_my, implicit_fac);
1546  }
1547  } else if (mode.add_turbulence) {
1548  SubtractTerrainMetricImplicitPart_T_Impl<false, true>(
1549  zbx, domain, field, policy.coefficients, z_nd, cellSizeInv, mf_mx, mf_my, implicit_fac);
1550  } else {
1551  SubtractTerrainMetricImplicitPart_T_Impl<false, false>(
1552  zbx, domain, field, policy.coefficients, z_nd, cellSizeInv, mf_mx, mf_my, implicit_fac);
1553  }
1554 }

Referenced by DiffusionSrcForState_T().

Here is the caller graph for this function:

◆ SubtractTerrainMetricImplicitPart_T_Impl()

template<bool MultiplyMolecularByDensity, bool AddTurbulence>
void SubtractTerrainMetricImplicitPart_T_Impl ( const amrex::Box &  zbx,
const amrex::Box &  domain,
const ScalarDiffusionFieldViews &  field,
const ScalarDiffusionCoefficients &  coefficients,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my,
const amrex::Real  implicit_fac 
)
inline

erf.implicit_terrain_metric: the implicit vertical solve also takes the compact terrain-metric flux -K_h M_s dphi/dz (ERF_TerrainImplicitMetric.H) on the interior zeta faces, so add implicit_fac * K_h M_s dphi/dz to the explicit raw F_z there. K_h is the horizontal coefficient of the x/y fluxes, averaged to the z face; the bottom and top faces, which carry the boundary condition, are left alone.

1496 {
1497  using namespace amrex;
1498  const int dom_klo = domain.smallEnd(2);
1499  const int dom_khi = domain.bigEnd(2);
1500  const auto scalar = field.scalar;
1501  const auto density = field.density;
1502  const auto mu_turb = field.mu_turb;
1503  const auto zflux = field.zflux;
1504  const int scalar_comp = field.scalar_comp;
1505  const int rho_comp = field.rho_comp;
1506  const int flux_comp = field.flux_comp;
1507  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
1508  if (!TerrainMetricImplicitFace(k, dom_klo, dom_khi)) { return; }
1510  MultiplyMolecularByDensity, AddTurbulence>(
1511  density, rho_comp, mu_turb, coefficients, i, j, k, 0, 0, 1,
1512  coefficients.eddy_h_comp);
1513  const Real h_zeta = Compute_h_zeta_AtKface(i, j, k, cellSizeInv, z_nd);
1514  const Real grad_z = (cellSizeInv[2] / h_zeta) *
1515  (scalar(i, j, k, scalar_comp) - scalar(i, j, k - 1, scalar_comp));
1516  const Real metric = TerrainMetricScalarFactor(
1517  Compute_h_xi_AtKface(i, j, k, cellSizeInv, z_nd),
1518  Compute_h_eta_AtKface(i, j, k, cellSizeInv, z_nd),
1519  mf_mx(i, j, 0), mf_my(i, j, 0));
1520  zflux(i, j, k, flux_comp) += implicit_fac * kh * metric * grad_z;
1521  });
1522 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool TerrainMetricImplicitFace(const int kface, const int dom_lo, const int dom_hi) noexcept
Definition: ERF_TerrainImplicitMetric.H:72
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainMetricScalarFactor(const amrex::Real h_xi, const amrex::Real h_eta, const amrex::Real mx, const amrex::Real my) noexcept
Definition: ERF_TerrainImplicitMetric.H:56
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtKface(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:440
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtKface(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:463
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtKface(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:416
int eddy_h_comp
Definition: ERF_ScalarDiffusion.H:25
Here is the call graph for this function:

◆ TerrainDiffusionDivergence_T()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionDivergence_T ( const amrex::Real  mapped_Fx_hi,
const amrex::Real  mapped_Fx_lo,
const amrex::Real  mapped_Fy_hi,
const amrex::Real  mapped_Fy_lo,
const amrex::Real  Gz_hi,
const amrex::Real  Gz_lo,
const amrex::Real  dx_inv,
const amrex::Real  dy_inv,
const amrex::Real  dz_inv,
const amrex::Real  mfsq,
const amrex::Real  detJ_cell 
)
noexcept

Native terrain divergence in the legacy arithmetic association.

640 {
641  amrex::Real stateContrib =
642  (mapped_Fx_hi - mapped_Fx_lo) * dx_inv * mfsq +
643  (mapped_Fy_hi - mapped_Fy_lo) * dy_inv * mfsq +
644  (Gz_hi - Gz_lo) * dz_inv;
645  stateContrib /= detJ_cell;
646  return stateContrib;
647 }

Referenced by ApplyScalarDiffusionMappedDivergence_T().

Here is the caller graph for this function:

◆ TerrainDiffusionGz()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionGz ( const amrex::Real  raw_Fz,
const amrex::Real  mx,
const amrex::Real  h_xi,
const amrex::Real  Fbar_x,
const amrex::Real  my,
const amrex::Real  h_eta,
const amrex::Real  Fbar_y 
)
noexcept

Raw terrain-coordinate F_z and its conservative transformed transfer are distinct quantities. G_z is the numerator F_z - m_x h_xi Fbar_x - m_y h_eta Fbar_y; T_z=G_z/(m_x m_y).

452 {
453  return raw_Fz - h_xi * mx * Fbar_x - h_eta * my * Fbar_y;
454 }

Referenced by TerrainScalarDiffusionGzAtKFace().

Here is the caller graph for this function:

◆ TerrainDiffusionMappedTx()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionMappedTx ( const amrex::Real  raw_Fx,
const amrex::Real  h_zeta,
const amrex::Real  my 
)
noexcept
461 {
462  return raw_Fx * h_zeta / my;
463 }

Referenced by ApplyScalarDiffusionMappedDivergence_T(), and BuildScalarDiffusionMappedTransfers_T().

Here is the caller graph for this function:

◆ TerrainDiffusionMappedTy()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionMappedTy ( const amrex::Real  raw_Fy,
const amrex::Real  h_zeta,
const amrex::Real  mx 
)
noexcept
470 {
471  return raw_Fy * h_zeta / mx;
472 }

Referenced by ApplyScalarDiffusionMappedDivergence_T(), and BuildScalarDiffusionMappedTransfers_T().

Here is the caller graph for this function:

◆ TerrainScalarDiffusionFluxAtIFace()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtIFace ( const amrex::Array4< const amrex::Real > &  scalar,
const int  scalar_comp,
const amrex::Real  coeff,
const int  i,
const int  j,
const int  k,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::Array4< const amrex::Real > &  z_cc,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_ux 
)
noexcept

Terrain x-face raw diffusion flux, including ERF's x-face map factor. coeff is the already selected effective face coefficient. Prescribed surface flux replacement is boundary policy and is intentionally outside this geometry primitive.

336 {
337  const amrex::Real h_xi = Compute_h_xi_AtIface(i, j, k, cellSizeInv, z_nd);
338  const amrex::Real idz_hi =
339  amrex::Real(1.0) / (z_cc(i, j, k + 1) - z_cc(i, j, k - 1));
340  const amrex::Real idz_lo =
341  amrex::Real(1.0) / (z_cc(i - 1, j, k + 1) - z_cc(i - 1, j, k - 1));
342  const amrex::Real grad_z =
343  amrex::Real(0.5) * (scalar(i, j, k + 1, scalar_comp) * idz_hi +
344  scalar(i - 1, j, k + 1, scalar_comp) * idz_lo -
345  scalar(i, j, k - 1, scalar_comp) * idz_hi -
346  scalar(i - 1, j, k - 1, scalar_comp) * idz_lo);
347  const amrex::Real grad_xi =
348  cellSizeInv[0] *
349  (scalar(i, j, k, scalar_comp) - scalar(i - 1, j, k, scalar_comp));
350  return ScalarDiffusionFlux_Tx(coeff, mf_ux(i, j, 0), grad_xi, h_xi, grad_z);
351 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_Tx(const amrex::Real coeff, const amrex::Real face_map, const amrex::Real grad_xi, const amrex::Real h_xi, const amrex::Real grad_z) noexcept
Definition: ERF_ScalarDiffusion.H:297
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtIface(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:299

Referenced by BuildScalarDiffusionFluxes_T_Impl().

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

◆ TerrainScalarDiffusionFluxAtJFace()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtJFace ( const amrex::Array4< const amrex::Real > &  scalar,
const int  scalar_comp,
const amrex::Real  coeff,
const int  i,
const int  j,
const int  k,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::Array4< const amrex::Real > &  z_cc,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_vy 
)
noexcept

Terrain y-face raw diffusion flux, including ERF's y-face map factor.

366 {
367  const amrex::Real h_eta = Compute_h_eta_AtJface(i, j, k, cellSizeInv, z_nd);
368  const amrex::Real idz_hi =
369  amrex::Real(1.0) / (z_cc(i, j, k + 1) - z_cc(i, j, k - 1));
370  const amrex::Real idz_lo =
371  amrex::Real(1.0) / (z_cc(i, j - 1, k + 1) - z_cc(i, j - 1, k - 1));
372  const amrex::Real grad_z =
373  amrex::Real(0.5) * (scalar(i, j, k + 1, scalar_comp) * idz_hi +
374  scalar(i, j - 1, k + 1, scalar_comp) * idz_lo -
375  scalar(i, j, k - 1, scalar_comp) * idz_hi -
376  scalar(i, j - 1, k - 1, scalar_comp) * idz_lo);
377  const amrex::Real grad_eta =
378  cellSizeInv[1] *
379  (scalar(i, j, k, scalar_comp) - scalar(i, j - 1, k, scalar_comp));
380  return ScalarDiffusionFlux_Ty(coeff, mf_vy(i, j, 0), grad_eta, h_eta, grad_z);
381 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real ScalarDiffusionFlux_Ty(const amrex::Real coeff, const amrex::Real face_map, const amrex::Real grad_eta, const amrex::Real h_eta, const amrex::Real grad_z) noexcept
Definition: ERF_ScalarDiffusion.H:308
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtJface(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:392

Referenced by BuildScalarDiffusionFluxes_T_Impl().

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

◆ TerrainScalarDiffusionFluxAtKFace()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionFluxAtKFace ( const amrex::Array4< const amrex::Real > &  scalar,
const int  scalar_comp,
const amrex::Real  coeff,
const int  i,
const int  j,
const int  kface,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const bool  ext_dir_lo,
const bool  ext_dir_hi 
)
noexcept

Terrain raw vertical diffusion flux at one k face. Dirichlet boundary stencils are selected explicitly by the caller; surface-layer replacement remains separate boundary policy.

400 {
401  amrex::Real grad_z;
402  if (ext_dir_lo) {
403  const amrex::Real zm = Compute_Z_AtWFace(i, j, kface + 1, z_nd);
404  const amrex::Real dz0 = zm - Compute_Z_AtWFace(i, j, kface, z_nd);
405  const amrex::Real dz1 = Compute_Z_AtWFace(i, j, kface + 2, z_nd) - zm;
406  const amrex::Real idz0 = amrex::Real(1.0) / dz0;
407  const amrex::Real f = dz1 / dz0 + amrex::Real(2.0);
408  const amrex::Real f2 = f * f;
409  const amrex::Real c3 = amrex::Real(2.0) / (f - f2);
410  const amrex::Real c2 = -f2 * c3;
411  const amrex::Real c1 = -(amrex::Real(1.0) - f2) * c3;
412  grad_z = idz0 * (c1 * scalar(i, j, kface - 1, scalar_comp) +
413  c2 * scalar(i, j, kface, scalar_comp) +
414  c3 * scalar(i, j, kface + 1, scalar_comp));
415  } else if (ext_dir_hi) {
416  const amrex::Real zm = Compute_Z_AtWFace(i, j, kface - 1, z_nd);
417  const amrex::Real dz0 = Compute_Z_AtWFace(i, j, kface, z_nd) - zm;
418  const amrex::Real dz1 = zm - Compute_Z_AtWFace(i, j, kface - 2, z_nd);
419  const amrex::Real idz0 = amrex::Real(1.0) / dz0;
420  const amrex::Real f = dz1 / dz0 + amrex::Real(2.0);
421  const amrex::Real f2 = f * f;
422  const amrex::Real c3 = amrex::Real(2.0) / (f - f2);
423  const amrex::Real c2 = -f2 * c3;
424  const amrex::Real c1 = -(amrex::Real(1.0) - f2) * c3;
425  grad_z = idz0 * (-(
426  c1 * scalar(i, j, kface, scalar_comp) +
427  c2 * scalar(i, j, kface - 1, scalar_comp) +
428  c3 * scalar(i, j, kface - 2, scalar_comp)));
429  } else {
430  const amrex::Real h_zeta =
431  Compute_h_zeta_AtKface(i, j, kface, cellSizeInv, z_nd);
432  grad_z = (cellSizeInv[2] / h_zeta) * (scalar(i, j, kface, scalar_comp) -
433  scalar(i, j, kface - 1, scalar_comp));
434  }
435  return -coeff * grad_z;
436 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Z_AtWFace(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:736
real(c_double), parameter c2
Definition: ERF_module_model_constants.F90:35
real(c_double), private c1
Definition: ERF_module_mp_morr_two_moment.F90:212

Referenced by BuildScalarDiffusionFluxes_T_Impl().

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

◆ TerrainScalarDiffusionGzAtKFace()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionGzAtKFace ( const int  i,
const int  j,
const int  kface,
const amrex::Box &  domain,
const amrex::Array4< const amrex::Real > &  raw_xflux,
const amrex::Array4< const amrex::Real > &  raw_yflux,
const amrex::Array4< const amrex::Real > &  raw_zflux,
const int  flux_comp,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my 
)
noexcept

Construct the native terrain numerator G_z at one vertical face. This helper owns x/y-face interpolation, physical-boundary extrapolation, and terrain cross terms; native divergence consumes G_z directly.

516 {
517  const int klo = domain.smallEnd(2);
518  const int khi = domain.bigEnd(2) + 1;
519  amrex::Real xbar, ybar;
520 
521  if (kface == klo) {
522  const amrex::Real xlo = myhalf * (raw_xflux(i, j, klo, flux_comp) +
523  raw_xflux(i + 1, j, klo, flux_comp));
524  const amrex::Real xhi = myhalf * (raw_xflux(i, j, klo + 1, flux_comp) +
525  raw_xflux(i + 1, j, klo + 1, flux_comp));
526  xbar = amrex::Real(1.5) * xlo - myhalf * xhi;
527  const amrex::Real ylo = myhalf * (raw_yflux(i, j, klo, flux_comp) +
528  raw_yflux(i, j + 1, klo, flux_comp));
529  const amrex::Real yhi = myhalf * (raw_yflux(i, j, klo + 1, flux_comp) +
530  raw_yflux(i, j + 1, klo + 1, flux_comp));
531  ybar = amrex::Real(1.5) * ylo - myhalf * yhi;
532  } else if (kface == khi) {
533  const amrex::Real xlo = myhalf * (raw_xflux(i, j, khi - 2, flux_comp) +
534  raw_xflux(i + 1, j, khi - 2, flux_comp));
535  const amrex::Real xhi = myhalf * (raw_xflux(i, j, khi - 1, flux_comp) +
536  raw_xflux(i + 1, j, khi - 1, flux_comp));
537  xbar = amrex::Real(1.5) * xhi - myhalf * xlo;
538  const amrex::Real ylo = myhalf * (raw_yflux(i, j, khi - 2, flux_comp) +
539  raw_yflux(i, j + 1, khi - 2, flux_comp));
540  const amrex::Real yhi = myhalf * (raw_yflux(i, j, khi - 1, flux_comp) +
541  raw_yflux(i, j + 1, khi - 1, flux_comp));
542  ybar = amrex::Real(1.5) * yhi - myhalf * ylo;
543  } else {
544  xbar = fourth * (raw_xflux(i, j, kface, flux_comp) +
545  raw_xflux(i + 1, j, kface, flux_comp) +
546  raw_xflux(i, j, kface - 1, flux_comp) +
547  raw_xflux(i + 1, j, kface - 1, flux_comp));
548  ybar = fourth * (raw_yflux(i, j, kface, flux_comp) +
549  raw_yflux(i, j + 1, kface, flux_comp) +
550  raw_yflux(i, j, kface - 1, flux_comp) +
551  raw_yflux(i, j + 1, kface - 1, flux_comp));
552  }
553 
554  const amrex::Real mx = mf_mx(i, j, 0);
555  const amrex::Real my = mf_my(i, j, 0);
556  const amrex::Real h_xi = Compute_h_xi_AtKface(i, j, kface, cellSizeInv, z_nd);
557  const amrex::Real h_eta =
558  Compute_h_eta_AtKface(i, j, kface, cellSizeInv, z_nd);
559  const amrex::Real Gz = TerrainDiffusionGz(
560  raw_zflux(i, j, kface, flux_comp), mx, h_xi, xbar, my, h_eta, ybar);
561  return Gz;
562 }
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainDiffusionGz(const amrex::Real raw_Fz, const amrex::Real mx, const amrex::Real h_xi, const amrex::Real Fbar_x, const amrex::Real my, const amrex::Real h_eta, const amrex::Real Fbar_y) noexcept
Definition: ERF_ScalarDiffusion.H:444

Referenced by ApplyScalarDiffusionMappedDivergence_T(), and TerrainScalarDiffusionMappedTransferAtKFace().

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

◆ TerrainScalarDiffusionMappedTransferAtKFace()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real TerrainScalarDiffusionMappedTransferAtKFace ( const int  i,
const int  j,
const int  kface,
const amrex::Box &  domain,
const amrex::Array4< const amrex::Real > &  raw_xflux,
const amrex::Array4< const amrex::Real > &  raw_yflux,
const amrex::Array4< const amrex::Real > &  raw_zflux,
const int  flux_comp,
const amrex::Array4< const amrex::Real > &  z_nd,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &  cellSizeInv,
const amrex::Array4< const amrex::Real > &  mf_mx,
const amrex::Array4< const amrex::Real > &  mf_my,
const bool  suppress_transfer = false 
)
noexcept

Complete terrain vertical transfer at one k face. Terrain interpolation, boundary extrapolation and cross terms remain owned by the Gz helper above. Set suppress_transfer when the caller's resolved boundary policy suppresses the complete lower terrain-normal transfer.

At an interior k face, raw_xflux and raw_yflux must be valid at kface and kface-1. At the physical bottom or top face, the authoritative Gz helper uses one-sided extrapolation and needs no out-of-domain z layer.

589 {
590  if (suppress_transfer) return amrex::Real(0.0);
592  i, j, kface, domain, raw_xflux, raw_yflux, raw_zflux, flux_comp, z_nd,
593  cellSizeInv, mf_mx, mf_my);
595  Gz, mf_mx(i, j, 0), mf_my(i, j, 0));
596 }

Referenced by BuildScalarDiffusionMappedTransfers_T().

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