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