ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_FillZeroAreaFaceFluxes.cpp File Reference
#include "ERF.H"
#include "ERF_Utils.H"
Include dependency graph for ERF_FillZeroAreaFaceFluxes.cpp:

Functions

template<typename T >
void FillZeroAreaFaceFluxes (MultiFab &phi, Array< MultiFab, AMREX_SPACEDIM > &fluxes, const Geometry &geom, EBFArrayBoxFactory const &ebfact, T const &ebfact_u, T const &ebfact_v, T const &ebfact_w)
 
template void FillZeroAreaFaceFluxes (amrex::MultiFab &, amrex::Array< amrex::MultiFab, AMREX_SPACEDIM > &, const amrex::Geometry &, amrex::EBFArrayBoxFactory const &, amrex::EBFArrayBoxFactory const &, amrex::EBFArrayBoxFactory const &, amrex::EBFArrayBoxFactory const &)
 
template void FillZeroAreaFaceFluxes (amrex::MultiFab &, amrex::Array< amrex::MultiFab, AMREX_SPACEDIM > &, const amrex::Geometry &, amrex::EBFArrayBoxFactory const &, eb_aux_ const &, eb_aux_ const &, eb_aux_ const &)
 

Function Documentation

◆ FillZeroAreaFaceFluxes() [1/3]

template void FillZeroAreaFaceFluxes ( amrex::MultiFab &  ,
amrex::Array< amrex::MultiFab, AMREX_SPACEDIM > &  ,
const amrex::Geometry &  ,
amrex::EBFArrayBoxFactory const &  ,
amrex::EBFArrayBoxFactory const &  ,
amrex::EBFArrayBoxFactory const &  ,
amrex::EBFArrayBoxFactory const &   
)

◆ FillZeroAreaFaceFluxes() [2/3]

template void FillZeroAreaFaceFluxes ( amrex::MultiFab &  ,
amrex::Array< amrex::MultiFab, AMREX_SPACEDIM > &  ,
const amrex::Geometry &  ,
amrex::EBFArrayBoxFactory const &  ,
eb_aux_ const &  ,
eb_aux_ const &  ,
eb_aux_ const &   
)

◆ FillZeroAreaFaceFluxes() [3/3]

template<typename T >
void FillZeroAreaFaceFluxes ( MultiFab &  phi,
Array< MultiFab, AMREX_SPACEDIM > &  fluxes,
const Geometry &  geom,
EBFArrayBoxFactory const &  ebfact,
T const &  ebfact_u,
T const &  ebfact_v,
T const &  ebfact_w 
)

Compute phi gradients where the area of the face is zero

At such a face one of the two adjacent cells is covered, so the gradient is extrapolated from the two nearest face gradients on the uncovered side, which reaches three cells away. Give phi three filled ghost cells to get that stencil everywhere; with fewer, faces near the edge of a box fall back to a first-order one-sided gradient, and the result then depends on the grid decomposition.

