ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
eb_aux_ Class Reference

Stores face-centered EB geometry reconstructed from a cell-centered factory. More...

#include <ERF_EBAux.H>

Collaboration diagram for eb_aux_:

Public Member Functions

 eb_aux_ ()
 Construct an undefined auxiliary EB factory. More...
 
 ~eb_aux_ ()=default
 Destroy the auxiliary EB factory; the owned geometry is released by its unique_ptrs. More...
 
void define (int const &a_level, int const &a_idim, amrex::Geometry const &a_geom, amrex::BoxArray const &a_grids, amrex::DistributionMapping const &a_dmap, amrex::Vector< int > const &a_ngrow, amrex::EBFArrayBoxFactory const *a_factory)
 Define face-centered EB geometry for one staggered direction. More...
 
void set_verbose ()
 Enable verbose diagnostic output during factory construction. More...
 
const amrex::FabArray< amrex::EBCellFlagFab > & getMultiEBCellFlagFab () const
 Return the reconstructed EB cell flags. More...
 
const amrex::MultiFab & getVolFrac () const
 Return the reconstructed volume fractions. More...
 
const amrex::MultiFab & getCentroid () const
 Return the reconstructed volume centroids. More...
 
const amrex::MultiFab & getBndryArea () const
 Return the reconstructed EB boundary areas. More...
 
const amrex::MultiFab & getBndryCent () const
 Return the reconstructed EB boundary centroids. More...
 
const amrex::MultiFab & getBndryNormal () const
 Return the reconstructed EB boundary normals. More...
 
amrex::Array< const amrex::MultiFab *, AMREX_SPACEDIM > getAreaFrac () const
 Return reconstructed area fractions for all coordinate directions. More...
 
amrex::Array< const amrex::MultiFab *, AMREX_SPACEDIM > getFaceCent () const
 Return reconstructed face centroids for all coordinate directions. More...
 

Private Attributes

int m_verbose
 
std::unique_ptr< amrex::FabArray< amrex::EBCellFlagFab > > m_cellflags
 
std::unique_ptr< amrex::MultiFab > m_volfrac
 
std::unique_ptr< amrex::MultiFab > m_volcent
 
std::unique_ptr< amrex::MultiFab > m_bndryarea
 
std::unique_ptr< amrex::MultiFab > m_bndrycent
 
std::unique_ptr< amrex::MultiFab > m_bndrynorm
 
amrex::Array< std::unique_ptr< amrex::MultiFab >, AMREX_SPACEDIM > m_areafrac
 
amrex::Array< std::unique_ptr< amrex::MultiFab >, AMREX_SPACEDIM > m_facecent
 

Detailed Description

Stores face-centered EB geometry reconstructed from a cell-centered factory.

This class mirrors the subset of the AMReX EB factory interface needed by ERF staggered momentum fields when native face-centered EB factories are disabled.

Constructor & Destructor Documentation

◆ eb_aux_()

eb_aux_::eb_aux_ ( )

Construct an undefined auxiliary EB factory.

18  : m_verbose(0)
19 // ,m_defined(0)
20 {}
int m_verbose
Definition: ERF_EBAux.H:78

◆ ~eb_aux_()

eb_aux_::~eb_aux_ ( )
default

Destroy the auxiliary EB factory; the owned geometry is released by its unique_ptrs.

Member Function Documentation

◆ define()

void eb_aux_::define ( int const &  a_level,
int const &  a_idim,
amrex::Geometry const &  a_geom,
amrex::BoxArray const &  a_grids,
amrex::DistributionMapping const &  a_dmap,
amrex::Vector< int > const &  a_ngrow,
amrex::EBFArrayBoxFactory const *  a_factory 
)

Define face-centered EB geometry for one staggered direction.

May be called more than once on the same object – ERF::RemakeLevel and MakeNewLevelFromCoarse both redefine the factories of an existing level. Each call replaces the previously owned geometry, which is freed on reassignment of the owning unique_ptr.

