ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ERF_EBPolygon.H
Go to the documentation of this file.
1 #ifndef ERF_EB_POLYGON_H_
2 #define ERF_EB_POLYGON_H_
3 
4 #include <AMReX_REAL.H>
5 #include <AMReX_RealVect.H>
6 
7 #include "ERF_Constants.H"
8 
9 class polygon_ {
10 
11  public:
12 
13  AMREX_GPU_HOST_DEVICE
14  polygon_ ( amrex::RealVect a_point,
15  amrex::RealVect a_normal )
16  : m_cell_face(1)
17  , m_eb_point(a_point)
18  , m_eb_normal(a_normal)
19  , m_defined(0)
20  , m_vertices(0)
21  , m_area(0.)
22  , m_sorted(0)
23  , m_vertex({amrex::RealVect(0.), amrex::RealVect(0.), amrex::RealVect(0.),
24  amrex::RealVect(0.), amrex::RealVect(0.), amrex::RealVect(0.)})
25  , m_zdir(0.)
26  {}
27 
28  AMREX_GPU_HOST_DEVICE
30  : m_cell_face(0)
31  , m_eb_point(0.)
32  , m_eb_normal(0.)
33  , m_defined(0)
34  , m_vertices(0)
35  , m_area(0.)
36  , m_sorted(0)
37  , m_vertex({amrex::RealVect(0.), amrex::RealVect(0.), amrex::RealVect(0.),
38  amrex::RealVect(0.), amrex::RealVect(0.), amrex::RealVect(0.)})
39  , m_zdir(0.)
40  {}
41 
42  AMREX_GPU_HOST_DEVICE
43  void add_vertex ( amrex::RealVect const& a_v ) {
44  for ( int i(0); i<m_vertices; ++i) {
45  if (m_vertex[i] == a_v) {
46  return;
47  }
48  }
49  AMREX_ASSERT( m_vertices < m_max_vertices );
50  m_vertex[m_vertices] = a_v;
51  m_vertices++;
52  }
53 
54  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
55  void set_area ( amrex::Real const& a_area ) { m_area = a_area; }
56 
57  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
58  void define () {
59 
60  AMREX_ALWAYS_ASSERT( m_defined == 0 ); // TODO ---------------------------- remove ALWAYS
61 
62  m_defined = 1;
63 
64  // We need at least 3 faces.
65  if (m_vertices < 3) { return; }
66 
67  // Check to see if the vertices of the face are inside or outside of the plane.
68  // If they are outside, this face doesn't belong to the volume.
69  if ( m_cell_face ) {
70  for ( int i(0); i<m_vertices; ++i) {
71  if ((m_eb_normal.dotProduct(m_vertex[i] - m_eb_point)) >= 0.) {
72  } else {
73  }
74  }
75  }
76 
77  // Calculate the centroid of the polygon.
78  amrex::RealVect centroid = get_centroid();
79 
80  // Shift the vertices relative to the centroid
81  amrex::Array<amrex::RealVect,m_max_vertices> vertex_cent;
82  for ( int i(0); i<m_vertices; ++i) { vertex_cent[i] = m_vertex[i] - centroid; }
83 
84  // Find a vertex that isn't inline with v[0] and the centroid so we can
85  // compute a vector normal to the face.
86  for ( int i(1); i<m_vertices; ++i ) {
87  m_zdir = vertex_cent[0].crossProduct(vertex_cent[i]);
88  if ( !amrex::almostEqual(m_zdir.vectorLength(),0.) ) { break; }
89  }
90  AMREX_ALWAYS_ASSERT(!amrex::almostEqual(m_zdir.vectorLength(), 0.));
91  m_zdir /= m_zdir.vectorLength();
92 
93  m_theta[0] = 0.0;
94  for ( int i(1); i<m_vertices; ++i) {
95 
96  m_theta[i] = std::atan2(m_zdir.dotProduct( vertex_cent[0].crossProduct(vertex_cent[i]) ),
97  vertex_cent[0].dotProduct(vertex_cent[i]));
98 
99  m_theta[i] += ((m_theta[i] >= 0.) ? 0.0 : 2.0*PI);
100  }
101 
102  // Sort counter clockwise based on theta.
103  for (int i(0); i<m_vertices; ++i) {
104  for (int j(0); j < m_vertices-i-1; ++j) {
105  if ( m_theta[j] > m_theta[j+1] ) {
106  amrex::Swap(m_theta[j], m_theta[j+1]);
107  amrex::Swap(m_vertex[j], m_vertex[j+1]);
108  amrex::Swap(vertex_cent[j], vertex_cent[j+1]);
109  }
110  } // j-loop
111  } // i-loop
112  m_sorted = 1;
113 
114  // Compute areas of triangles
115  for (int i(0); i<m_vertices; ++i) {
116  int const j( (i+1 == m_vertices) ? 0 : i+1 );
117  amrex::RealVect vi_cross_vj = vertex_cent[i].crossProduct(vertex_cent[j]);
118  m_area += 0.5*vi_cross_vj.vectorLength();
119  }
120  AMREX_ALWAYS_ASSERT( m_area > 0. ); // <------------------------------- TODO remove ALWAYS
121  }
122 
123  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
124  int ok ( ) const noexcept
125  { return ((m_area > 0. || (m_area == 0. && m_defined == 1)) ? 1 : 0); }
126 
127  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
128  amrex::Real area ( ) const noexcept {
129  AMREX_ALWAYS_ASSERT( ok() ); // <-------------------------------------- TODO remove ALWAYS
130  return m_area;
131  }
132 
133  // Distance from polygon to a_point
134  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
135  amrex::Real distance ( amrex::RealVect const& a_point ) const noexcept {
136  AMREX_ALWAYS_ASSERT( m_defined == 1 ); // <--------------------------- TODO remove ALWAYS
137  amrex::RealVect x0 = a_point - m_vertex[0];
138  return amrex::Math::abs(x0.dotProduct(m_zdir));
139  }
140 
141  // Centroid of the polygon based on the sub-triangulation
142  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
143  amrex::RealVect get_centroid ( ) const noexcept {
144  amrex::RealVect cent(0.);
145  if (m_vertices==3) {
146  cent = (m_vertex[0] + m_vertex[1] + m_vertex[2]) / 3.0;
147  } else {
148  // Loop over sub-triangles
149  amrex::Real area(0.);
150  for ( int i(0); i<m_vertices-2; ++i) {
151  amrex::RealVect const v0 (m_vertex[i+1] - m_vertex[0]);
152  amrex::RealVect const v1 (m_vertex[i+2] - m_vertex[0]);
153  amrex::RealVect v0_cross_v1 = v0.crossProduct(v1);
154  amrex::Real area_tri = 0.5 * v0_cross_v1.vectorLength();
155  amrex::RealVect cent_tri = (m_vertex[0] + m_vertex[i+1] + m_vertex[i+2]) / 3.0;
156  area += area_tri;
157  cent += area_tri * cent_tri;
158  }
159  cent = cent / area;
160  }
161  return cent;
162  }
163 
164  // Unit normal vector
165  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
166  amrex::RealVect normal () const noexcept {
167  return m_zdir;
168  }
169 
170 #ifndef AMREX_USE_GPU
171  void report ( int const a_id, amrex::RealVect a_v0 )
172 #else
173  void report ( int const /*a_id*/, amrex::RealVect /*a_v0*/ )
174 #endif
175  {
176 
177 #ifndef AMREX_USE_GPU
178  amrex::RealVect centroid = get_centroid();
179  amrex::Print() << "Face " << a_id
180  << " -------------------------------------------\n"
181  << "\nok? " << (ok() ? "yes" : "no") << "\n\n";
182  for (int i(0); i<m_vertices; ++i) {
183  amrex::Print() << "v" << i << ": " << m_vertex[i] << '\n';
184  }
185  amrex::Print() << "\nvc: " << " " << centroid << "\n";
186 
187  amrex::Real const dist = distance( a_v0 );
188  // amrex::Real const vol = ok() ? m_area * dist : 0.;
189 
190  amrex::Print() << "\narea: " << m_area
191  << "\ndistance: " << dist
192  << "\nvolume: " << dist*m_area
193  << "\n==================================================\n\n";
194 #endif
195  }
196 
197  private:
198 
199  static int constexpr m_max_vertices = 6;
200 
201  int const m_cell_face;
202 
203  amrex::RealVect const m_eb_point;
204  amrex::RealVect const m_eb_normal;
205 
207 
209 
210  amrex::Real m_area;
211 
212  int m_sorted;
213 
214  amrex::Array<amrex::RealVect,m_max_vertices> m_vertex;
215 
216  amrex::GpuArray<amrex::Real,m_max_vertices> m_theta;
217 
218  amrex::RealVect m_zdir; // normal to polygon
219 };
220 
221 
222 #endif
constexpr amrex::Real PI
Definition: ERF_Constants.H:6
Definition: ERF_EBPolygon.H:9
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect get_centroid() const noexcept
Definition: ERF_EBPolygon.H:143
int m_defined
Definition: ERF_EBPolygon.H:206
amrex::Real m_area
Definition: ERF_EBPolygon.H:210
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int ok() const noexcept
Definition: ERF_EBPolygon.H:124
amrex::GpuArray< amrex::Real, m_max_vertices > m_theta
Definition: ERF_EBPolygon.H:216
AMREX_GPU_HOST_DEVICE void add_vertex(amrex::RealVect const &a_v)
Definition: ERF_EBPolygon.H:43
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real distance(amrex::RealVect const &a_point) const noexcept
Definition: ERF_EBPolygon.H:135
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real area() const noexcept
Definition: ERF_EBPolygon.H:128
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void set_area(amrex::Real const &a_area)
Definition: ERF_EBPolygon.H:55
int const m_cell_face
Definition: ERF_EBPolygon.H:201
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect normal() const noexcept
Definition: ERF_EBPolygon.H:166
int m_sorted
Definition: ERF_EBPolygon.H:212
int m_vertices
Definition: ERF_EBPolygon.H:208
amrex::Array< amrex::RealVect, m_max_vertices > m_vertex
Definition: ERF_EBPolygon.H:214
amrex::RealVect const m_eb_normal
Definition: ERF_EBPolygon.H:204
static constexpr int m_max_vertices
Definition: ERF_EBPolygon.H:199
void report(int const a_id, amrex::RealVect a_v0)
Definition: ERF_EBPolygon.H:171
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void define()
Definition: ERF_EBPolygon.H:58
AMREX_GPU_HOST_DEVICE polygon_()
Definition: ERF_EBPolygon.H:29
AMREX_GPU_HOST_DEVICE polygon_(amrex::RealVect a_point, amrex::RealVect a_normal)
Definition: ERF_EBPolygon.H:14
amrex::RealVect const m_eb_point
Definition: ERF_EBPolygon.H:203
amrex::RealVect m_zdir
Definition: ERF_EBPolygon.H:218