Template Parameters
TEB factory or auxiliary EB data type for face-centered grids
Parameters
phiCell-centered solution used to compute gradients, with its ghost cells filled
fluxesFace-centered gradient fluxes to fill
geomGeometry used for inverse cell spacing
ebfactCell-centered embedded-boundary factory
ebfact_uEmbedded-boundary data on x-faces
ebfact_vEmbedded-boundary data on y-faces
ebfact_wEmbedded-boundary data on z-faces
32 {
33  BL_PROFILE("ERF::FillZeroAreaFaceFluxes()");
34 
35  const GpuArray<Real, AMREX_SPACEDIM> dxInv = geom.InvCellSizeArray();
36 
37  for (MFIter mfi(phi,TileNoZ()); mfi.isValid(); ++mfi)
38  {
39  const Box& tbx = mfi.tilebox();
40  const Box& xbx = mfi.nodaltilebox(0);
41  const Box& ybx = mfi.nodaltilebox(1);
42  const Box& zbx = mfi.nodaltilebox(2);
43 
44  // EBCellFlagFab const& cflag_fab = (ebfact.get_const_factory())->getMultiEBCellFlagFab()[mfi];
45  EBCellFlagFab const& cflag_fab = (ebfact.getMultiEBCellFlagFab())[mfi];
46  Array4<const EBCellFlag> cflag = cflag_fab.const_array();
47 
48  if (cflag_fab.getType(tbx) == FabType::singlevalued)
49  {
50  Array4<const Real> apx = ebfact.getAreaFrac()[0]->const_array(mfi);
51  Array4<const Real> apy = ebfact.getAreaFrac()[1]->const_array(mfi);
52  Array4<const Real> apz = ebfact.getAreaFrac()[2]->const_array(mfi);
53 
54  Array4<const EBCellFlag> u_cflag = ebfact_u.getMultiEBCellFlagFab()[mfi].const_array();
55  Array4<const EBCellFlag> v_cflag = ebfact_v.getMultiEBCellFlagFab()[mfi].const_array();
56  Array4<const EBCellFlag> w_cflag = ebfact_w.getMultiEBCellFlagFab()[mfi].const_array();
57 
58  Array4<Real const> const& p_arr = phi.const_array(mfi);
59  Array4<Real> const& fx = fluxes[0].array(mfi);
60  Array4<Real> const& fy = fluxes[1].array(mfi);
61  Array4<Real> const& fz = fluxes[2].array(mfi);
62 
63  // The region of phi that we may read: this FAB's own cells, less any that lie
64  // outside the domain in a non-periodic direction, since the FillBoundary done
65  // before this call leaves those unfilled. The three-cell stencils below reach
66  // three cells past the tile at a face on the box edge, so they must be checked
67  // against this rather than assumed to fit (issue #3699)
68  const Box rbx = phi[mfi].box() & geom.growPeriodicDomain(phi.nGrowVect());
69  const auto rlo = lbound(rbx);
70  const auto rhi = ubound(rbx);
71 
72  ParallelFor(xbx, ybx, zbx,
73  // x-face
74  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
75  {
76  if (apx(i,j,k) == zero) {
77  if (!u_cflag(i,j,k).isCovered()) {
78  if (cflag(i,j,k).isCovered() && !cflag(i-1,j,k).isCovered()) {
79  // Extrapolate from the uncovered side, at i-1 and below
80  if (i-3 >= rlo.x) {
81  fx(i,j,k) = dxInv[0] * (p_arr(i-3,j,k) - three*p_arr(i-2,j,k) + two*p_arr(i-1,j,k));
82  } else if (i-2 >= rlo.x) {
83  fx(i,j,k) = dxInv[0] * (p_arr(i-1,j,k) - p_arr(i-2,j,k));
84  }
85  } else if (cflag(i-1,j,k).isCovered() && !cflag(i,j,k).isCovered()) {
86  // Extrapolate from the uncovered side, at i and above
87  if (i+2 <= rhi.x) {
88  fx(i,j,k) = dxInv[0] * (three*p_arr(i+1,j,k) - p_arr(i+2,j,k) - two*p_arr(i,j,k));
89  } else if (i+1 <= rhi.x) {
90  fx(i,j,k) = dxInv[0] * (p_arr(i+1,j,k) - p_arr(i,j,k));
91  }
92  }
93  }
94  }
95  },
96  // y-face
97  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
98  {
99  if (apy(i,j,k) == zero) {
100  if (!v_cflag(i,j,k).isCovered()) {
101  if (cflag(i,j,k).isCovered() && !cflag(i,j-1,k).isCovered()) {
102  // Extrapolate from the uncovered side, at j-1 and below
103  if (j-3 >= rlo.y) {
104  fy(i,j,k) = dxInv[1] * (p_arr(i,j-3,k) - three*p_arr(i,j-2,k) + two*p_arr(i,j-1,k));
105  } else if (j-2 >= rlo.y) {
106  fy(i,j,k) = dxInv[1] * (p_arr(i,j-1,k) - p_arr(i,j-2,k));
107  }
108  } else if (cflag(i,j-1,k).isCovered() && !cflag(i,j,k).isCovered()) {
109  // Extrapolate from the uncovered side, at j and above
110  if (j+2 <= rhi.y) {
111  fy(i,j,k) = dxInv[1] * (three*p_arr(i,j+1,k) - p_arr(i,j+2,k) - two*p_arr(i,j,k));
112  } else if (j+1 <= rhi.y) {
113  fy(i,j,k) = dxInv[1] * (p_arr(i,j+1,k) - p_arr(i,j,k));
114  }
115  }
116  }
117  }
118  },
119  // z-face
120  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
121  {
122  if (apz(i,j,k) == zero) {
123  if (!w_cflag(i,j,k).isCovered()) {
124  if (cflag(i,j,k).isCovered() && !cflag(i,j,k-1).isCovered()) {
125  // Extrapolate from the uncovered side, at k-1 and below
126  if (k-3 >= rlo.z) {
127  fz(i,j,k) = dxInv[2] * (p_arr(i,j,k-3) - three*p_arr(i,j,k-2) + two*p_arr(i,j,k-1));
128  } else if (k-2 >= rlo.z) {
129  fz(i,j,k) = dxInv[2] * (p_arr(i,j,k-1) - p_arr(i,j,k-2));
130  }
131  } else if (cflag(i,j,k-1).isCovered() && !cflag(i,j,k).isCovered()) {
132  // Extrapolate from the uncovered side, at k and above
133  if (k+2 <= rhi.z) {
134  fz(i,j,k) = dxInv[2] * (three*p_arr(i,j,k+1) - p_arr(i,j,k+2) - two*p_arr(i,j,k));
135  } else if (k+1 <= rhi.z) {
136  fz(i,j,k) = dxInv[2] * (p_arr(i,j,k+1) - p_arr(i,j,k));
137  }
138  }
139  }
140  }
141  });
142  } // single-valued
143  } // mfi
144 }
if(l_use_mynn &&start_comp<=RhoKE_comp &&end_comp >=RhoKE_comp)
Definition: ERF_AddQKESources.H:2
constexpr amrex::Real three
Definition: ERF_Constants.H:11
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
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_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ rhi
Definition: ERF_WSM6.H:250

Referenced by solve_with_EB_mlmg().

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