Parameters
a_levelAMR level index.
a_idimStaggered direction for the target velocity grid.
a_geomCell-centered level geometry.
a_gridsCell-centered grid boxes.
a_dmapDistribution mapping for the grids.
a_ngrowGhost-cell counts for flags, volumes, and centroids.
a_factorySource cell-centered EB factory.
31 {
32  // Box dbox(a_geom.Domain());
33 
34  // small_volfrac
35  Real small_volfrac = Real(1.e-14);
36  ParmParse pp("eb2");
37  pp.queryAdd("small_volfrac", small_volfrac);
38  // Snap centroid/normal components that are pure roundoff to exactly zero.
39  const Real small_value = Real(10)*real_eps;
40 
41  const IntVect vdim(IntVect::TheDimensionVector(a_idim));
42 
43  const BoxArray& my_grids = amrex::convert(a_grids, vdim);
44 
45  // NOTE: assigning here frees whatever a previous call to define() allocated
46  m_cellflags = std::make_unique<FabArray<EBCellFlagFab>>(my_grids, a_dmap, 1, a_ngrow[0], MFInfo(),
47  DefaultFabFactory<EBCellFlagFab>());
48 
49  // Set m_cellflags type to singlevalued
50  m_cellflags->setVal(EBCellFlag::TheDefaultCell());
51  for (MFIter mfi(*m_cellflags, false); mfi.isValid(); ++mfi) {
52  auto& fab = (*m_cellflags)[mfi];
53  fab.setType(FabType::singlevalued);
54  }
55 
56  m_volfrac = std::make_unique<MultiFab>(my_grids, a_dmap, 1, a_ngrow[1], MFInfo(), FArrayBoxFactory());
57  m_volcent = std::make_unique<MultiFab>(my_grids, a_dmap, AMREX_SPACEDIM, a_ngrow[2], MFInfo(), FArrayBoxFactory());
58 
59  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
60  m_areafrac[idim] = std::make_unique<MultiFab>(a_grids, a_dmap, 1, a_ngrow[1]+1, MFInfo(), FArrayBoxFactory());
61  m_facecent[idim] = std::make_unique<MultiFab>(a_grids, a_dmap, AMREX_SPACEDIM-1, a_ngrow[2], MFInfo(), FArrayBoxFactory());
62  }
63 
64  m_bndryarea = std::make_unique<MultiFab>(my_grids, a_dmap, 1, a_ngrow[2], MFInfo(), FArrayBoxFactory());
65  m_bndrycent = std::make_unique<MultiFab>(my_grids, a_dmap, AMREX_SPACEDIM, a_ngrow[2], MFInfo(), FArrayBoxFactory());
66  m_bndrynorm = std::make_unique<MultiFab>(my_grids, a_dmap, AMREX_SPACEDIM, a_ngrow[2], MFInfo(), FArrayBoxFactory());
67 
68  // Initialize with zeros
69  m_volfrac->setVal(0.0);
70  m_volcent->setVal(0.0);
71 
72  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
73  m_areafrac[idim]->setVal(0.0);
74  m_facecent[idim]->setVal(0.0);
75  }
76 
77  m_bndryarea->setVal(0.0);
78  m_bndrycent->setVal(0.0);
79  m_bndrynorm->setVal(0.0);
80 
81  const auto& FlagFab = a_factory->getMultiEBCellFlagFab(); // EBFArrayBoxFactory, EBDataCollection
82 
83  for (MFIter mfi(*m_cellflags, false); mfi.isValid(); ++mfi) {
84 
85  const Box& bx = mfi.validbox();
86  const Box& bx_grown = mfi.growntilebox();
87  const Box tbx = mfi.nodaltilebox(a_idim);
88  const Box domain = surroundingNodes(a_geom.Domain(), a_idim);
89 
90  GpuArray<Real, AMREX_SPACEDIM> dx = a_geom.CellSizeArray();
91  bool l_periodic = a_geom.isPeriodic(a_idim);
92 
93  Array4<EBCellFlag> const& aux_flag = m_cellflags->array(mfi);
94  Array4<Real> const& aux_vfrac = m_volfrac->array(mfi);
95  Array4<Real> const& aux_afrac_x = m_areafrac[0]->array(mfi);
96  Array4<Real> const& aux_afrac_y = m_areafrac[1]->array(mfi);
97  Array4<Real> const& aux_afrac_z = m_areafrac[2]->array(mfi);
98 
99  if (FlagFab[mfi].getType(bx) == FabType::covered ) {
100 
101  ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
102  {
103  aux_flag(i,j,k).setCovered();
104  aux_flag(i,j,k).setDisconnected();
105  if (i==bx.bigEnd(0)) {
106  aux_flag(i+1,j,k).setCovered();
107  }
108  if (j==bx.bigEnd(1)) {
109  aux_flag(i,j+1,k).setCovered();
110  }
111  if (k==bx.bigEnd(2)) {
112  aux_flag(i,j,k+1).setCovered();
113  }
114  });
115 
116  } else if (FlagFab[mfi].getType(bx) == FabType::regular ) {
117 
118  ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
119  {
120  aux_flag(i,j,k).setRegular();
121  aux_flag(i,j,k).setDisconnected();
122  aux_vfrac(i,j,k) = one;
123  aux_afrac_x(i,j,k) = one;
124  aux_afrac_y(i,j,k) = one;
125  aux_afrac_z(i,j,k) = one;
126  if (i==bx.bigEnd(0)) {
127  aux_flag(i+1,j,k).setRegular();
128  aux_vfrac(i+1,j,k) = one;
129  aux_afrac_x(i+1,j,k) = one;
130  }
131  if (j==bx.bigEnd(1)) {
132  aux_flag(i,j+1,k).setRegular();
133  aux_vfrac(i,j+1,k) = one;
134  aux_afrac_y(i,j+1,k) = one;
135  }
136  if (k==bx.bigEnd(2)) {
137  aux_flag(i,j,k+1).setRegular();
138  aux_vfrac(i,j,k+1) = one;
139  aux_afrac_z(i,j,k+1) = one;
140  }
141  });
142 
143  } else if (FlagFab[mfi].getType(bx) == FabType::singlevalued ) {
144 
145  // Initialization
146 
147  // CC cell quantities
148  Array4<EBCellFlag const> const& flag = FlagFab.const_array(mfi);
149  Array4<Real const> const& afrac = (a_factory->getAreaFrac()[a_idim])->const_array(mfi);
150  Array4<Real const> const& bnorm = a_factory->getBndryNormal()[mfi].const_array();
151  Array4<Real const> const& bcent = a_factory->getBndryCent()[mfi].const_array();
152 
153  // aux quantities
154  Array4<Real> const& aux_vcent = m_volcent->array(mfi);
155  Array4<Real> const& aux_fcent_x = m_facecent[0]->array(mfi);
156  Array4<Real> const& aux_fcent_y = m_facecent[1]->array(mfi);
157  Array4<Real> const& aux_fcent_z = m_facecent[2]->array(mfi);
158  Array4<Real> const& aux_barea = m_bndryarea->array(mfi);
159  Array4<Real> const& aux_bcent = m_bndrycent->array(mfi);
160  Array4<Real> const& aux_bnorm = m_bndrynorm->array(mfi);
161 
162  // Extended domain in the direction of periodicity
163  Box dom_grown = domain;
164  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
165  if (a_geom.isPeriodic(idim)) {
166  dom_grown.grow(idim, a_ngrow[0]);
167  }
168  }
169 
170  const IntVect dom_grown_lo = dom_grown.smallEnd();
171  const IntVect dom_grown_hi = dom_grown.bigEnd();
172 
173  BoxList diffList = boxDiff(bx_grown, bx);
174  for (const Box& b : diffList) {
175  ParallelFor(b, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
176  {
177  if ( i < dom_grown_lo[0] || i > dom_grown_hi[0] ||
178  j < dom_grown_lo[1] || j > dom_grown_hi[1] ||
179  k < dom_grown_lo[2] || k > dom_grown_hi[2] ) {
180  aux_flag(i,j,k).setCovered();
181  aux_flag(i,j,k).setDisconnected();
182  }
183  });
184  }
185 
186 #ifndef AMREX_USE_GPU
187  int const verbose=m_verbose;
188 #endif
189 
190  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
191  {
192  // defaults to covered and disconnected.
193  aux_flag(i,j,k).setCovered();
194  aux_flag(i,j,k).setDisconnected();
195 
196  if (i==bx.bigEnd(0)) {
197  aux_flag(i+1,j,k).setCovered();
198  }
199  if (j==bx.bigEnd(1)) {
200  aux_flag(i,j+1,k).setCovered();
201  }
202  if (k==bx.bigEnd(2)) {
203  aux_flag(i,j,k+1).setCovered();
204  }
205 
206  // Index for low and hi cells
207  IntVect iv_hi(i,j,k);
208  IntVect iv_lo(iv_hi - vdim);
209 
210  bool lo_isCovered = flag(iv_lo).isCovered();
211  bool hi_isCovered = flag(iv_hi).isCovered();
212  bool lo_isRegular = flag(iv_lo).isRegular();
213  bool hi_isRegular = flag(iv_hi).isRegular();
214  bool lo_isSingleValued = flag(iv_lo).isSingleValued();
215  bool hi_isSingleValued = flag(iv_hi).isSingleValued();
216 
217  const bool at_lo_boundary = (!l_periodic && iv_hi[a_idim]==domain.smallEnd(a_idim));
218  const bool at_hi_boundary = (!l_periodic && iv_hi[a_idim]==domain.bigEnd(a_idim));
219 
220  // Treatment of lower boundary
221 
222  if (at_lo_boundary) {
223  if (hi_isCovered) {
224  lo_isCovered = true;
225  lo_isRegular = false;
226  lo_isSingleValued = false;
227  } else if (hi_isRegular) {
228  lo_isCovered = false;
229  lo_isRegular = true;
230  lo_isSingleValued = false;
231  } else if (hi_isSingleValued) {
232  if (almostEqual(afrac(i,j,k),zero)) {
233  lo_isCovered = true;
234  lo_isRegular = false;
235  lo_isSingleValued = false;
236  } else if (almostEqual(afrac(i,j,k),one)) {
237  lo_isCovered = false;
238  lo_isRegular = true;
239  lo_isSingleValued = false;
240  } else {
241  lo_isCovered = false;
242  lo_isRegular = false;
243  lo_isSingleValued = true;
244  iv_lo = iv_hi; // At the lower boundary, low cell takes the values of the high cell.
245  }
246  }
247  }
248 
249  // Treatment of upper boundary
250 
251  if (at_hi_boundary) {
252  if (lo_isCovered) { // Covered
253  hi_isCovered = true;
254  hi_isRegular = false;
255  hi_isSingleValued = false;
256  } else if (lo_isRegular) { // Regular
257  hi_isCovered = false;
258  hi_isRegular = true;
259  hi_isSingleValued = false;
260  } else if (lo_isSingleValued) { // SingleValued
261  if (almostEqual(afrac(i,j,k),zero)) { //Covered
262  hi_isCovered = true;
263  hi_isRegular = false;
264  hi_isSingleValued = false;
265  } else if (almostEqual(afrac(i,j,k),one)) { //Regular
266  hi_isCovered = false;
267  hi_isRegular = true;
268  hi_isSingleValued = false;
269  } else { // SingleValued
270  hi_isCovered = false;
271  hi_isRegular = false;
272  hi_isSingleValued = true;
273  iv_hi = iv_lo; // At the upper boundary, hi cell takes the values of the low cell.
274  }
275  }
276  }
277 
278  if ( lo_isCovered && hi_isCovered) {
279 
280  // defaults to covered and disconnected.
281 
282  } else if ( lo_isRegular && hi_isRegular) {
283 
284  aux_flag(i,j,k).setRegular();
285  aux_flag(i,j,k).setConnected();
286 
287  aux_vfrac(i,j,k) = one;
288 
289  aux_afrac_x(i,j,k) = one;
290  aux_afrac_y(i,j,k) = one;
291  aux_afrac_z(i,j,k) = one;
292 
293  if (i==bx.bigEnd(0)) {
294  aux_afrac_x(i+1,j,k) = one;
295  }
296  if (j==bx.bigEnd(1)) {
297  aux_afrac_y(i,j+1,k) = one;
298  }
299  if (k==bx.bigEnd(2)) {
300  aux_afrac_z(i,j,k+1) = one;
301  }
302 
303  } else {
304 
305 #ifndef AMREX_USE_GPU
306  if (verbose) { Print() << "\ncell: " << amrex::IntVect(i,j,k) << "\n"; }
307 #endif
308  Array<Real,AMREX_SPACEDIM> lo_arr = {-myhalf,-myhalf,-myhalf};
309  Array<Real,AMREX_SPACEDIM> hi_arr = { myhalf, myhalf, myhalf};
310 
311  //-----------------------
312  // Low EB cut cell
313  //-----------------------
314 
315  // Map bcent and bnorm to the isoparametric space for anisotropic grids.
316  // (This step is needed because bcent in AMReX is isotropically normalized.)
317 
318  RealVect lo_point (bcent(iv_lo,0), bcent(iv_lo,1), bcent(iv_lo,2));
319  RealVect lo_normal(bnorm(iv_lo,0), bnorm(iv_lo,1), bnorm(iv_lo,2));
320 
321  if (at_lo_boundary) { // At lower boundary
322  lo_point[a_idim] += one; // Move the boundary centroid upward in the a_idim direction.
323  }
324 
325  if (lo_isSingleValued ) {
326  Real bnorm_x = bnorm(iv_lo,0) * dx[0];
327  Real bnorm_y = bnorm(iv_lo,1) * dx[1];
328  Real bnorm_z = bnorm(iv_lo,2) * dx[2];
329 
330  Real norm = std::sqrt( bnorm_x*bnorm_x + bnorm_y*bnorm_y + bnorm_z*bnorm_z);
331 
332  RealVect bnorm_isoparam ( bnorm_x / norm, bnorm_y / norm, bnorm_z / norm);
333 
334  lo_normal = bnorm_isoparam;
335  }
336 
337  // High side of low cell
338  lo_arr[a_idim] = zero;
339  hi_arr[a_idim] = myhalf;
340  RealBox lo_rbx(lo_arr.data(), hi_arr.data());
341 
342  eb_cut_cell_ lo_eb_cc(flag(iv_lo), lo_rbx, lo_point, lo_normal);
343 
344  // cell iv_lo covered (regular) implies lo_eb_cc is covered (regular)
345  // The inverse is not always true.
346  AMREX_ASSERT( !lo_isCovered || lo_eb_cc.isCovered() );
347  AMREX_ASSERT( !lo_isRegular || lo_eb_cc.isRegular() );
348 
349  //-----------------------
350  // High EB cut cell
351  //-----------------------
352 
353  RealVect hi_point (bcent(iv_hi,0), bcent(iv_hi,1), bcent(iv_hi,2));
354  RealVect hi_normal(bnorm(iv_hi,0), bnorm(iv_hi,1), bnorm(iv_hi,2));
355 
356  if (at_hi_boundary) {
357  hi_point[a_idim] += -one; // Move the boundary centroid downward in the a_idim direction.
358  }
359 
360  if (hi_isSingleValued ) {
361  Real bnorm_x = bnorm(iv_hi,0) * dx[0];
362  Real bnorm_y = bnorm(iv_hi,1) * dx[1];
363  Real bnorm_z = bnorm(iv_hi,2) * dx[2];
364 
365  Real norm = std::sqrt( bnorm_x*bnorm_x + bnorm_y*bnorm_y + bnorm_z*bnorm_z);
366 
367  RealVect bnorm_isoparam ( bnorm_x / norm, bnorm_y / norm, bnorm_z / norm);
368 
369  hi_normal = bnorm_isoparam;
370  }
371 
372  // Low side of high cell
373  lo_arr[a_idim] = -myhalf;
374  hi_arr[a_idim] = zero;
375  RealBox hi_rbx(lo_arr.data(), hi_arr.data());
376 
377  eb_cut_cell_ hi_eb_cc(flag(iv_hi), hi_rbx, hi_point, hi_normal);
378 
379  // cell iv_hi covered (regular) implies hi_eb_cc is covered (regular)
380  // The inverse is not always true.
381  AMREX_ASSERT( !hi_isCovered || hi_eb_cc.isCovered() );
382  AMREX_ASSERT( !hi_isRegular || hi_eb_cc.isRegular() );
383 
384 #if 0
385 #if defined(AMREX_DEBUG) || defined(AMREX_TESTING) || 1
386 
387  { /***************************** SANITY CHECK ***********************\
388  * Perform some basic sanity checks to verify that what we computed *
389  * for cell (i,j,k) compares to what we know to be true. *
390  \******************************************************************/
391 
392  // Compute the cut-cell for the high side of the high cell. This is
393  // only needed for sanity checks.
394 
395  eb_cut_cell_ hi_hi_eb_cc(flag(iv_hi), lo_rbx, hi_point, hi_normal);
396 
397  // cell iv_hi covered (regular) implies hi_hi_eb_cc is covered (regular)
398  // The inverse is not always true.
399 #ifndef AMREX_USE_GPU
400  if ( !(!hi_isRegular || hi_hi_eb_cc.isRegular()) ||
401  !(!hi_isCovered || hi_hi_eb_cc.isCovered()) ) {
402  Print() << "flag(iv_hi) and hi_hi_eb_cc flags do not agree\n"
403  << "\n isRegular() " << hi_isRegular << " " << hi_hi_eb_cc.isRegular()
404  << "\n isCovered() " << hi_isCovered << " " << hi_hi_eb_cc.isCovered()
405  << "\n";
406  }
407 #endif
408  // If cell iv_hi is regular or covered, then hi_hi_eb_cc must also
409  // be regular or covered. The inverse is not true.
410  AMREX_ALWAYS_ASSERT( !hi_isRegular || hi_hi_eb_cc.isRegular() );
411  AMREX_ALWAYS_ASSERT( !hi_isCovered || hi_hi_eb_cc.isCovered() );
412 
413  // The area and volume fractions that are computed for the scalar grid
414  // are slightly different than those we compute from the geometric
415  // reconstruction using the EB point and normal. However, we expect
416  // that the area fractions computed here will give back the same
417  // normal we used to compute them.
418  if ( hi_isSingleValued ) {
419 
420  Real const adx = (a_idim == 0)
421  ? (hi_eb_cc.areaLo(0) - hi_hi_eb_cc.areaHi(0)) * dx[1] * dx[2]
422  : (hi_eb_cc.areaLo(0) + hi_hi_eb_cc.areaLo(0)) * dx[1] * dx[2]
423  - (hi_eb_cc.areaHi(0) + hi_hi_eb_cc.areaHi(0)) * dx[1] * dx[2];
424 
425  Real const ady = (a_idim == 1)
426  ? (hi_eb_cc.areaLo(1) - hi_hi_eb_cc.areaHi(1)) * dx[0] * dx[2]
427  : (hi_eb_cc.areaLo(1) + hi_hi_eb_cc.areaLo(1)) * dx[0] * dx[2]
428  - (hi_eb_cc.areaHi(1) + hi_hi_eb_cc.areaHi(1)) * dx[0] * dx[2];
429 
430  Real const adz = (a_idim == 2)
431  ? (hi_eb_cc.areaLo(2) - hi_hi_eb_cc.areaHi(2)) * dx[0] * dx[1]
432  : (hi_eb_cc.areaLo(2) + hi_hi_eb_cc.areaLo(2)) * dx[0] * dx[1]
433  - (hi_eb_cc.areaHi(2) + hi_hi_eb_cc.areaHi(2)) * dx[0] * dx[1];
434 
435  Real const apnorm = std::sqrt(adx*adx + ady*ady + adz*adz);
436 
437  // EB normal
438  Real const apnorminv = one / apnorm;
439  RealVect const normal(adx*apnorminv, ady*apnorminv, adz*apnorminv);
440  Real const dot_normals = normal.dotProduct(hi_normal);
441 
442 #ifndef AMREX_USE_GPU
443  if ( !amrex::almostEqual(dot_normals, one) ) {
444  Print() << "\nFail: check-1 dot_normals " << dot_normals
445  << '\n';
446 
447  hi_eb_cc.debug();
448  hi_hi_eb_cc.debug();
449 
450  } else if (verbose) {
451  Print() << "Pass: dot_normals = one\n";
452 
453  }
454 #endif
455  AMREX_ALWAYS_ASSERT( amrex::almostEqual(dot_normals, one) );
456  }
457 
458  // The a_idim area of hi_eb_cc.areaHi() should equal hi_hi_eb_cc.areaLo()
459  {
460 #ifndef AMREX_USE_GPU
461  Real const abs_err = std::abs( hi_eb_cc.areaHi(a_idim) - hi_hi_eb_cc.areaLo(a_idim) );
463  if ( abs_err >= machine_tol ) {
464  Print() << "\nFail: check-2 area abs_err: " << abs_err
465  << "\n hi_eb_cc.areaHi " << hi_eb_cc.areaHi(a_idim)
466  << "\n hi_hi_eb_cc.areaLo " << hi_hi_eb_cc.areaLo(a_idim)
467  << '\n';
468  } else if (verbose) {
469  Print() << "Pass: hi_eb_cc.areaHi = hi_hi_eb_cc.areaLo"
470  << " abs_err: " << abs_err << "\n";
471  }
472  AMREX_ALWAYS_ASSERT( abs_err < machine_tol );
473 #endif
474  }
475 
476  // The low-side area of hi_eb_cc should equal a_idim afrac.
477  { Real const abs_err = amrex::max(std::abs(lo_eb_cc.areaHi(a_idim) - afrac(iv_hi)),
478  std::abs(hi_eb_cc.areaLo(a_idim) - afrac(iv_hi)));
479  Real compare_tol = Real(5.0e-6);
480 #ifndef AMREX_USE_GPU
481  if ( abs_err >= compare_tol ) {
482  //hi_eb_cc.debug();
483  Print() << "\nFail: check-3 area abs_err " << abs_err
484  << "\n hi_eb_cc.areaLo(" << a_idim << ") = " << hi_eb_cc.areaLo(a_idim)
485  << "\n lo_eb_cc.areaHi(" << a_idim << ") = " << lo_eb_cc.areaHi(a_idim)
486  << "\n afrac" << iv_hi << " = " << afrac(iv_hi)
487  << '\n';
488  } else if (verbose) {
489  Print() << "Pass: hi_eb_cc.areaLo = afrac = " << afrac(iv_hi)
490  << " abs_err: " << abs_err << "\n";
491  }
492 #endif
493  AMREX_ALWAYS_ASSERT( abs_err < compare_tol );
494  }
495 
496  // The combined volumes of hi_eb_cc.areaHi() and hi_hi_eb_cc should
497  // equal vfrac(iv_hi).
498  { Real const vol = hi_eb_cc.volume() + hi_hi_eb_cc.volume();
499  Real const abs_err = amrex::Math::abs(vfrac(iv_hi) - vol);
500  Real compare_tol = Real(5.0e-6);
501 #ifndef AMREX_USE_GPU
502  if ( abs_err >= compare_tol ) {
503  hi_eb_cc.debug();
504  hi_hi_eb_cc.debug();
505  amrex::Print() << "\nFail: check-4 volume abs_err: " << abs_err
506  << "\n point: " << hi_point
507  << "\n normal: " << hi_normal
508  << "\n hi_eb_cc.volume() " << hi_eb_cc.volume()
509  << "\n hi_hi_eb_cc.volume() " << hi_hi_eb_cc.volume()
510  << "\n vfrac: " << vfrac(iv_hi)
511  << '\n';
512  } else if (verbose) {
513  Print() << "Pass: hi_eb_cc + hi_hi_eb_cc = vfrac = " << vfrac(iv_hi)
514  << " abs_err: " << abs_err << "\n";
515  }
516 #endif
517  AMREX_ALWAYS_ASSERT( abs_err < compare_tol );
518  }
519  } //
520 #endif
521 #endif // 0
522 
523  //-----------------------
524  // Fill out aux_ arrays
525  //-----------------------
526 
527  if (lo_eb_cc.isCovered() && hi_eb_cc.isCovered()) {
528 
529  // defaults to covered and disconnected.
530 
531  } else if (lo_eb_cc.isRegular() && hi_eb_cc.isRegular()) {
532 
533  aux_flag(i,j,k).setRegular();
534  aux_flag(i,j,k).setConnected();
535 
536  aux_vfrac(i,j,k) = one;
537 
538  aux_afrac_x(i,j,k) = one;
539  aux_afrac_y(i,j,k) = one;
540  aux_afrac_z(i,j,k) = one;
541 
542  aux_fcent_x(i,j,k,0) = zero; aux_fcent_x(i,j,k,1) = zero;
543  aux_fcent_y(i,j,k,0) = zero; aux_fcent_y(i,j,k,1) = zero;
544  aux_fcent_z(i,j,k,0) = zero; aux_fcent_z(i,j,k,1) = zero;
545 
546  if (i==bx.bigEnd(0)) {
547  aux_afrac_x(i+1,j,k) = one;
548  aux_fcent_x(i+1,j,k,0) = zero; aux_fcent_x(i+1,j,k,1) = zero;
549  }
550  if (j==bx.bigEnd(1)) {
551  aux_afrac_y(i,j+1,k) = one;
552  aux_fcent_y(i,j+1,k,0) = zero; aux_fcent_y(i,j+1,k,1) = zero;
553  }
554  if (k==bx.bigEnd(2)) {
555  aux_afrac_z(i,j,k+1) = one;
556  aux_fcent_z(i,j,k+1,0) = zero; aux_fcent_z(i,j,k+1,1) = zero;
557  }
558 
559  } else if ( (lo_eb_cc.isRegular() && hi_eb_cc.isCovered())
560  || (lo_eb_cc.isCovered() && hi_eb_cc.isRegular()) ) {
561 
562  // This is a problematic situation.
563 #ifndef AMREX_USE_GPU
564  Print()<< "eb_aux_ / Check: Regular and Covered cut cells are facing each other." << std::endl;
565 #endif
566 
567  } else {
568 
569  // zero Cell Flag
570 
571  aux_flag(i,j,k).setSingleValued();
572 
573  // 1. Volume Fraction
574 
575  Real lo_vol {lo_eb_cc.volume()}; AMREX_ASSERT(lo_vol >= zero && lo_vol <= myhalf);
576  Real hi_vol {hi_eb_cc.volume()}; AMREX_ASSERT(hi_vol >= zero && hi_vol <= myhalf);
577 
578  aux_vfrac(i,j,k) = lo_vol + hi_vol;
579 
580  // 2. Volume Centroid
581 
582  /* centVol() returns the coordinates based on m_rbx.
583  The coordinates in the a_idim direction are in [zero,myhalf] for the low cell and in [-myhalf,zero] for the hi cell.
584  Therefore, they need to be mapped to the eb_aux space, by shifting:
585  x' = x - myhalf (low cell), x + myhalf (hi cell) if a_idim = 0
586  y' = y - myhalf (low cell), y + myhalf (hi cell) if a_idim = 1
587  z' = z - myhalf (low cell), z + myhalf (hi cell) if a_idim = 2
588  */
589 
590  RealVect lo_vcent {lo_eb_cc.centVol()};
591  RealVect hi_vcent {hi_eb_cc.centVol()};
592 
593  lo_vcent[a_idim] = lo_vcent[a_idim] - myhalf;
594  hi_vcent[a_idim] = hi_vcent[a_idim] + myhalf;
595 
596  aux_vcent(i,j,k,0) = ( lo_vol * lo_vcent[0] + hi_vol * hi_vcent[0] ) / aux_vfrac(i,j,k);
597  aux_vcent(i,j,k,1) = ( lo_vol * lo_vcent[1] + hi_vol * hi_vcent[1] ) / aux_vfrac(i,j,k);
598  aux_vcent(i,j,k,2) = ( lo_vol * lo_vcent[2] + hi_vol * hi_vcent[2] ) / aux_vfrac(i,j,k);
599 
600  // 3. Area Fraction
601 
602  Real lo_areaLo_x {lo_eb_cc.areaLo(0)};
603  Real lo_areaLo_y {lo_eb_cc.areaLo(1)};
604  Real lo_areaLo_z {lo_eb_cc.areaLo(2)};
605 
606  Real hi_areaLo_x {hi_eb_cc.areaLo(0)};
607  Real hi_areaLo_y {hi_eb_cc.areaLo(1)};
608  Real hi_areaLo_z {hi_eb_cc.areaLo(2)};
609 
610  aux_afrac_x(i,j,k) = (a_idim == 0) ? lo_areaLo_x : lo_areaLo_x + hi_areaLo_x;
611  aux_afrac_y(i,j,k) = (a_idim == 1) ? lo_areaLo_y : lo_areaLo_y + hi_areaLo_y;
612  aux_afrac_z(i,j,k) = (a_idim == 2) ? lo_areaLo_z : lo_areaLo_z + hi_areaLo_z;
613 
614  if (i==bx.bigEnd(0)) {
615  Real lo_areaHi_x {lo_eb_cc.areaHi(0)};
616  Real hi_areaHi_x {hi_eb_cc.areaHi(0)};
617  aux_afrac_x(i+1,j,k) = (a_idim == 0) ? hi_areaHi_x : lo_areaHi_x + hi_areaHi_x;
618  }
619  if (j==bx.bigEnd(1)) {
620  Real lo_areaHi_y {lo_eb_cc.areaHi(1)};
621  Real hi_areaHi_y {hi_eb_cc.areaHi(1)};
622  aux_afrac_y(i,j+1,k) = (a_idim == 1) ? hi_areaHi_y : lo_areaHi_y + hi_areaHi_y;
623  }
624  if (k==bx.bigEnd(2)) {
625  Real lo_areaHi_z {lo_eb_cc.areaHi(2)};
626  Real hi_areaHi_z {hi_eb_cc.areaHi(2)};
627  aux_afrac_z(i,j,k+1) = (a_idim == 2) ? hi_areaHi_z : lo_areaHi_z + hi_areaHi_z;
628  }
629 
630  // 4. Face Centroid
631 
632  /* fcentLo returns the coordinates based on m_rbx.
633  The coordinates in the a_idim direction are in [zero,myhalf] for the low cell and in [-myhalf,zero] for the hi cell.
634  Therefore, they need to be mapped to the eb_aux space, by shifting:
635  x' = x - myhalf (low cell), x + myhalf (hi cell) if a_idim = 0
636  y' = y - myhalf (low cell), y + myhalf (hi cell) if a_idim = 1
637  z' = z - myhalf (low cell), z + myhalf (hi cell) if a_idim = 2
638  */
639 
640  RealVect lo_centLo_x {lo_eb_cc.centLo(0)};
641  RealVect lo_centLo_y {lo_eb_cc.centLo(1)};
642  RealVect lo_centLo_z {lo_eb_cc.centLo(2)};
643 
644  RealVect hi_centLo_x {hi_eb_cc.centLo(0)};
645  RealVect hi_centLo_y {hi_eb_cc.centLo(1)};
646  RealVect hi_centLo_z {hi_eb_cc.centLo(2)};
647 
648  if (a_idim == 0) {
649  aux_fcent_x(i,j,k,0) = lo_centLo_x[1]; // y
650  aux_fcent_x(i,j,k,1) = lo_centLo_x[2]; // z
651  aux_fcent_y(i,j,k,0) = (aux_afrac_y(i,j,k) > zero) // x (mapped)
652  ? ( lo_areaLo_y * (lo_centLo_y[0] - myhalf)
653  + hi_areaLo_y * (hi_centLo_y[0] + myhalf) ) / aux_afrac_y(i,j,k)
654  : zero;
655  aux_fcent_y(i,j,k,1) = (aux_afrac_y(i,j,k) > zero) // z
656  ? ( lo_areaLo_y * lo_centLo_y[2]
657  + hi_areaLo_y * hi_centLo_y[2] ) / aux_afrac_y(i,j,k)
658  : zero;
659  aux_fcent_z(i,j,k,0) = (aux_afrac_z(i,j,k) > zero) // x (mapped)
660  ? ( lo_areaLo_z * (lo_centLo_z[0] - myhalf)
661  + hi_areaLo_z * (hi_centLo_z[0] + myhalf) ) / aux_afrac_z(i,j,k)
662  : zero;
663  aux_fcent_z(i,j,k,1) = (aux_afrac_z(i,j,k) > zero) // y
664  ? ( lo_areaLo_z * lo_centLo_z[1]
665  + hi_areaLo_z * hi_centLo_z[1] ) / aux_afrac_z(i,j,k)
666  : zero;
667  } else if (a_idim == 1) {
668  aux_fcent_x(i,j,k,0) = (aux_afrac_x(i,j,k) > zero) // y (mapped)
669  ? ( lo_areaLo_x * (lo_centLo_x[1] - myhalf)
670  + hi_areaLo_x * (hi_centLo_x[1] + myhalf) ) / aux_afrac_x(i,j,k)
671  : zero;
672  aux_fcent_x(i,j,k,1) = (aux_afrac_x(i,j,k) > zero) // z
673  ? ( lo_areaLo_x * lo_centLo_x[2]
674  + hi_areaLo_x * hi_centLo_x[2] ) / aux_afrac_x(i,j,k)
675  : zero;
676  aux_fcent_y(i,j,k,0) = lo_centLo_y[0]; // x
677  aux_fcent_y(i,j,k,1) = lo_centLo_y[2]; // z
678  aux_fcent_z(i,j,k,0) = (aux_afrac_z(i,j,k) > zero) // x
679  ? ( lo_areaLo_z * lo_centLo_z[0]
680  + hi_areaLo_z * hi_centLo_z[0] ) / aux_afrac_z(i,j,k)
681  : zero;
682  aux_fcent_z(i,j,k,1) = (aux_afrac_z(i,j,k) > zero) // y (mapped)
683  ? ( lo_areaLo_z * (lo_centLo_z[1] - myhalf)
684  + hi_areaLo_z * (hi_centLo_z[1] + myhalf) ) / aux_afrac_z(i,j,k)
685  : zero;
686  } else if (a_idim == 2) {
687  aux_fcent_x(i,j,k,0) = (aux_afrac_x(i,j,k) > zero) // y
688  ? ( lo_areaLo_x * lo_centLo_x[1]
689  + hi_areaLo_x * hi_centLo_x[1] ) / aux_afrac_x(i,j,k)
690  : zero;
691  aux_fcent_x(i,j,k,1) = (aux_afrac_x(i,j,k) > zero) // z (mapped)
692  ? ( lo_areaLo_x * (lo_centLo_x[2] - myhalf)
693  + hi_areaLo_x * (hi_centLo_x[2] + myhalf) ) / aux_afrac_x(i,j,k)
694  : zero;
695  aux_fcent_y(i,j,k,0) = (aux_afrac_y(i,j,k) > zero) // x
696  ? ( lo_areaLo_y * lo_centLo_y[0]
697  + hi_areaLo_y * hi_centLo_y[0] ) / aux_afrac_y(i,j,k)
698  : zero;
699  aux_fcent_y(i,j,k,1) = (aux_afrac_y(i,j,k) > zero) // z (mapped)
700  ? ( lo_areaLo_y * (lo_centLo_y[2] - myhalf)
701  + hi_areaLo_y * (hi_centLo_y[2] + myhalf) ) / aux_afrac_y(i,j,k)
702  : zero;
703  aux_fcent_z(i,j,k,0) = lo_centLo_z[0]; // x
704  aux_fcent_z(i,j,k,1) = lo_centLo_z[1]; // y
705  }
706 
707  if (i==bx.bigEnd(0)) {
708  Real lo_areaHi_x {lo_eb_cc.areaHi(0)};
709  Real hi_areaHi_x {hi_eb_cc.areaHi(0)};
710  RealVect lo_centHi_x {lo_eb_cc.centHi(0)};
711  RealVect hi_centHi_x {hi_eb_cc.centHi(0)};
712  if (a_idim == 0) {
713  aux_fcent_x(i+1,j,k,0) = hi_centHi_x[1]; // y
714  aux_fcent_x(i+1,j,k,1) = hi_centHi_x[2]; // z
715  } else if (a_idim == 1) {
716  aux_fcent_x(i+1,j,k,0) = (aux_afrac_x(i+1,j,k) > zero) // y (mapped)
717  ? ( lo_areaHi_x * (lo_centHi_x[1] - myhalf)
718  + hi_areaHi_x * (hi_centHi_x[1] + myhalf) ) / aux_afrac_x(i+1,j,k)
719  : zero;
720  aux_fcent_x(i+1,j,k,1) = (aux_afrac_x(i+1,j,k) > zero) // z
721  ? ( lo_areaHi_x * lo_centHi_x[2]
722  + hi_areaHi_x * hi_centHi_x[2] ) / aux_afrac_x(i+1,j,k)
723  : zero;
724  } else if (a_idim == 2) {
725  aux_fcent_x(i+1,j,k,0) = (aux_afrac_x(i+1,j,k) > zero) // y
726  ? ( lo_areaHi_x * lo_centHi_x[1]
727  + hi_areaHi_x * hi_centHi_x[1] ) / aux_afrac_x(i+1,j,k)
728  : zero;
729  aux_fcent_x(i+1,j,k,1) = (aux_afrac_x(i+1,j,k) > zero) // z (mapped)
730  ? ( lo_areaHi_x * (lo_centHi_x[2] - myhalf)
731  + hi_areaHi_x * (hi_centHi_x[2] + myhalf) ) / aux_afrac_x(i+1,j,k)
732  : zero;
733  }
734  }
735  if (j==bx.bigEnd(1)) {
736  Real lo_areaHi_y {lo_eb_cc.areaHi(1)};
737  Real hi_areaHi_y {hi_eb_cc.areaHi(1)};
738  RealVect lo_centHi_y {lo_eb_cc.centHi(1)};
739  RealVect hi_centHi_y {hi_eb_cc.centHi(1)};
740  if (a_idim == 0) {
741  aux_fcent_y(i,j+1,k,0) = (aux_afrac_y(i,j+1,k) > zero) // x (mapped)
742  ? ( lo_areaHi_y * (lo_centHi_y[0] - myhalf)
743  + hi_areaHi_y * (hi_centHi_y[0] + myhalf) ) / aux_afrac_y(i,j+1,k)
744  : zero;
745  aux_fcent_y(i,j+1,k,1) = (aux_afrac_y(i,j+1,k) > zero) // z
746  ? ( lo_areaHi_y * lo_centHi_y[2]
747  + hi_areaHi_y * hi_centHi_y[2] ) / aux_afrac_y(i,j+1,k)
748  : zero;
749  } else if (a_idim == 1) {
750  aux_fcent_y(i,j+1,k,0) = lo_centHi_y[0]; // x
751  aux_fcent_y(i,j+1,k,1) = lo_centHi_y[2]; // z
752  } else if (a_idim == 2) {
753  aux_fcent_y(i,j+1,k,0) = (aux_afrac_y(i,j+1,k) > zero) // x
754  ? ( lo_areaHi_y * lo_centHi_y[0]
755  + hi_areaHi_y * hi_centHi_y[0] ) / aux_afrac_y(i,j+1,k)
756  : zero;
757  aux_fcent_y(i,j+1,k,1) = (aux_afrac_y(i,j+1,k) > zero) // z (mapped)
758  ? ( lo_areaHi_y * (lo_centHi_y[2] - myhalf)
759  + hi_areaHi_y * (hi_centHi_y[2] + myhalf) ) / aux_afrac_y(i,j+1,k)
760  : zero;
761  }
762  }
763  if (k==bx.bigEnd(2)) {
764  Real lo_areaHi_z {lo_eb_cc.areaHi(2)};
765  Real hi_areaHi_z {hi_eb_cc.areaHi(2)};
766  RealVect lo_centHi_z {lo_eb_cc.centHi(2)};
767  RealVect hi_centHi_z {hi_eb_cc.centHi(2)};
768  if (a_idim == 0) {
769  aux_fcent_z(i,j,k+1,0) = (aux_afrac_z(i,j,k+1) > zero) // x (mapped)
770  ? ( lo_areaHi_z * (lo_centHi_z[0] - myhalf)
771  + hi_areaHi_z * (hi_centHi_z[0] + myhalf) ) / aux_afrac_z(i,j,k+1)
772  : zero;
773  aux_fcent_z(i,j,k+1,1) = (aux_afrac_z(i,j,k+1) > zero) // y
774  ? ( lo_areaHi_z * lo_centHi_z[1]
775  + hi_areaHi_z * hi_centHi_z[1] ) / aux_afrac_z(i,j,k+1)
776  : zero;
777  } else if (a_idim == 1) {
778  aux_fcent_z(i,j,k+1,0) = (aux_afrac_z(i,j,k+1) > zero) // x
779  ? ( lo_areaHi_z * lo_centHi_z[0]
780  + hi_areaHi_z * hi_centHi_z[0] ) / aux_afrac_z(i,j,k+1)
781  : zero;
782  aux_fcent_z(i,j,k+1,1) = (aux_afrac_z(i,j,k+1) > zero) // y (mapped)
783  ? ( lo_areaHi_z * (lo_centHi_z[1] - myhalf)
784  + hi_areaHi_z * (hi_centHi_z[1] + myhalf) ) / aux_afrac_z(i,j,k+1)
785  : zero;
786  } else if (a_idim == 2) {
787  aux_fcent_z(i,j,k+1,0) = lo_centHi_z[0]; // x
788  aux_fcent_z(i,j,k+1,1) = lo_centHi_z[1]; // y
789  }
790  }
791 
792  // 5. Boundary Area
793 
794  Real lo_areaBoun {lo_eb_cc.areaBoun()};
795  Real hi_areaBoun {hi_eb_cc.areaBoun()};
796 
797  aux_barea(i,j,k) = lo_areaBoun + hi_areaBoun;
798 
799  // 6. Boundary Centroid
800 
801  RealVect lo_centBoun {lo_eb_cc.centBoun()};
802  RealVect hi_centBoun {hi_eb_cc.centBoun()};
803 
804  if (a_idim == 0) {
805  aux_bcent(i,j,k,0) = ( lo_areaBoun * (lo_centBoun[0]-myhalf) + hi_areaBoun * (hi_centBoun[0]+myhalf) ) / aux_barea(i,j,k); // x (mapped)
806  aux_bcent(i,j,k,1) = ( lo_areaBoun * lo_centBoun[1] + hi_areaBoun * hi_centBoun[1] ) / aux_barea(i,j,k); // y
807  aux_bcent(i,j,k,2) = ( lo_areaBoun * lo_centBoun[2] + hi_areaBoun * hi_centBoun[2] ) / aux_barea(i,j,k); // z
808  } else if (a_idim == 1) {
809  aux_bcent(i,j,k,0) = ( lo_areaBoun * lo_centBoun[0] + hi_areaBoun * hi_centBoun[0] ) / aux_barea(i,j,k); // x
810  aux_bcent(i,j,k,1) = ( lo_areaBoun * (lo_centBoun[1]-myhalf) + hi_areaBoun * (hi_centBoun[1]+myhalf) ) / aux_barea(i,j,k); // y (mapped)
811  aux_bcent(i,j,k,2) = ( lo_areaBoun * lo_centBoun[2] + hi_areaBoun * hi_centBoun[2] ) / aux_barea(i,j,k); // z
812  } else if (a_idim == 2) {
813  aux_bcent(i,j,k,0) = ( lo_areaBoun * lo_centBoun[0] + hi_areaBoun * hi_centBoun[0] ) / aux_barea(i,j,k); // x
814  aux_bcent(i,j,k,1) = ( lo_areaBoun * lo_centBoun[1] + hi_areaBoun * hi_centBoun[1] ) / aux_barea(i,j,k); // y
815  aux_bcent(i,j,k,2) = ( lo_areaBoun * (lo_centBoun[2]-myhalf) + hi_areaBoun * (hi_centBoun[2]+myhalf) ) / aux_barea(i,j,k); // z (mapped)
816  }
817 
818  // 7. Boundary Normal
819 
820  RealVect eb_normal = ( lo_areaBoun * lo_normal + hi_areaBoun * hi_normal )/ aux_barea(i,j,k);
821 
822  aux_bnorm(i,j,k,0) = eb_normal[0];
823  aux_bnorm(i,j,k,1) = eb_normal[1];
824  aux_bnorm(i,j,k,2) = eb_normal[2];
825 
826  }
827 
828  } // flag(iv_lo) and flag(iv_hi)
829 
830  });
831 
832  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
833  {
834  if (aux_vfrac(i,j,k) < small_volfrac)
835  {
836  aux_vfrac(i,j,k) = zero;
837  }
838  });
839 
840  } // if (FlagFab[mfi].getType(bx) == FabType::singlevalued )
841 
842  } // MFIter
843 
844  // We FillBoundary volfrac here so that we can use tests on volfrac in ghost cells below
845  m_volfrac->FillBoundary(a_geom.periodicity());
846 
847  for (MFIter mfi(*m_cellflags, false); mfi.isValid(); ++mfi) {
848 
849  const Box& bx = mfi.validbox();
850  const Box& bx_grown = mfi.growntilebox();
851 
852  Array4<EBCellFlag> const& aux_flag = m_cellflags->array(mfi);
853  Array4<Real> const& aux_vfrac = m_volfrac->array(mfi);
854  Array4<Real> const& aux_afrac_x = m_areafrac[0]->array(mfi);
855  Array4<Real> const& aux_afrac_y = m_areafrac[1]->array(mfi);
856  Array4<Real> const& aux_afrac_z = m_areafrac[2]->array(mfi);
857  Array4<Real> const& aux_afrac_idim = m_areafrac[a_idim]->array(mfi);
858 
859  Array4<Real> const& aux_vcent = m_volcent->array(mfi);
860  Array4<Real> const& aux_fcent_x = m_facecent[0]->array(mfi);
861  Array4<Real> const& aux_fcent_y = m_facecent[1]->array(mfi);
862  Array4<Real> const& aux_fcent_z = m_facecent[2]->array(mfi);
863  Array4<Real> const& aux_barea = m_bndryarea->array(mfi);
864  Array4<Real> const& aux_bcent = m_bndrycent->array(mfi);
865  Array4<Real> const& aux_bnorm = m_bndrynorm->array(mfi);
866 
867  if (FlagFab[mfi].getType(bx) == FabType::singlevalued ) {
868 
869  // Corrections for small cells
870  Box my_xbx(bx); my_xbx.growHi(0,1);
871  int xbx_lo = my_xbx.smallEnd(0);
872  int xbx_hi = my_xbx.bigEnd(0);
873  ParallelFor(my_xbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
874  {
875  if ((i == xbx_lo && aux_vfrac(i,j,k) < small_volfrac) ||
876  (i == xbx_hi && aux_vfrac(i-1,j,k) < small_volfrac) ||
877  (i > xbx_lo && i < xbx_hi &&
878  (aux_vfrac(i,j,k) < small_volfrac || aux_vfrac(i-1,j,k) < small_volfrac))) {
879  aux_afrac_x(i,j,k) = zero;
880  }
881  });
882 
883  Box my_ybx(bx); my_ybx.growHi(1,1);
884  int ybx_lo = my_ybx.smallEnd(1);
885  int ybx_hi = my_ybx.bigEnd(1);
886  ParallelFor(my_ybx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
887  {
888  if ((j == ybx_lo && aux_vfrac(i,j,k) < small_volfrac) ||
889  (j == ybx_hi && aux_vfrac(i,j-1,k) < small_volfrac) ||
890  (j > ybx_lo && j < ybx_hi &&
891  (aux_vfrac(i,j,k) < small_volfrac || aux_vfrac(i,j-1,k) < small_volfrac))) {
892  aux_afrac_y(i,j,k) = zero;
893  }
894  });
895 
896  Box my_zbx(bx); my_zbx.growHi(2,1);
897  int zbx_lo = my_zbx.smallEnd(2);
898  int zbx_hi = my_zbx.bigEnd(2);
899  ParallelFor(my_zbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
900  {
901  if ((k == zbx_lo && aux_vfrac(i,j,k) < small_volfrac) ||
902  (k == zbx_hi && aux_vfrac(i,j,k-1) < small_volfrac) ||
903  (k > zbx_lo && k < zbx_hi &&
904  (aux_vfrac(i,j,k) < small_volfrac || aux_vfrac(i,j,k-1) < small_volfrac))) {
905  aux_afrac_z(i,j,k) = zero;
906  }
907  });
908 
909  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
910  {
911  if (aux_vfrac(i,j,k) < small_volfrac)
912  {
913  aux_vcent(i,j,k,0) = zero;
914  aux_vcent(i,j,k,1) = zero;
915  aux_vcent(i,j,k,2) = zero;
916 
917  aux_fcent_x(i ,j ,k ,0) = zero;
918  aux_fcent_x(i ,j ,k ,1) = zero;
919  aux_fcent_x(i+1,j ,k ,0) = zero;
920  aux_fcent_x(i+1,j ,k ,1) = zero;
921 
922  aux_fcent_y(i ,j ,k ,0) = zero;
923  aux_fcent_y(i ,j ,k ,1) = zero;
924  aux_fcent_y(i ,j+1,k ,0) = zero;
925  aux_fcent_y(i ,j+1,k ,1) = zero;
926 
927  aux_fcent_z(i ,j ,k ,0) = zero;
928  aux_fcent_z(i ,j ,k ,1) = zero;
929  aux_fcent_z(i ,j ,k+1,0) = zero;
930  aux_fcent_z(i ,j ,k+1,1) = zero;
931 
932  aux_barea(i,j,k) = zero;
933 
934  aux_bcent(i,j,k,0) = zero;
935  aux_bcent(i,j,k,1) = zero;
936  aux_bcent(i,j,k,2) = zero;
937 
938  aux_bnorm(i,j,k,0) = zero;
939  aux_bnorm(i,j,k,1) = zero;
940  aux_bnorm(i,j,k,2) = zero;
941 
942  aux_flag(i,j,k).setCovered();
943  }
944 
945  if (std::abs(aux_vcent(i,j,k,0)) < small_value) aux_vcent(i,j,k,0) = zero;
946  if (std::abs(aux_vcent(i,j,k,1)) < small_value) aux_vcent(i,j,k,1) = zero;
947  if (std::abs(aux_vcent(i,j,k,2)) < small_value) aux_vcent(i,j,k,2) = zero;
948  if (std::abs(aux_bcent(i,j,k,0)) < small_value) aux_bcent(i,j,k,0) = zero;
949  if (std::abs(aux_bcent(i,j,k,1)) < small_value) aux_bcent(i,j,k,1) = zero;
950  if (std::abs(aux_bcent(i,j,k,2)) < small_value) aux_bcent(i,j,k,2) = zero;
951  });
952 
953  // Area fraction MultiFab has one more slice at bigEnd(idim),
954  // and this slice is not filled by fillBoundary(), for higher levels.
955  // (Lower level might be filled by fillBoundary().)
956  // Fill the ghost region for the last slice at bigEnd(idim)
957  // by the value of the nearest point. And let fillBoundary() overwrite it.
958 
959  Box upper_slab = makeSlab(bx_grown, a_idim, bx.bigEnd(a_idim)+1);
960  Box bx_grown_1 = bx; bx_grown_1.grow(a_idim,1);
961  BoxList slab_diffList = boxDiff(upper_slab, bx_grown_1);
962 
963  for (const Box& b : slab_diffList) {
964  ParallelFor(b, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
965  {
966  IntVect iv(AMREX_D_DECL(i,j,k));
967  IntVect iv_nearest = iv;
968  for (int d=0; d<AMREX_SPACEDIM; ++d) {
969  iv_nearest[d] = Clamp(iv[d], bx_grown_1.smallEnd(d), bx_grown_1.bigEnd(d));
970  }
971  aux_afrac_idim(iv) = aux_afrac_idim(iv_nearest);
972  });
973  }
974 
975  } // if (FlagFab[mfi].getType(bx) == FabType::singlevalued )
976 
977  } // MFIter
978 
979  // Fill Boundary
980 
981  // The FB call for volfrac is done above
982  // m_volfrac->FillBoundary(a_geom.periodicity());
983 
984  m_volcent->FillBoundary(a_geom.periodicity());
985  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
986  m_areafrac[idim]->FillBoundary(a_geom.periodicity());
987  m_facecent[idim]->FillBoundary(a_geom.periodicity());
988  }
989  m_bndryarea->FillBoundary(a_geom.periodicity());
990  m_bndrycent->FillBoundary(a_geom.periodicity());
991  m_bndrynorm->FillBoundary(a_geom.periodicity());
992 
993  // Set Connectivities
994  for (MFIter mfi(*m_cellflags, false); mfi.isValid(); ++mfi) {
995 
996  const Box& bx = mfi.validbox();
997  const Box domain = surroundingNodes(a_geom.Domain(), a_idim);
998 
999  if (FlagFab[mfi].getType(bx) == FabType::singlevalued ) {
1000 
1001  Array4<EBCellFlag> const& aux_flag = m_cellflags->array(mfi);
1002  Array4<Real> const& aux_afrac_x = m_areafrac[0]->array(mfi);
1003  Array4<Real> const& aux_afrac_y = m_areafrac[1]->array(mfi);
1004  Array4<Real> const& aux_afrac_z = m_areafrac[2]->array(mfi);
1005 
1006  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1007  {
1008  EB2::build_cellflag_from_ap (i, j, k, aux_flag, aux_afrac_x, aux_afrac_y, aux_afrac_z);
1009  });
1010 
1011  // Set disconnected non-periodicfaces
1012 
1013  bool l_periodic_x = a_geom.isPeriodic(0);
1014  bool l_periodic_y = a_geom.isPeriodic(1);
1015  bool l_periodic_z = a_geom.isPeriodic(2);
1016 
1017  if (!l_periodic_x) {
1018  const Box dom_grown = grow(grow(domain,1,1),2,1);
1019  const Box bx_grown = grow(grow( bx,1,1),2,1);
1020  const Box bx_face_x_lo = bx_grown & makeSlab(dom_grown,0,domain.smallEnd(0));
1021  const Box bx_face_x_hi = bx_grown & makeSlab(dom_grown,0,domain.bigEnd(0));
1022 
1023  ParallelFor(bx_face_x_lo, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1024  {
1025  for(int kk(-1); kk<=1; kk++) {
1026  for(int jj(-1); jj<=1; jj++) {
1027  aux_flag(i,j,k).setDisconnected(-1,jj,kk);
1028  }}
1029  });
1030  ParallelFor(bx_face_x_hi, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1031  {
1032  for(int kk(-1); kk<=1; kk++) {
1033  for(int jj(-1); jj<=1; jj++) {
1034  aux_flag(i,j,k).setDisconnected( 1,jj,kk);
1035  }}
1036  });
1037  }
1038 
1039  if (!l_periodic_y) {
1040  const Box dom_grown = grow(grow(domain,0,1),2,1);
1041  const Box bx_grown = grow(grow( bx,0,1),2,1);
1042  const Box bx_face_y_lo = bx_grown & makeSlab(dom_grown,1,domain.smallEnd(1));
1043  const Box bx_face_y_hi = bx_grown & makeSlab(dom_grown,1,domain.bigEnd(1));
1044 
1045  ParallelFor(bx_face_y_lo, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1046  {
1047  for(int kk(-1); kk<=1; kk++) {
1048  for(int ii(-1); ii<=1; ii++) {
1049  aux_flag(i,j,k).setDisconnected(ii,-1,kk);
1050  }}
1051  });
1052  ParallelFor(bx_face_y_hi, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1053  {
1054  for(int kk(-1); kk<=1; kk++) {
1055  for(int ii(-1); ii<=1; ii++) {
1056  aux_flag(i,j,k).setDisconnected(ii, 1,kk);
1057  }}
1058  });
1059  }
1060 
1061  if (!l_periodic_z) {
1062  const Box dom_grown = grow(grow(domain,0,1),1,1);
1063  const Box bx_grown = grow(grow( bx,0,1),1,1);
1064  const Box bx_face_z_lo = bx_grown & makeSlab(dom_grown,2,domain.smallEnd(2));
1065  const Box bx_face_z_hi = bx_grown & makeSlab(dom_grown,2,domain.bigEnd(2));
1066 
1067  ParallelFor(bx_face_z_lo, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1068  {
1069  for(int jj(-1); jj<=1; jj++) {
1070  for(int ii(-1); ii<=1; ii++) {
1071  aux_flag(i,j,k).setDisconnected(ii,jj,-1);
1072  }}
1073  });
1074  ParallelFor(bx_face_z_hi, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1075  {
1076  for(int jj(-1); jj<=1; jj++) {
1077  for(int ii(-1); ii<=1; ii++) {
1078  aux_flag(i,j,k).setDisconnected(ii,jj, 1);
1079  }}
1080  });
1081  }
1082 
1083  } // FabType::singlevalued
1084 
1085  } // MFIter
1086 
1087  // Set disconnected zero-volume-fraction cells
1088  // (equivalent to eb_::set_connection_flags for CC grids)
1089 
1090  for (MFIter mfi(*m_cellflags, false); mfi.isValid(); ++mfi) {
1091 
1092  const Box& bx = mfi.validbox();
1093  const Box gbx = amrex::grow(bx, m_cellflags->nGrow()-1); // Leave one cell layer
1094 
1095  Array4<EBCellFlag> const& aux_flag = m_cellflags->array(mfi);
1096  Array4<Real> const& aux_vfrac = m_volfrac->array(mfi);
1097 
1098  ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1099  {
1100  for(int kk(-1); kk<=1; kk++) {
1101  for(int jj(-1); jj<=1; jj++) {
1102  for(int ii(-1); ii<=1; ii++)
1103  {
1104  if (aux_vfrac(i+ii,j+jj,k+kk) == zero) {
1105  aux_flag(i,j,k).setDisconnected(ii,jj,kk);
1106  }
1107  }}}
1108  });
1109 
1110  ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
1111  {
1112  if (aux_vfrac(i,j,k)==zero) {
1113  aux_flag(i,j,k).setCovered();
1114  }
1115  });
1116 
1117  } // MFIter
1118 
1119  // Fill Boundary
1120 
1121  m_cellflags->FillBoundary(a_geom.periodicity());
1122 
1123 #if 0
1124  // We leave these here for debugging if necessary.
1125  // If you uncomment these, make sure to uncomment AMReX_VisMF include above
1126  if (a_idim == 0) {
1127  amrex::VisMF::Write(*m_volfrac,"UVOL");
1128  amrex::VisMF::Write(*m_areafrac[0],"UAREAX");
1129  amrex::VisMF::Write(*m_areafrac[1],"UAREAY");
1130  amrex::VisMF::Write(*m_areafrac[2],"UAREAZ");
1131  } else if (a_idim == 1) {
1132  amrex::VisMF::Write(*m_volfrac,"VVOL");
1133  amrex::VisMF::Write(*m_areafrac[0],"VAREAX");
1134  amrex::VisMF::Write(*m_areafrac[1],"VAREAY");
1135  amrex::VisMF::Write(*m_areafrac[2],"VAREAZ");
1136  } else {
1137  amrex::VisMF::Write(*m_volfrac,"WVOL");
1138  amrex::VisMF::Write(*m_areafrac[0],"WAREAX");
1139  amrex::VisMF::Write(*m_areafrac[1],"WAREAY");
1140  amrex::VisMF::Write(*m_areafrac[2],"WAREAZ");
1141  }
1142 #endif
1143 }
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
ParmParse pp("prob")
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
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);})
constexpr amrex::Real real_eps
Definition: ERF_NumericalConstants.H:27
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:30
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:29
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:34
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::Array< std::unique_ptr< amrex::MultiFab >, AMREX_SPACEDIM > m_areafrac
Definition: ERF_EBAux.H:92
std::unique_ptr< amrex::MultiFab > m_bndrynorm
Definition: ERF_EBAux.H:90
std::unique_ptr< amrex::MultiFab > m_bndrycent
Definition: ERF_EBAux.H:89
std::unique_ptr< amrex::FabArray< amrex::EBCellFlagFab > > m_cellflags
Definition: ERF_EBAux.H:85
std::unique_ptr< amrex::MultiFab > m_bndryarea
Definition: ERF_EBAux.H:88
amrex::Array< std::unique_ptr< amrex::MultiFab >, AMREX_SPACEDIM > m_facecent
Definition: ERF_EBAux.H:93
std::unique_ptr< amrex::MultiFab > m_volcent
Definition: ERF_EBAux.H:87
std::unique_ptr< amrex::MultiFab > m_volfrac
Definition: ERF_EBAux.H:86
Reconstructs geometric moments for one EB cut cell.
Definition: ERF_EBCutCell.H:69
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12

