ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_EBCutCell.H
Go to the documentation of this file.
1 /**
2  * \file ERF_EBCutCell.H
3  * \brief Defines cut-cell geometry reconstruction from EB plane intersections.
4  */
5 #ifndef ERF_EB_CUT_CELL_H_
6 #define ERF_EB_CUT_CELL_H_
7 
8 #include <AMReX_REAL.H>
9 #include <AMReX_Array.H>
10 #include <AMReX_RealBox.H>
11 #include <AMReX_RealVect.H>
12 #include <AMReX_Algorithm.H>
13 #include <AMReX_EBCellFlag.H>
14 #include <AMReX_GpuPrint.H>
15 
16 #include "ERF_EBPolygon.H"
17 
18 /**
19  * \brief Intersect a plane with a line segment.
20  * \param a_plane_point Point on the plane.
21  * \param a_plane_normal Unit normal for the plane.
22  * \param a_edge_point0 First endpoint of the edge.
23  * \param a_edge_point1 Second endpoint of the edge.
24  * \param[out] a_intersection_point Intersection point when the edge crosses the plane.
25  * \param[out] a_intersection_dist Distance from a_edge_point0 to the intersection.
26  * \return 1 if the segment intersects the plane, otherwise 0.
27  */
28 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
29 int
30 intersect_plane_edge ( amrex::RealVect const& a_plane_point,
31  amrex::RealVect const& a_plane_normal,
32  amrex::RealVect const& a_edge_point0,
33  amrex::RealVect const& a_edge_point1,
34  amrex::RealVect& a_intersection_point,
35  amrex::Real& a_intersection_dist )
36 {
37  amrex::RealVect const edge(a_edge_point1 - a_edge_point0);
38  amrex::Real const edge_length = edge.vectorLength();
39 
40  AMREX_ALWAYS_ASSERT(edge_length > zero);
41 
42  amrex::RealVect edge_normal = edge / edge_length;
43 
44  amrex::Real np_dot_ne = a_plane_normal.dotProduct(edge_normal);
45 
46  // if ( amrex::Math::abs(np_dot_ne) < std::numeric_limits<amrex::Real>::min() )
47  if ( amrex::Math::abs(np_dot_ne) < amrex::Real(10.0) * std::numeric_limits<amrex::Real>::epsilon() )
48  { return 0; }
49 
50  a_intersection_dist = a_plane_normal.dotProduct(a_plane_point)
51  - a_plane_normal.dotProduct(a_edge_point0);
52  a_intersection_dist /= np_dot_ne;
53 
54  a_intersection_point = a_edge_point0 + a_intersection_dist*edge_normal;
55 
56  if (zero <= a_intersection_dist && a_intersection_dist <= edge_length) { return 1;}
57 
58  return 0;
59 }
60 
61 /**
62  * \brief Reconstructs geometric moments for one EB cut cell.
63  *
64  * The class clips a rectangular cell by a planar EB approximation and exposes
65  * volume, face areas, centroids, boundary area, boundary centroid, and boundary
66  * normal data used by auxiliary face-centered EB factories.
67  */
68 class eb_cut_cell_ {
69 
70  public:
71 
72  /**
73  * \brief Construct cut-cell geometry from a cell flag, box, EB point, and EB normal.
74  * \param a_flag AMReX EB cell flag for the cell.
75  * \param a_rbox Physical-space cell box.
76  * \param a_point Point on the EB plane.
77  * \param a_normal Unit normal for the EB plane.
78  */
79  AMREX_GPU_HOST_DEVICE
80  eb_cut_cell_ ( amrex::EBCellFlag const& a_flag,
81  amrex::RealBox const& a_rbox,
82  amrex::RealVect const& a_point,
83  amrex::RealVect const& a_normal );
84 
85  //! Return true if the reconstructed cell is covered.
86  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
87  bool isCovered () const noexcept { return m_flag.isCovered(); }
88 
89  //! Return true if the reconstructed cell is regular.
90  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
91  bool isRegular () const noexcept { return m_flag.isRegular(); }
92 
93  //! Return true if the reconstructed cell is single-valued.
94  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
95  bool isSingleValued () const noexcept { return m_flag.isSingleValued(); }
96 
97  //! Mark the reconstructed cell as covered.
98  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
99  void set_covered () {
100  m_flag.setCovered();
101  }
102 
103  //! Mark the reconstructed cell as regular and fill regular face areas.
104  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
105  void set_regular () {
106 
107  m_flag.setRegular();
108 
109  m_F1.set_area( m_rbox.length(0)*m_rbox.length(1) );
110  m_F3.set_area( m_rbox.length(0)*m_rbox.length(1) );
111 
112  m_F2.set_area( m_rbox.length(1)*m_rbox.length(2) );
113  m_F4.set_area( m_rbox.length(1)*m_rbox.length(2) );
114 
115  m_F5.set_area( m_rbox.length(0)*m_rbox.length(2) );
116  m_F6.set_area( m_rbox.length(0)*m_rbox.length(2) );
117 
119 
120  }
121 
122  //! Return the physical volume of the reconstructed cell.
123  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
124  amrex::Real volume () const {
125 
126  if (m_flag.isCovered() ) { return zero; }
127  if (m_flag.isRegular() ) { return m_rbox.volume(); }
128 
130 
131  amrex::Real const* lo = m_rbox.lo();
132  amrex::RealVect v0(lo[0], lo[1], lo[2]);
133 
134  if (m_F2.ok() ) { volume += m_F2.area() * m_F2.distance(v0); }
135  if (m_F3.ok() ) { volume += m_F3.area() * m_F3.distance(v0); }
136  if (m_F6.ok() ) { volume += m_F6.area() * m_F6.distance(v0); }
137  if (m_F7.ok() ) { volume += m_F7.area() * m_F7.distance(v0); }
138 
139  volume /= three;
140 
141  return m_invert*volume + (one-m_invert)*(m_rbox.volume()-volume);
142  }
143 
144  /**
145  * \brief Return the low-side face area in one coordinate direction.
146  * \param idir Coordinate direction.
147  */
148  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
149  amrex::Real areaLo ( int const idir ) const noexcept {
150  AMREX_ASSERT( idir >=0 && idir < AMREX_SPACEDIM );
151  if (m_flag.isCovered() ) { return zero; }
152  if (m_flag.isRegular() ) { return m_lo_faces[idir]->area(); }
153  amrex::Real const area(m_lo_faces[idir]->area());
154  return m_invert*area + (one-m_invert)*(m_rbox_area[idir] - area);
155  }
156 
157  /**
158  * \brief Return the high-side face area in one coordinate direction.
159  * \param idir Coordinate direction.
160  */
161  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
162  amrex::Real areaHi ( int const idir ) const noexcept {
163  AMREX_ASSERT( idir >= 0 && idir < AMREX_SPACEDIM );
164  if (m_flag.isCovered() ) { return zero; }
165  if (m_flag.isRegular() ) { return m_hi_faces[idir]->area(); }
166  amrex::Real const area(m_hi_faces[idir]->area());
167  return m_invert*area + (one-m_invert)*(m_rbox_area[idir] - area);
168  }
169 
170  //! Return the EB boundary area inside the cell.
171  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
172  amrex::Real areaBoun () const noexcept {
173  return m_F7.area();
174  }
175 
176  /**
177  * \brief Return the low-side face centroid in one coordinate direction.
178  * \param idir Coordinate direction.
179  */
180  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
181  amrex::RealVect centLo ( int const idir ) const noexcept {
182  AMREX_ASSERT( idir >=0 && idir < AMREX_SPACEDIM );
183  amrex::RealVect cent = m_cellface_cent[ m_lo_faces_id[idir] ];
184  if (m_flag.isCovered() || m_flag.isRegular() ) {
185  // Default cent
186  } else {
187  amrex::Real const area_R = m_lo_faces[idir]->area();
188  if (amrex::almostEqual(area_R,zero) || amrex::almostEqual(area_R, m_rbox_area[idir]) ){
189  // Default cent
190  } else {
191  amrex::RealVect cent_O = cent;
192  amrex::RealVect cent_R = m_lo_faces[idir]->get_centroid();
193  amrex::Real const area_C = m_rbox_area[idir] - area_R;
194  cent = m_invert * cent_R + (one-m_invert) * ((one+area_R/area_C)*cent_O - area_R/area_C*cent_R);
195  }
196  }
197  return cent;
198  }
199 
200  /**
201  * \brief Return the high-side face centroid in one coordinate direction.
202  * \param idir Coordinate direction.
203  */
204  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
205  amrex::RealVect centHi ( int const idir ) const noexcept {
206  AMREX_ASSERT( idir >=0 && idir < AMREX_SPACEDIM );
207  amrex::RealVect cent = m_cellface_cent[ m_hi_faces_id[idir] ];
208  if (m_flag.isCovered() || m_flag.isRegular() ) {
209  // Default cent
210  } else {
211  amrex::Real const area_R = m_hi_faces[idir]->area();
212  if (amrex::almostEqual(area_R,zero) || amrex::almostEqual(area_R, m_rbox_area[idir]) ){
213  // Default cent
214  } else {
215  amrex::RealVect cent_O = cent;
216  amrex::RealVect cent_R = m_hi_faces[idir]->get_centroid();
217  amrex::Real const area_C = m_rbox_area[idir] - area_R;
218  cent = m_invert * cent_R + (one-m_invert) * ((one+area_R/area_C)*cent_O - area_R/area_C*cent_R);
219  }
220  }
221  return cent;
222  }
223 
224  //! Return the EB boundary centroid.
225  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
226  amrex::RealVect centBoun () const noexcept {
227  amrex::RealVect cent{zero,zero,zero};
228  if (m_flag.isSingleValued()) {
229  cent = m_F7.get_centroid();
230  }
231  return cent;
232  }
233 
234  //! Return the EB boundary normal.
235  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
236  amrex::RealVect normBoun () const noexcept {
237  amrex::RealVect normal{zero,zero,zero};
238  if (m_flag.isSingleValued()) {
239  normal = m_eb_normal;
240  }
241  return normal;
242  }
243 
244  //! Return the volume centroid of the reconstructed cell.
245  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
246  amrex::RealVect centVol () const noexcept {
247  amrex::RealVect vcent = m_cell_cent;
248  if (m_flag.isSingleValued()) {
249  amrex::Real xm = m_rbox.lo(0);
250  amrex::Real xp = m_rbox.hi(0);
251  amrex::Real ym = m_rbox.lo(1);
252  amrex::Real yp = m_rbox.hi(1);
253  amrex::Real zm = m_rbox.lo(2);
254  amrex::Real zp = m_rbox.hi(2);
255 
256  amrex::Real axm = areaLo(0);
257  amrex::Real axp = areaHi(0);
258  amrex::Real aym = areaLo(1);
259  amrex::Real ayp = areaHi(1);
260  amrex::Real azm = areaLo(2);
261  amrex::Real azp = areaHi(2);
262 
263  amrex::Real barea = m_F7.area();
264  amrex::RealVect bcent = m_F7.get_centroid();
265 
266  amrex::Real vol = volume();
267 
268  vcent[0] = myhalf * ( - xm * xm * axm + xp * xp * axp + bcent[0] * bcent[0] * m_eb_normal[0] * barea ) / vol;
269  vcent[1] = myhalf * ( - ym * ym * aym + yp * yp * ayp + bcent[1] * bcent[1] * m_eb_normal[1] * barea ) / vol;
270  vcent[2] = myhalf * ( - zm * zm * azm + zp * zp * azp + bcent[2] * bcent[2] * m_eb_normal[2] * barea ) / vol;
271  }
272  return vcent;
273  }
274 
275  /**
276  * \brief Print cut-cell diagnostics on CPU builds.
277  * \param a_face Face identifier to report, or -1 for all faces.
278  */
279  void debug ( int const a_face = -1 );
280 
281  private:
282 
283  amrex::RealBox const m_rbox;
284  amrex::RealVect const m_eb_point;
285  amrex::RealVect const m_eb_normal;
286 
288 
289  amrex::RealVect m_rbox_area;
290 
291  amrex::EBCellFlag m_flag;
292 
293  // Cell faces
294 
301 
302  static int constexpr m_max_faces = 6;
303  amrex::Array<amrex::RealVect,m_max_faces> m_cellface_cent; // Centroids of cell faces
304  amrex::RealVect m_cell_cent; // Centroid of cell
305  amrex::RealVect m_dx;
306 
307  // cut face
309 
310  amrex::Array<polygon_ const* const,3> m_lo_faces {&m_F4, &m_F5, &m_F1};
311  amrex::Array<polygon_ const* const,3> m_hi_faces {&m_F2, &m_F6, &m_F3};
312 
313  amrex::Array<int const,3> m_lo_faces_id {3,4,0};
314  amrex::Array<int const,3> m_hi_faces_id {1,5,2};
315 
316  //! Stores precomputed data for one edge-plane intersection path.
317  struct path_data;
318 
319  //! Compute all edge-plane intersections and populate polygon vertices.
320  AMREX_GPU_HOST_DEVICE
321  void calc_edge_intersections ();
322 
323  //! Populate polygon vertices for cells that are fully covered or regular.
324  AMREX_GPU_HOST_DEVICE
326 };
327 
328 AMREX_GPU_HOST_DEVICE
329 AMREX_FORCE_INLINE
331 eb_cut_cell_ ( amrex::EBCellFlag const& a_flag,
332  amrex::RealBox const& a_rbox,
333  amrex::RealVect const& a_point,
334  amrex::RealVect const& a_normal )
335  : m_rbox(a_rbox)
336  , m_eb_point(a_point)
337  , m_eb_normal(a_normal)
338  , m_invert(zero)
339  , m_F1(a_point, a_normal)
340  , m_F2(a_point, a_normal)
341  , m_F3(a_point, a_normal)
342  , m_F4(a_point, a_normal)
343  , m_F5(a_point, a_normal)
344  , m_F6(a_point, a_normal)
345  , m_cellface_cent({amrex::RealVect(zero), amrex::RealVect(zero), amrex::RealVect(zero),
346  amrex::RealVect(zero), amrex::RealVect(zero), amrex::RealVect(zero)})
347 {
348  using namespace amrex;
349 
350  m_rbox_area[0] = m_rbox.length(1)*m_rbox.length(2);
351  m_rbox_area[1] = m_rbox.length(0)*m_rbox.length(2);
352  m_rbox_area[2] = m_rbox.length(0)*m_rbox.length(1);
353 
354  amrex::RealVect v0(m_rbox.lo(0), m_rbox.lo(1), m_rbox.lo(2));
355  amrex::RealVect v1(m_rbox.hi(0), m_rbox.lo(1), m_rbox.lo(2));
356  amrex::RealVect v2(m_rbox.lo(0), m_rbox.hi(1), m_rbox.lo(2));
357  amrex::RealVect v3(m_rbox.lo(0), m_rbox.lo(1), m_rbox.hi(2));
358  amrex::RealVect v4(m_rbox.hi(0), m_rbox.lo(1), m_rbox.hi(2));
359  amrex::RealVect v5(m_rbox.hi(0), m_rbox.hi(1), m_rbox.lo(2));
360  amrex::RealVect v6(m_rbox.lo(0), m_rbox.hi(1), m_rbox.hi(2));
361  amrex::RealVect v7(m_rbox.hi(0), m_rbox.hi(1), m_rbox.hi(2));
362 
363  // Centroids of cell faces
364 
365  m_cellface_cent[0] = fourth * ( v0 + v2 + v5 + v1 ); // F1
366  m_cellface_cent[1] = fourth * ( v1 + v5 + v7 + v4 ); // F2
367  m_cellface_cent[2] = fourth * ( v3 + v4 + v7 + v6 ); // F3
368  m_cellface_cent[3] = fourth * ( v0 + v3 + v6 + v2 ); // F4
369  m_cellface_cent[4] = fourth * ( v0 + v1 + v4 + v3 ); // F5
370  m_cellface_cent[5] = fourth * ( v2 + v5 + v7 + v6 ); // F6
371 
372  // Cell centroid
373 
374  m_cell_cent[0] = myhalf * ( m_rbox.lo(0) + m_rbox.hi(0) );
375  m_cell_cent[1] = myhalf * ( m_rbox.lo(1) + m_rbox.hi(1) );
376  m_cell_cent[2] = myhalf * ( m_rbox.lo(2) + m_rbox.hi(2) );
377 
378  // Cell size
379 
380  m_dx[0] = m_rbox.hi(0) - m_rbox.lo(0);
381  m_dx[1] = m_rbox.hi(1) - m_rbox.lo(1);
382  m_dx[2] = m_rbox.hi(2) - m_rbox.lo(2);
383 
384  if (a_flag.isCovered() ) {
385 
386  set_covered();
387 
388  } else if (a_flag.isRegular() ) {
389 
390  set_regular();
391 
392  } else { // Check that the box and plane intersect.
393 
394  amrex::RealVect c = myhalf*(v0 + v7);
395  amrex::RealVect e = v7 - c;
396 
397  amrex::Real r = e[0]*amrex::Math::abs(a_normal[0]) +
398  e[1]*amrex::Math::abs(a_normal[1]) +
399  e[2]*amrex::Math::abs(a_normal[2]);
400 
401  amrex::Real s = amrex::Math::abs(c.dotProduct(a_normal)
402  - a_point.dotProduct(a_normal));
403 
404  if (s > r) {
405  if ((a_normal.dotProduct(v0) - a_normal.dotProduct(a_point)) > zero)
406  { set_covered(); } else { set_regular(); }
407  } else { m_flag.setSingleValued(); }
408  }
409 
410  if ( m_flag.isSingleValued() ) {
411 
412  m_invert = ((m_eb_normal.dotProduct(v0) - m_eb_normal.dotProduct(m_eb_point)) > zero) ? zero : one;
413 
414  calc_edge_intersections();
415 
416  } // end singleValued
417 
418  m_F1.define();
419  m_F2.define();
420  m_F3.define();
421  m_F4.define();
422  m_F5.define();
423  m_F6.define();
424  m_F7.define();
425 
426  // For covered and regular cut cells, add vertices to utilize e.g., get_centroid.
427  if ( !m_flag.isSingleValued() ) {
428  set_covered_regular_cell_vertices();
429  }
430 
431 }
432 
433 /**
434  * \brief Intersection metadata for one ordered edge path in the cut-cell box.
435  */
437 {
438  //! Construct empty path data.
439  AMREX_GPU_HOST_DEVICE
440  AMREX_FORCE_INLINE
441  path_data() = default;
442 
443  //! Whether the edge intersects the EB plane.
444  bool intersected{};
445  //! Whether the intersection lies on the start vertex.
447  //! Whether the intersection lies on the end vertex.
449  //! Coordinates of the intersection point.
450  amrex::RealVect vIP{};
451  //! Distance from the start vertex to the intersection point.
453  //! Physical length of the edge.
455 
456  /**
457  * \brief Compute and store the intersection data for one edge.
458  * \param eb_point Point on the EB plane.
459  * \param eb_normal Unit normal for the EB plane.
460  * \param v_start First endpoint of the edge.
461  * \param v_end Second endpoint of the edge.
462  */
463  AMREX_GPU_HOST_DEVICE
464  AMREX_FORCE_INLINE
465  void set(const amrex::RealVect& eb_point,
466  const amrex::RealVect& eb_normal,
467  const amrex::RealVect& v_start,
468  const amrex::RealVect& v_end)
469  {
470  constexpr amrex::Real tol = amrex::Real(1.e-15);
471  amrex::RealVect v_intersect{v_start};
472  amrex::Real dist_intersect = std::numeric_limits<amrex::Real>::quiet_NaN();
474  eb_point, eb_normal, v_start, v_end, v_intersect, dist_intersect
475  );
476  vIP = v_intersect;
477  distIP = dist_intersect;
478  edge_length = (v_start - v_end).vectorLength();
479  if (intersected) {
480  // check if intersection is at vertices
481  intersected_start = (amrex::Math::abs(dist_intersect) < tol);
482  intersected_end = (amrex::Math::abs(edge_length - dist_intersect) < tol);
483  } else {
484  intersected_start = false;
485  intersected_end = false;
486  distIP = amrex::Real(-1.0);
487  }
488  }
489 };
490 
491 AMREX_GPU_HOST_DEVICE
492 AMREX_FORCE_INLINE
493 void
496 {
497  using namespace amrex;
498 
499  amrex::RealVect v0(m_rbox.lo(0), m_rbox.lo(1), m_rbox.lo(2));
500  amrex::RealVect v1(m_rbox.hi(0), m_rbox.lo(1), m_rbox.lo(2));
501  amrex::RealVect v2(m_rbox.lo(0), m_rbox.hi(1), m_rbox.lo(2));
502  amrex::RealVect v3(m_rbox.lo(0), m_rbox.lo(1), m_rbox.hi(2));
503  amrex::RealVect v4(m_rbox.hi(0), m_rbox.lo(1), m_rbox.hi(2));
504  amrex::RealVect v5(m_rbox.hi(0), m_rbox.hi(1), m_rbox.lo(2));
505  amrex::RealVect v6(m_rbox.lo(0), m_rbox.hi(1), m_rbox.hi(2));
506  amrex::RealVect v7(m_rbox.hi(0), m_rbox.hi(1), m_rbox.hi(2));
507 
508 // #ifndef AMREX_USE_GPU
509 
510  bool print_initial = ( Math::abs(m_eb_point[0]-Real(1.666667e-01))<Real(1.e-4) &&
511  Math::abs(m_eb_point[1]+Real(4.194018e-01))<Real(1.e-4) &&
512  Math::abs(m_eb_point[2]+Real(1.666667e-01))<Real(1.e-4) );
513  const bool print_F1 = print_initial && false;
514  const bool print_F2 = print_initial && false;
515  const bool print_F3 = print_initial && false;
516  const bool print_F4 = print_initial && false;
517  const bool print_F5 = print_initial && false;
518  const bool print_F6 = print_initial && false;
519  const bool print_F7 = print_initial && false;
520 // #endif
521 
522  m_F1.add_vertex(v0); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Initial: add v0 -> F1");
523  m_F4.add_vertex(v0); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Initial: add v0 -> F4");
524  m_F5.add_vertex(v0); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Initial: add v0 -> F5");
525 
526  int add_v7(1);
527 
528  amrex::RealVect vIP;
529  amrex::Real distIP;
530 
531  amrex::Array<bool,8> vertex_intersected{}; // true if vertex has been intersected within a path.
532 
533  //------------------------------------------------------------
534  // STEP 1: Predefine edge-plane intersections along 6 paths.
535  // Check how the edges intersect the plane and whether the configuration is valid.
536  // If the configuration is not valid, adjust it.
537  //------------------------------------------------------------
538 
539  amrex::Array<path_data,3> p1, p2, p3;
540  path_data p4, p5, p6;
541 
542  // Path 1: v0->v1->v4->v7
543  p1[0].set(m_eb_point, m_eb_normal, v0, v1);
544  p1[1].set(m_eb_point, m_eb_normal, v1, v4);
545  p1[2].set(m_eb_point, m_eb_normal, v4, v7);
546 
547  // Path 2: v0->v2->v5->v7
548  p2[0].set(m_eb_point, m_eb_normal, v0, v2);
549  p2[1].set(m_eb_point, m_eb_normal, v2, v5);
550  p2[2].set(m_eb_point, m_eb_normal, v5, v7);
551 
552  // Path 3: v0->v3->v6->v7
553  p3[0].set(m_eb_point, m_eb_normal, v0, v3);
554  p3[1].set(m_eb_point, m_eb_normal, v3, v6);
555  p3[2].set(m_eb_point, m_eb_normal, v6, v7);
556 
557  // Path 4: v1->v5
558  p4.set(m_eb_point, m_eb_normal, v1, v5);
559 
560  // Path 5: v2->v6
561  p5.set(m_eb_point, m_eb_normal, v2, v6);
562 
563  // Path 6: v3->v4
564  p6.set(m_eb_point, m_eb_normal, v3, v4);
565 
566  //------------------------------------------------------------
567  // STEP 2: Add vertices to faces.
568  //------------------------------------------------------------
569 
570  // Path 1
571  {
572  int cuts(0);
573  for (int i = 0; i < 8; ++i) vertex_intersected[i] = false;
574 
575  if (p1[0].intersected) {
576  if (p1[0].intersected_start) {
577  m_F1.add_vertex(v0); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add v0 -> F1");
578  m_F4.add_vertex(v0); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add v0 -> F4");
579  m_F5.add_vertex(v0); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add v0 -> F5");
580  m_F7.add_vertex(v0); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add v0 -> F7");
581  if (!vertex_intersected[0]) {
582  vertex_intersected[0] = true;
583  ++cuts;
584  }
585  } else if (p1[0].intersected_end) {
586  m_F1.add_vertex(v1); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add v1 -> F1");
587  m_F2.add_vertex(v1); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add v1 -> F2");
588  m_F5.add_vertex(v1); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add v1 -> F5");
589  m_F7.add_vertex(v1); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add v1 -> F7");
590  if (!vertex_intersected[1]) {
591  vertex_intersected[1] = true;
592  ++cuts;
593  }
594  } else {
595  m_F1.add_vertex(p1[0].vIP); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add vIP -> F1");
596  m_F5.add_vertex(p1[0].vIP); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add vIP -> F5");
597  m_F7.add_vertex(p1[0].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v0--v1: add vIP -> F7");
598  ++cuts;
599  }
600 
601  } // Path 1: v0--v1
602 
603  if (cuts%2 == 0) {
604  m_F1.add_vertex(v1); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v0--v1, cuts-mod-2==0: add v1 -> F1");
605  m_F2.add_vertex(v1); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v0--v1, cuts-mod-2==0: add v1 -> F2");
606  m_F5.add_vertex(v1); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v0--v1, cuts-mod-2==0: add v1 -> F5");
607  }
608 
609  if (p1[1].intersected) {
610  if (p1[1].intersected_start) {
611  m_F1.add_vertex(v1); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add v1 -> F1");
612  m_F2.add_vertex(v1); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add v1 -> F2");
613  m_F5.add_vertex(v1); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add v1 -> F5");
614  m_F7.add_vertex(v1); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add v1 -> F7");
615  if (!vertex_intersected[1]) {
616  vertex_intersected[1] = true;
617  ++cuts;
618  }
619  } else if (p1[1].intersected_end) {
620  m_F2.add_vertex(v4); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add v4 -> F2");
621  m_F3.add_vertex(v4); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add v4 -> F3");
622  m_F5.add_vertex(v4); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add v4 -> F5");
623  m_F7.add_vertex(v4); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add v4 -> F7");
624  if (!vertex_intersected[4]) {
625  vertex_intersected[4] = true;
626  ++cuts;
627  }
628  } else {
629  m_F2.add_vertex(p1[1].vIP); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add vIP -> F2");
630  m_F5.add_vertex(p1[1].vIP); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add vIP -> F5");
631  m_F7.add_vertex(p1[1].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v1--v4: add vIP -> F7");
632  ++cuts;
633  }
634 
635  } // P1: v1--v4
636 
637  if (cuts%2 == 0) {
638  m_F2.add_vertex(v4); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v1--v4, cuts-mod-2==0: add v4 -> F2");
639  m_F3.add_vertex(v4); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v1--v4, cuts-mod-2==0: add v4 -> F3");
640  m_F5.add_vertex(v4); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v1--v4, cuts-mod-2==0: add v4 -> F5");
641  }
642 
643  if (p1[2].intersected) {
644  if (p1[2].intersected_start) {
645  m_F2.add_vertex(v4); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add v4 -> F2");
646  m_F3.add_vertex(v4); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add v4 -> F3");
647  m_F5.add_vertex(v4); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add v4 -> F5");
648  m_F7.add_vertex(v4); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add v4 -> F7");
649  if (!vertex_intersected[4]) {
650  vertex_intersected[4] = true;
651  ++cuts;
652  }
653  } else if (p1[2].intersected_end) {
654  m_F2.add_vertex(v7); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add v7 -> F2");
655  m_F3.add_vertex(v7); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add v7 -> F3");
656  m_F6.add_vertex(v7); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add v7 -> F6");
657  m_F7.add_vertex(v7); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add v7 -> F7");
658  if (!vertex_intersected[7]) {
659  vertex_intersected[7] = true;
660  ++cuts;
661  }
662  } else {
663  m_F2.add_vertex(p1[2].vIP); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add vIP -> F2");
664  m_F3.add_vertex(p1[2].vIP); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add vIP -> F3");
665  m_F7.add_vertex(p1[2].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 1: v4--v7: add vIP -> F7");
666  ++cuts;
667  }
668 
669  } // P1: v4--v7
670 
671  if (cuts == 2 && add_v7) {
672  if (!intersect_plane_edge(m_eb_point, m_eb_normal, v0, v7, vIP, distIP)) {
673  m_F2.add_vertex(v7); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v4--v7, cuts == 2 && add_v7: add v7 -> F2");
674  m_F3.add_vertex(v7); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v4--v7, cuts == 2 && add_v7: add v7 -> F3");
675  m_F6.add_vertex(v7); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 1: after v4--v7, cuts == 2 && add_v7: add v7 -> F6");
676  add_v7 = 0;
677  }
678  }
679  } // end Path 1
680 
681  // Path 4
682  if (p4.intersected) {
683  if (p4.intersected_start) {
684  m_F1.add_vertex(v1); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add v1 -> F1");
685  m_F2.add_vertex(v1); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add v1 -> F2");
686  m_F5.add_vertex(v1); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add v1 -> F5");
687  m_F7.add_vertex(v1); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add v1 -> F7");
688  } else if (p4.intersected_end) {
689  m_F1.add_vertex(v5); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add v5 -> F1");
690  m_F2.add_vertex(v5); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add v5 -> F2");
691  m_F6.add_vertex(v5); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add v5 -> F6");
692  m_F7.add_vertex(v5); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add v5 -> F7");
693  } else {
694  m_F1.add_vertex(p4.vIP); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add vIP -> F1");
695  m_F2.add_vertex(p4.vIP); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add vIP -> F2");
696  m_F7.add_vertex(p4.vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 4: v1--v5: add vIP -> F7");
697  }
698  }
699 
700  // Path 2
701  { int cuts(0);
702  for (int i = 0; i < 8; ++i) vertex_intersected[i] = false;
703 
704  if (p2[0].intersected) {
705  if (p2[0].intersected_start) {
706  m_F1.add_vertex(v0); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add v0 -> F1");
707  m_F4.add_vertex(v0); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add v0 -> F4");
708  m_F5.add_vertex(v0); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add v0 -> F5");
709  m_F7.add_vertex(v0); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add v0 -> F7");
710  if (!vertex_intersected[0]) {
711  vertex_intersected[0] = true;
712  ++cuts;
713  }
714  } else if (p2[0].intersected_end) {
715  m_F1.add_vertex(v2); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add v2 -> F1");
716  m_F4.add_vertex(v2); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add v2 -> F4");
717  m_F6.add_vertex(v2); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add v2 -> F6");
718  m_F7.add_vertex(v2); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add v2 -> F7");
719  if (!vertex_intersected[2]) {
720  vertex_intersected[2] = true;
721  ++cuts;
722  }
723  } else {
724  m_F1.add_vertex(p2[0].vIP); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add vIP -> F1");
725  m_F4.add_vertex(p2[0].vIP); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add vIP -> F4");
726  m_F7.add_vertex(p2[0].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v0--v2: add vIP -> F7");
727  ++cuts;
728  }
729 
730  } // P2: v0--v2
731 
732  if (cuts%2 == 0) {
733  m_F1.add_vertex(v2); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v0--v2, cuts-mod-2==0: add v2 -> F1");
734  m_F4.add_vertex(v2); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v0--v2, cuts-mod-2==0: add v2 -> F4");
735  m_F6.add_vertex(v2); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v0--v2, cuts-mod-2==0: add v2 -> F6");
736  }
737 
738  if (p2[1].intersected) {
739  if (p2[1].intersected_start) {
740  m_F1.add_vertex(v2); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add v2 -> F1");
741  m_F4.add_vertex(v2); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add v2 -> F4");
742  m_F6.add_vertex(v2); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add v2 -> F6");
743  m_F7.add_vertex(v2); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add v2 -> F7");
744  if (!vertex_intersected[2]) {
745  vertex_intersected[2] = true;
746  ++cuts;
747  }
748  } else if (p2[1].intersected_end) {
749  m_F1.add_vertex(v5); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add v5 -> F1");
750  m_F2.add_vertex(v5); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add v5 -> F2");
751  m_F6.add_vertex(v5); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add v5 -> F6");
752  m_F7.add_vertex(v5); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add v5 -> F7");
753  if (!vertex_intersected[5]) {
754  vertex_intersected[5] = true;
755  ++cuts;
756  }
757  } else {
758  m_F1.add_vertex(p2[1].vIP); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add vIP -> F1");
759  m_F6.add_vertex(p2[1].vIP); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add vIP -> F6");
760  m_F7.add_vertex(p2[1].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v2--v5: add vIP -> F7");
761  ++cuts;
762  }
763  }
764 
765  if (cuts%2 == 0) {
766  m_F1.add_vertex(v5); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v2--v5, cuts-mod-2==0: add v5 -> F1");
767  m_F2.add_vertex(v5); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v2--v5, cuts-mod-2==0: add v5 -> F2");
768  m_F6.add_vertex(v5); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v2--v5, cuts-mod-2==0: add v5 -> F6");
769  }
770 
771  if (p2[2].intersected) {
772  if (p2[2].intersected_start) {
773  m_F1.add_vertex(v5); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add v5 -> F1");
774  m_F2.add_vertex(v5); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add v5 -> F2");
775  m_F6.add_vertex(v5); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add v5 -> F6");
776  m_F7.add_vertex(v5); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add v5 -> F7");
777  if (!vertex_intersected[5]) {
778  vertex_intersected[5] = true;
779  ++cuts;
780  }
781  } else if (p2[2].intersected_end) {
782  m_F2.add_vertex(v7); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add v7 -> F2");
783  m_F3.add_vertex(v7); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add v7 -> F3");
784  m_F6.add_vertex(v7); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add v7 -> F6");
785  m_F7.add_vertex(v7); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add v7 -> F7");
786  if (!vertex_intersected[7]) {
787  vertex_intersected[7] = true;
788  ++cuts;
789  }
790  } else {
791  m_F2.add_vertex(p2[2].vIP); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add vIP -> F2");
792  m_F6.add_vertex(p2[2].vIP); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add vIP -> F6");
793  m_F7.add_vertex(p2[2].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 2: v5--v7: add vIP -> F7");
794  ++cuts;
795  }
796  } // Path 2: v5--v7
797 
798  if (cuts == 2 && add_v7) {
799  if (!intersect_plane_edge(m_eb_point, m_eb_normal, v0, v7, vIP, distIP)) {
800  m_F2.add_vertex(v7); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v5--v7, cuts == 2 && add_v7: add v7 -> F2");
801  m_F3.add_vertex(v7); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v5--v7, cuts == 2 && add_v7: add v7 -> F3");
802  m_F6.add_vertex(v7); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 2: after v5--v7, cuts == 2 && add_v7: add v7 -> F6");
803  add_v7 = 0;
804  }
805  }
806 
807  } // end Path 2
808 
809  // Path 5
810  if (p5.intersected) {
811  if (p5.intersected_start) {
812  m_F1.add_vertex(v2); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add v2 -> F1");
813  m_F4.add_vertex(v2); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add v2 -> F4");
814  m_F6.add_vertex(v2); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add v2 -> F6");
815  m_F7.add_vertex(v2); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add v2 -> F7");
816  } else if (p5.intersected_end) {
817  m_F3.add_vertex(v6); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add v6 -> F3");
818  m_F4.add_vertex(v6); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add v6 -> F4");
819  m_F6.add_vertex(v6); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add v6 -> F6");
820  m_F7.add_vertex(v6); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add v6 -> F7");
821  } else {
822  m_F4.add_vertex(p5.vIP); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add vIP -> F4");
823  m_F6.add_vertex(p5.vIP); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add vIP -> F6");
824  m_F7.add_vertex(p5.vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 5: v2--v6: add vIP -> F7");
825  }
826  } // end Path 5
827 
828 
829  // Path 3
830  { int cuts(0);
831  for (int i = 0; i < 8; ++i) vertex_intersected[i] = false;
832 
833  if (p3[0].intersected) {
834  if (p3[0].intersected_start) {
835  m_F1.add_vertex(v0); if(print_F1) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add v0 -> F1");
836  m_F4.add_vertex(v0); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add v0 -> F4");
837  m_F5.add_vertex(v0); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add v0 -> F5");
838  m_F7.add_vertex(v0); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add v0 -> F7");
839  if (!vertex_intersected[0]) {
840  vertex_intersected[0] = true;
841  ++cuts;
842  }
843  } else if (p3[0].intersected_end) {
844  m_F3.add_vertex(v3); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add v3 -> F3");
845  m_F4.add_vertex(v3); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add v3 -> F4");
846  m_F5.add_vertex(v3); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add v3 -> F5");
847  m_F7.add_vertex(v3); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add v3 -> F7");
848  if (!vertex_intersected[3]) {
849  vertex_intersected[3] = true;
850  ++cuts;
851  }
852  } else {
853  m_F4.add_vertex(p3[0].vIP); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add vIP -> F4");
854  m_F5.add_vertex(p3[0].vIP); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add vIP -> F5");
855  m_F7.add_vertex(p3[0].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v0--v3: add vIP -> F7");
856  ++cuts;
857  }
858 
859  } // P3: v0--v3
860 
861  if (cuts%2 == 0) {
862  m_F3.add_vertex(v3); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v0--v3, cuts-mod-2 == 0: add v3 -> F3");
863  m_F4.add_vertex(v3); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v0--v3, cuts-mod-2 == 0: add v3 -> F4");
864  m_F5.add_vertex(v3); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v0--v3, cuts-mod-2 == 0: add v3 -> F5");
865  }
866 
867  if (p3[1].intersected) {
868  if (p3[1].intersected_start) {
869  m_F3.add_vertex(v3); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add v3 -> F3");
870  m_F4.add_vertex(v3); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add v3 -> F4");
871  m_F5.add_vertex(v3); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add v3 -> F5");
872  m_F7.add_vertex(v3); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add v3 -> F7");
873  if (!vertex_intersected[3]) {
874  vertex_intersected[3] = true;
875  ++cuts;
876  }
877  } else if (p3[1].intersected_end) {
878  m_F3.add_vertex(v6); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add v6 -> F3");
879  m_F4.add_vertex(v6); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add v6 -> F4");
880  m_F6.add_vertex(v6); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add v6 -> F6");
881  m_F7.add_vertex(v6); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add v6 -> F7");
882  if (!vertex_intersected[6]) {
883  vertex_intersected[6] = true;
884  ++cuts;
885  }
886  } else {
887  m_F3.add_vertex(p3[1].vIP); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add vIP -> F3");
888  m_F4.add_vertex(p3[1].vIP); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add vIP -> F4");
889  m_F7.add_vertex(p3[1].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v3--v6: add vIP -> F7");
890  ++cuts;
891  }
892 
893  } // P3: v3--v6
894 
895  if (cuts%2 == 0) {
896  m_F3.add_vertex(v6); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v3--v6, cuts-mod-2 == 0: add v6 -> F3");
897  m_F4.add_vertex(v6); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v3--v6, cuts-mod-2 == 0: add v6 -> F4");
898  m_F6.add_vertex(v6); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v3--v6, cuts-mod-2 == 0: add v6 -> F6");
899  }
900 
901  if (p3[2].intersected) {
902  if (p3[2].intersected_start) {
903  m_F3.add_vertex(v6); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add v6 -> F3");
904  m_F4.add_vertex(v6); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add v6 -> F4");
905  m_F6.add_vertex(v6); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add v6 -> F6");
906  m_F7.add_vertex(v6); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add v6 -> F7");
907  if (!vertex_intersected[6]) {
908  vertex_intersected[6] = true;
909  ++cuts;
910  }
911  } else if (p3[2].intersected_end) {
912  m_F2.add_vertex(v7); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add v7 -> F2");
913  m_F3.add_vertex(v7); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add v7 -> F3");
914  m_F6.add_vertex(v7); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add v7 -> F6");
915  m_F7.add_vertex(v7); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add v7 -> F7");
916  if (!vertex_intersected[7]) {
917  vertex_intersected[7] = true;
918  ++cuts;
919  }
920  } else {
921  m_F3.add_vertex(p3[2].vIP); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add vIP -> F3");
922  m_F6.add_vertex(p3[2].vIP); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add vIP -> F6");
923  m_F7.add_vertex(p3[2].vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 3: v6--v7: add vIP -> F7");
924  ++cuts;
925  }
926  } // P3: v6--v7
927 
928  if (cuts == 2 && add_v7) {
929  if (!intersect_plane_edge(m_eb_point, m_eb_normal, v0, v7, vIP, distIP)) {
930  m_F2.add_vertex(v7); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v6--v7, cuts == 2 && add_v7: add v7 -> F2");
931  m_F3.add_vertex(v7); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v6--v7, cuts == 2 && add_v7: add v7 -> F3");
932  m_F6.add_vertex(v7); if(print_F6) AMREX_DEVICE_PRINTF("%s \n","Path 3: after v6--v7, cuts == 2 && add_v7: add v7 -> F6");
933  add_v7 = 0;
934  }
935  }
936 
937  } // end Path 3
938 
939  // Path 6
940  if (p6.intersected) {
941  if (p6.intersected_start) {
942  m_F3.add_vertex(v3); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add v3 -> F3");
943  m_F4.add_vertex(v3); if(print_F4) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add v3 -> F4");
944  m_F5.add_vertex(v3); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add v3 -> F5");
945  m_F7.add_vertex(v3); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add v3 -> F7");
946  } else if (p6.intersected_end) {
947  m_F2.add_vertex(v4); if(print_F2) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add v4 -> F2");
948  m_F3.add_vertex(v4); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add v4 -> F3\n");
949  m_F5.add_vertex(v4); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add v4 -> F5");
950  m_F7.add_vertex(v4); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add v4 -> F7");
951  } else {
952  m_F3.add_vertex(p6.vIP); if(print_F3) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add vIP -> F3");
953  m_F5.add_vertex(p6.vIP); if(print_F5) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add vIP -> F5");
954  m_F7.add_vertex(p6.vIP); if(print_F7) AMREX_DEVICE_PRINTF("%s \n","Path 6: v3--v4: add vIP -> F7");
955  }
956  } // end Path 6
957 
958  if (print_F1 || print_F2 || print_F3 || print_F4 || print_F5 || print_F6 || print_F7) {
959  AMREX_DEVICE_PRINTF("%s \n"," ");
960  }
961 
962 }
963 
964 AMREX_GPU_HOST_DEVICE
965 AMREX_FORCE_INLINE
966 void
969 {
970  using namespace amrex;
971 
972  RealVect v0(m_rbox.lo(0), m_rbox.lo(1), m_rbox.lo(2));
973  RealVect v1(m_rbox.hi(0), m_rbox.lo(1), m_rbox.lo(2));
974  RealVect v2(m_rbox.lo(0), m_rbox.hi(1), m_rbox.lo(2));
975  RealVect v3(m_rbox.lo(0), m_rbox.lo(1), m_rbox.hi(2));
976  RealVect v4(m_rbox.hi(0), m_rbox.lo(1), m_rbox.hi(2));
977  RealVect v5(m_rbox.hi(0), m_rbox.hi(1), m_rbox.lo(2));
978  RealVect v6(m_rbox.lo(0), m_rbox.hi(1), m_rbox.hi(2));
979  RealVect v7(m_rbox.hi(0), m_rbox.hi(1), m_rbox.hi(2));
980 
981  // Add vertices in the order of outward normal vector
982 
983  m_F1.add_vertex(v0);
984  m_F1.add_vertex(v2);
985  m_F1.add_vertex(v5);
986  m_F1.add_vertex(v1);
987 
988  m_F2.add_vertex(v1);
989  m_F2.add_vertex(v5);
990  m_F2.add_vertex(v7);
991  m_F2.add_vertex(v4);
992 
993  m_F3.add_vertex(v3);
994  m_F3.add_vertex(v4);
995  m_F3.add_vertex(v7);
996  m_F3.add_vertex(v6);
997 
998  m_F4.add_vertex(v0);
999  m_F4.add_vertex(v3);
1000  m_F4.add_vertex(v6);
1001  m_F4.add_vertex(v2);
1002 
1003  m_F5.add_vertex(v0);
1004  m_F5.add_vertex(v1);
1005  m_F5.add_vertex(v4);
1006  m_F5.add_vertex(v3);
1007 
1008  m_F6.add_vertex(v2);
1009  m_F6.add_vertex(v5);
1010  m_F6.add_vertex(v7);
1011  m_F6.add_vertex(v6);
1012 
1013 }
1014 
1015 #endif
constexpr amrex::Real three
Definition: ERF_Constants.H:11
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real fourth
Definition: ERF_Constants.H:14
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int intersect_plane_edge(amrex::RealVect const &a_plane_point, amrex::RealVect const &a_plane_normal, amrex::RealVect const &a_edge_point0, amrex::RealVect const &a_edge_point1, amrex::RealVect &a_intersection_point, amrex::Real &a_intersection_dist)
Intersect a plane with a line segment.
Definition: ERF_EBCutCell.H:30
Defines polygon geometry utilities for EB cut-cell reconstruction.
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Reconstructs geometric moments for one EB cut cell.
Definition: ERF_EBCutCell.H:68
AMREX_GPU_HOST_DEVICE void calc_edge_intersections()
Compute all edge-plane intersections and populate polygon vertices.
Definition: ERF_EBCutCell.H:495
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real volume() const
Return the physical volume of the reconstructed cell.
Definition: ERF_EBCutCell.H:124
polygon_ m_F6
Definition: ERF_EBCutCell.H:300
amrex::Array< polygon_ const *const, 3 > m_lo_faces
Definition: ERF_EBCutCell.H:310
amrex::RealVect m_rbox_area
Definition: ERF_EBCutCell.H:289
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool isRegular() const noexcept
Return true if the reconstructed cell is regular.
Definition: ERF_EBCutCell.H:91
amrex::RealVect m_cell_cent
Definition: ERF_EBCutCell.H:304
amrex::RealVect m_dx
Definition: ERF_EBCutCell.H:305
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real areaLo(int const idir) const noexcept
Return the low-side face area in one coordinate direction.
Definition: ERF_EBCutCell.H:149
amrex::RealVect const m_eb_point
Definition: ERF_EBCutCell.H:284
amrex::Real m_invert
Definition: ERF_EBCutCell.H:287
amrex::RealBox const m_rbox
Definition: ERF_EBCutCell.H:283
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real areaHi(int const idir) const noexcept
Return the high-side face area in one coordinate direction.
Definition: ERF_EBCutCell.H:162
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect centBoun() const noexcept
Return the EB boundary centroid.
Definition: ERF_EBCutCell.H:226
AMREX_GPU_HOST_DEVICE void set_covered_regular_cell_vertices()
Populate polygon vertices for cells that are fully covered or regular.
Definition: ERF_EBCutCell.H:968
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void set_regular()
Mark the reconstructed cell as regular and fill regular face areas.
Definition: ERF_EBCutCell.H:105
polygon_ m_F1
Definition: ERF_EBCutCell.H:295
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real areaBoun() const noexcept
Return the EB boundary area inside the cell.
Definition: ERF_EBCutCell.H:172
polygon_ m_F3
Definition: ERF_EBCutCell.H:297
amrex::EBCellFlag m_flag
Definition: ERF_EBCutCell.H:291
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect centHi(int const idir) const noexcept
Return the high-side face centroid in one coordinate direction.
Definition: ERF_EBCutCell.H:205
polygon_ m_F5
Definition: ERF_EBCutCell.H:299
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect centVol() const noexcept
Return the volume centroid of the reconstructed cell.
Definition: ERF_EBCutCell.H:246
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void set_covered()
Mark the reconstructed cell as covered.
Definition: ERF_EBCutCell.H:99
polygon_ m_F7
Definition: ERF_EBCutCell.H:308
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect normBoun() const noexcept
Return the EB boundary normal.
Definition: ERF_EBCutCell.H:236
amrex::Array< int const, 3 > m_hi_faces_id
Definition: ERF_EBCutCell.H:314
AMREX_GPU_HOST_DEVICE eb_cut_cell_(amrex::EBCellFlag const &a_flag, amrex::RealBox const &a_rbox, amrex::RealVect const &a_point, amrex::RealVect const &a_normal)
Construct cut-cell geometry from a cell flag, box, EB point, and EB normal.
Definition: ERF_EBCutCell.H:331
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool isSingleValued() const noexcept
Return true if the reconstructed cell is single-valued.
Definition: ERF_EBCutCell.H:95
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool isCovered() const noexcept
Return true if the reconstructed cell is covered.
Definition: ERF_EBCutCell.H:87
void debug(int const a_face=-1)
Print cut-cell diagnostics on CPU builds.
Definition: ERF_EBCutCell.cpp:13
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect centLo(int const idir) const noexcept
Return the low-side face centroid in one coordinate direction.
Definition: ERF_EBCutCell.H:181
static constexpr int m_max_faces
Definition: ERF_EBCutCell.H:302
amrex::RealVect const m_eb_normal
Definition: ERF_EBCutCell.H:285
amrex::Array< int const, 3 > m_lo_faces_id
Definition: ERF_EBCutCell.H:313
polygon_ m_F2
Definition: ERF_EBCutCell.H:296
amrex::Array< polygon_ const *const, 3 > m_hi_faces
Definition: ERF_EBCutCell.H:311
polygon_ m_F4
Definition: ERF_EBCutCell.H:298
amrex::Array< amrex::RealVect, m_max_faces > m_cellface_cent
Definition: ERF_EBCutCell.H:303
Polygon helper used to accumulate cut-cell face geometry.
Definition: ERF_EBPolygon.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect get_centroid() const noexcept
Return the polygon centroid from its sub-triangulation.
Definition: ERF_EBPolygon.H:205
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int ok() const noexcept
Return whether the polygon has been defined with a valid area state.
Definition: ERF_EBPolygon.H:182
AMREX_GPU_HOST_DEVICE void add_vertex(amrex::RealVect const &a_v)
Add a unique vertex to the polygon.
Definition: ERF_EBPolygon.H:63
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real distance(amrex::RealVect const &a_point) const noexcept
Return the perpendicular distance from this polygon to a point.
Definition: ERF_EBPolygon.H:197
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real area() const noexcept
Return the polygon area.
Definition: ERF_EBPolygon.H:187
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void set_area(amrex::Real const &a_area)
Set the polygon area directly.
Definition: ERF_EBPolygon.H:87
Definition: ERF_ConsoleIO.cpp:15
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
Intersection metadata for one ordered edge path in the cut-cell box.
Definition: ERF_EBCutCell.H:437
amrex::RealVect vIP
Coordinates of the intersection point.
Definition: ERF_EBCutCell.H:450
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE path_data()=default
Construct empty path data.
amrex::Real distIP
Distance from the start vertex to the intersection point.
Definition: ERF_EBCutCell.H:452
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void set(const amrex::RealVect &eb_point, const amrex::RealVect &eb_normal, const amrex::RealVect &v_start, const amrex::RealVect &v_end)
Compute and store the intersection data for one edge.
Definition: ERF_EBCutCell.H:465
amrex::Real edge_length
Physical length of the edge.
Definition: ERF_EBCutCell.H:454
bool intersected_end
Whether the intersection lies on the end vertex.
Definition: ERF_EBCutCell.H:448
bool intersected
Whether the edge intersects the EB plane.
Definition: ERF_EBCutCell.H:444
bool intersected_start
Whether the intersection lies on the start vertex.
Definition: ERF_EBCutCell.H:446