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_ ()
 Destroy the auxiliary EB factory. 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
 
amrex::FabArray< amrex::EBCellFlagFab > * m_cellflags = nullptr
 
amrex::MultiFab * m_volfrac = nullptr
 
amrex::MultiFab * m_volcent = nullptr
 
amrex::MultiFab * m_bndryarea = nullptr
 
amrex::MultiFab * m_bndrycent = nullptr
 
amrex::MultiFab * m_bndrynorm = nullptr
 
amrex::Array< amrex::MultiFab *, AMREX_SPACEDIM > m_areafrac {{AMREX_D_DECL(nullptr, nullptr, nullptr)}}
 
amrex::Array< amrex::MultiFab *, AMREX_SPACEDIM > m_facecent {{AMREX_D_DECL(nullptr, nullptr, nullptr)}}
 

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.

23  : m_verbose(0)
24 // ,m_defined(0)
25 {}
int m_verbose
Definition: ERF_EBAux.H:71

◆ ~eb_aux_()

eb_aux_::~eb_aux_ ( )

Destroy the auxiliary EB factory.

18 {
19 }

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.

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

1192 {
1193  AMREX_ASSERT(m_areafrac[0] != nullptr);
1194  return {AMREX_D_DECL(m_areafrac[0], m_areafrac[1], m_areafrac[2])};
1195 }

◆ getBndryArea()

const MultiFab & eb_aux_::getBndryArea ( ) const

Return the reconstructed EB boundary areas.

1171 {
1172  AMREX_ASSERT(m_bndryarea != nullptr);
1173  return *m_bndryarea;
1174 }

◆ getBndryCent()

const MultiFab & eb_aux_::getBndryCent ( ) const

Return the reconstructed EB boundary centroids.

1178 {
1179  AMREX_ASSERT(m_bndrycent != nullptr);
1180  return *m_bndrycent;
1181 }

◆ getBndryNormal()

const MultiFab & eb_aux_::getBndryNormal ( ) const

Return the reconstructed EB boundary normals.

1185 {
1186  AMREX_ASSERT(m_bndrynorm != nullptr);
1187  return *m_bndrynorm;
1188 }

◆ getCentroid()

const MultiFab & eb_aux_::getCentroid ( ) const

Return the reconstructed volume centroids.

1164 {
1165  AMREX_ASSERT(m_volcent != nullptr);
1166  return *m_volcent;
1167 }

◆ getFaceCent()

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

Return reconstructed face centroids for all coordinate directions.

1199 {
1200  AMREX_ASSERT(m_facecent[0] != nullptr);
1201  return {AMREX_D_DECL(m_facecent[0], m_facecent[1], m_facecent[2])};
1202 }

◆ getMultiEBCellFlagFab()

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

Return the reconstructed EB cell flags.

1150 {
1151  AMREX_ASSERT(m_cellflags != nullptr);
1152  return *m_cellflags;
1153 }

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.

1157 {
1158  AMREX_ASSERT(m_volfrac != nullptr);
1159  return *m_volfrac;
1160 }

◆ set_verbose()

void eb_aux_::set_verbose ( )
inline

Enable verbose diagnostic output during factory construction.

49 { m_verbose = 1; }

Member Data Documentation

◆ m_areafrac

amrex::Array<amrex::MultiFab*,AMREX_SPACEDIM> eb_aux_::m_areafrac {{AMREX_D_DECL(nullptr, nullptr, nullptr)}}
private

Referenced by define(), and getAreaFrac().

◆ m_bndryarea

amrex::MultiFab* eb_aux_::m_bndryarea = nullptr
private

Referenced by define(), and getBndryArea().

◆ m_bndrycent

amrex::MultiFab* eb_aux_::m_bndrycent = nullptr
private

Referenced by define(), and getBndryCent().

◆ m_bndrynorm

amrex::MultiFab* eb_aux_::m_bndrynorm = nullptr
private

Referenced by define(), and getBndryNormal().

◆ m_cellflags

amrex::FabArray<amrex::EBCellFlagFab>* eb_aux_::m_cellflags = nullptr
private

Referenced by define(), and getMultiEBCellFlagFab().

◆ m_facecent

amrex::Array<amrex::MultiFab*,AMREX_SPACEDIM> eb_aux_::m_facecent {{AMREX_D_DECL(nullptr, nullptr, nullptr)}}
private

Referenced by define(), and getFaceCent().

◆ m_verbose

int eb_aux_::m_verbose
private

Referenced by define(), and set_verbose().

◆ m_volcent

amrex::MultiFab* eb_aux_::m_volcent = nullptr
private

Referenced by define(), and getCentroid().

◆ m_volfrac

amrex::MultiFab* eb_aux_::m_volfrac = nullptr
private

Referenced by define(), and getVolFrac().


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