Referenced by eb_::make_all_factories().

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

◆ getAreaFrac()

Array< const MultiFab *, AMREX_SPACEDIM > eb_aux_::getAreaFrac ( ) const

Return reconstructed area fractions for all coordinate directions.

1189 {
1190  AMREX_ASSERT(m_areafrac[0] != nullptr);
1191  return {AMREX_D_DECL(m_areafrac[0].get(), m_areafrac[1].get(), m_areafrac[2].get())};
1192 }
pp get("wavelength", wavelength)
Here is the call graph for this function:

◆ getBndryArea()

const MultiFab & eb_aux_::getBndryArea ( ) const

Return the reconstructed EB boundary areas.

1168 {
1169  AMREX_ASSERT(m_bndryarea != nullptr);
1170  return *m_bndryarea;
1171 }

◆ getBndryCent()

const MultiFab & eb_aux_::getBndryCent ( ) const

Return the reconstructed EB boundary centroids.

1175 {
1176  AMREX_ASSERT(m_bndrycent != nullptr);
1177  return *m_bndrycent;
1178 }

◆ getBndryNormal()

const MultiFab & eb_aux_::getBndryNormal ( ) const

Return the reconstructed EB boundary normals.

1182 {
1183  AMREX_ASSERT(m_bndrynorm != nullptr);
1184  return *m_bndrynorm;
1185 }

◆ getCentroid()

const MultiFab & eb_aux_::getCentroid ( ) const

Return the reconstructed volume centroids.

1161 {
1162  AMREX_ASSERT(m_volcent != nullptr);
1163  return *m_volcent;
1164 }

◆ getFaceCent()

Array< const MultiFab *, AMREX_SPACEDIM > eb_aux_::getFaceCent ( ) const

Return reconstructed face centroids for all coordinate directions.

1196 {
1197  AMREX_ASSERT(m_facecent[0] != nullptr);
1198  return {AMREX_D_DECL(m_facecent[0].get(), m_facecent[1].get(), m_facecent[2].get())};
1199 }
Here is the call graph for this function:

◆ getMultiEBCellFlagFab()

const FabArray< EBCellFlagFab > & eb_aux_::getMultiEBCellFlagFab ( ) const

Return the reconstructed EB cell flags.

1147 {
1148  AMREX_ASSERT(m_cellflags != nullptr);
1149  return *m_cellflags;
1150 }

Referenced by AdvectionSrcForMom_EB(), compute_gradp_xy(), compute_gradp_z(), and DiffusionSrcForMom_EB().

Here is the caller graph for this function:

◆ getVolFrac()

const MultiFab & eb_aux_::getVolFrac ( ) const

Return the reconstructed volume fractions.

1154 {
1155  AMREX_ASSERT(m_volfrac != nullptr);
1156  return *m_volfrac;
1157 }

◆ set_verbose()

void eb_aux_::set_verbose ( )
inline

Enable verbose diagnostic output during factory construction.

56 { m_verbose = 1; }

Member Data Documentation

◆ m_areafrac

amrex::Array<std::unique_ptr<amrex::MultiFab>,AMREX_SPACEDIM> eb_aux_::m_areafrac
private

Referenced by define(), and getAreaFrac().

◆ m_bndryarea

std::unique_ptr<amrex::MultiFab> eb_aux_::m_bndryarea
private

Referenced by define(), and getBndryArea().

◆ m_bndrycent

std::unique_ptr<amrex::MultiFab> eb_aux_::m_bndrycent
private

Referenced by define(), and getBndryCent().

◆ m_bndrynorm

std::unique_ptr<amrex::MultiFab> eb_aux_::m_bndrynorm
private

Referenced by define(), and getBndryNormal().

◆ m_cellflags

std::unique_ptr<amrex::FabArray<amrex::EBCellFlagFab> > eb_aux_::m_cellflags
private

Referenced by define(), and getMultiEBCellFlagFab().

◆ m_facecent

amrex::Array<std::unique_ptr<amrex::MultiFab>,AMREX_SPACEDIM> eb_aux_::m_facecent
private

Referenced by define(), and getFaceCent().

◆ m_verbose

int eb_aux_::m_verbose
private

Referenced by define(), and set_verbose().

◆ m_volcent

std::unique_ptr<amrex::MultiFab> eb_aux_::m_volcent
private

Referenced by define(), and getCentroid().

◆ m_volfrac

std::unique_ptr<amrex::MultiFab> eb_aux_::m_volfrac
private

Referenced by define(), and getVolFrac().


The documentation for this class was generated from the following files: