ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
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_num_vertices(0)
21  , m_area(0.)
22  , m_sorted(0)
23  , m_vertices({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_num_vertices(0)
35  , m_area(0.)
36  , m_sorted(0)
37  , m_vertices({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
43  void add_vertex (amrex::RealVect const& a_v,
44  const std::string& msg, bool print_msg = false)
45  {
46  if (print_msg) {
47  amrex::Print() << msg << "\n";
48  }
49  add_vertex(a_v);
50  }
51 
52  AMREX_GPU_HOST_DEVICE
53  void add_vertex ( amrex::RealVect const& a_v ) {
54  for ( int i(0); i<m_num_vertices; ++i) {
55  if ( amrex::almostEqual(m_vertices[i][0],a_v[0]) &&
56  amrex::almostEqual(m_vertices[i][1],a_v[1]) &&
57  amrex::almostEqual(m_vertices[i][2],a_v[2]) ) {
58  return;
59  }
60  }
61  AMREX_ASSERT( m_num_vertices < m_max_vertices );
64  }
65 
66  AMREX_GPU_HOST_DEVICE
67  int get_num_vertices ( ) {
68  return m_num_vertices;
69  }
70 
71  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
72  void set_area ( amrex::Real const& a_area ) { m_area = a_area; }
73 
74  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
75  void define () {
76 
77  AMREX_ALWAYS_ASSERT( m_defined == 0 ); // TODO ---------------------------- remove ALWAYS
78 
79  m_defined = 1;
80 
81  // We need at least 3 faces.
82  if (m_num_vertices < 3) { return; }
83 
84  // Check to see if the vertices of the face are inside or outside of the plane.
85  // If they are outside, this face doesn't belong to the volume.
86  if ( m_cell_face ) {
87  for ( int i(0); i<m_num_vertices; ++i) {
88  if ((m_eb_normal.dotProduct(m_vertices[i] - m_eb_point)) >= 0.) {
89  } else {
90  }
91  }
92  }
93 
94  // Calculate the centroid of the polygon.
95  amrex::RealVect centroid = get_centroid();
96 
97  // Shift the vertices relative to the centroid
98  amrex::Array<amrex::RealVect,m_max_vertices> vertex_cent;
99  for ( int i(0); i<m_num_vertices; ++i) {
100  vertex_cent[i] = m_vertices[i] - centroid;
101  }
102 
103  // Compute the normal vector m_zdir by cross product of two vectors in vertex_cent.
104  // Choose the vectors with the largest cross-product magnitude.
105  amrex::RealVect v_normal;
106  amrex::Real max_norm2 = -1.0;
107  const amrex::RealVect& vertex_cent_0 = vertex_cent[0];
108 
109  for (int i = 1; i < m_num_vertices; ++i)
110  {
111  amrex::RealVect vi = vertex_cent[i];
112  amrex::RealVect v_cross = vertex_cent_0.crossProduct(vi);
113  amrex::Real n2 = v_cross.radSquared();
114  if (n2 > max_norm2)
115  {
116  max_norm2 = n2;
117  v_normal = v_cross;
118  }
119  }
120  if (!amrex::almostEqual(max_norm2, 0.0))
121  {
122  v_normal /= std::sqrt(max_norm2);
123  }
124  m_zdir = v_normal;
125 
126  //
127 
128  m_theta[0] = 0.0;
129  for ( int i(1); i<m_num_vertices; ++i) {
130 
131  m_theta[i] = std::atan2(m_zdir.dotProduct( vertex_cent[0].crossProduct(vertex_cent[i]) ),
132  vertex_cent[0].dotProduct(vertex_cent[i]));
133 
134  m_theta[i] += ((m_theta[i] >= 0.) ? 0.0 : 2.0*PI);
135  }
136 
137  // Sort counter clockwise based on theta.
138  for (int i(0); i<m_num_vertices; ++i) {
139  for (int j(0); j < m_num_vertices-i-1; ++j) {
140  if ( m_theta[j] > m_theta[j+1] ) {
141  amrex::Swap(m_theta[j], m_theta[j+1]);
142  amrex::Swap(m_vertices[j], m_vertices[j+1]);
143  amrex::Swap(vertex_cent[j], vertex_cent[j+1]);
144  }
145  } // j-loop
146  } // i-loop
147  m_sorted = 1;
148 
149  // Compute areas of triangles
150 
151  for (int i(0); i<m_num_vertices; ++i) {
152  int const j( (i+1 == m_num_vertices) ? 0 : i+1 );
153  amrex::RealVect vi_cross_vj = vertex_cent[i].crossProduct(vertex_cent[j]);
154  m_area += 0.5*vi_cross_vj.vectorLength();
155  }
156  AMREX_ALWAYS_ASSERT( m_area > 0. ); // <------------------------------- TODO remove ALWAYS
157  } // void define
158 
159  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
160  int ok ( ) const noexcept
161  { return ((m_area > 0. || (m_area == 0. && m_defined == 1)) ? 1 : 0); }
162 
163  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
164  amrex::Real area ( ) const noexcept {
165  AMREX_ALWAYS_ASSERT( ok() ); // <-------------------------------------- TODO remove ALWAYS
166  return m_area;
167  }
168 
169  // Distance from polygon to a_point
170  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
171  amrex::Real distance ( amrex::RealVect const& a_point ) const noexcept {
172  AMREX_ALWAYS_ASSERT( m_defined == 1 ); // <--------------------------- TODO remove ALWAYS
173  amrex::RealVect x0 = a_point - m_vertices[0];
174  return amrex::Math::abs(x0.dotProduct(m_zdir));
175  }
176 
177  // Centroid of the polygon based on the sub-triangulation
178  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
179  amrex::RealVect get_centroid ( ) const noexcept {
180  amrex::RealVect cent(0.);
181  if (m_num_vertices==3) {
182  cent = (m_vertices[0] + m_vertices[1] + m_vertices[2]) / 3.0;
183  } else {
184  // Loop over sub-triangles
185  amrex::Real area(0.);
186  for ( int i(0); i<m_num_vertices-2; ++i) {
187  amrex::RealVect const v0 (m_vertices[i+1] - m_vertices[0]);
188  amrex::RealVect const v1 (m_vertices[i+2] - m_vertices[0]);
189  amrex::RealVect v0_cross_v1 = v0.crossProduct(v1);
190  amrex::Real area_tri = 0.5 * v0_cross_v1.vectorLength();
191  amrex::RealVect cent_tri = (m_vertices[0] + m_vertices[i+1] + m_vertices[i+2]) / 3.0;
192  area += area_tri;
193  cent += area_tri * cent_tri;
194  }
195  cent = cent / area;
196  }
197  return cent;
198  }
199 
200  // Unit normal vector
201  [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
202  amrex::RealVect normal () const noexcept {
203  return m_zdir;
204  }
205 
206 #ifndef AMREX_USE_GPU
207  void report ( int const a_id, amrex::RealVect a_v0 )
208 #else
209  void report ( int const /*a_id*/, amrex::RealVect /*a_v0*/ )
210 #endif
211  {
212 
213 #ifndef AMREX_USE_GPU
214  amrex::RealVect centroid = get_centroid();
215  amrex::Print() << "Face " << a_id
216  << " -------------------------------------------\n"
217  << "\nok? " << (ok() ? "yes" : "no") << "\n\n";
218  for (int i(0); i<m_num_vertices; ++i) {
219  amrex::Print() << "v" << i << ": " << m_vertices[i] << '\n';
220  }
221  amrex::Print() << "\nvc: " << " " << centroid << "\n";
222 
223  amrex::Real const dist = distance( a_v0 );
224  // amrex::Real const vol = ok() ? m_area * dist : 0.;
225 
226  amrex::Print() << "\narea: " << m_area
227  << "\ndistance: " << dist
228  << "\nvolume: " << dist*m_area
229  << "\n==================================================\n\n";
230 #endif
231  }
232 
233  void debug( int const a_id ) {
234  amrex::Print() << "EBPolygon: id = " << a_id << ", m_num_vertices = " << m_num_vertices << '\n';
235  for (int i(0); i<m_num_vertices; ++i) {
236  amrex::Print() << "EBPolygon: v" << i << ": " << m_vertices[i] << '\n';
237  }
238  }
239  void debug() {
240  debug(-1);
241  }
242 
243  private:
244 
245  static int constexpr m_max_vertices = 6;
246 
247  int const m_cell_face;
248 
249  amrex::RealVect const m_eb_point;
250  amrex::RealVect const m_eb_normal;
251 
253 
255 
257 
258  int m_sorted;
259 
260  amrex::Array<amrex::RealVect,m_max_vertices> m_vertices;
261 
262  amrex::GpuArray<amrex::Real,m_max_vertices> m_theta;
263 
264  amrex::RealVect m_zdir; // normal to polygon
265 };
266 
267 
268 #endif
constexpr amrex::Real PI
Definition: ERF_Constants.H:6
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_EBPolygon.H:9
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect get_centroid() const noexcept
Definition: ERF_EBPolygon.H:179
int m_defined
Definition: ERF_EBPolygon.H:252
AMREX_GPU_HOST_DEVICE int get_num_vertices()
Definition: ERF_EBPolygon.H:67
amrex::Real m_area
Definition: ERF_EBPolygon.H:256
amrex::Array< amrex::RealVect, m_max_vertices > m_vertices
Definition: ERF_EBPolygon.H:260
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int ok() const noexcept
Definition: ERF_EBPolygon.H:160
amrex::GpuArray< amrex::Real, m_max_vertices > m_theta
Definition: ERF_EBPolygon.H:262
AMREX_GPU_HOST_DEVICE void add_vertex(amrex::RealVect const &a_v)
Definition: ERF_EBPolygon.H:53
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real distance(amrex::RealVect const &a_point) const noexcept
Definition: ERF_EBPolygon.H:171
void debug(int const a_id)
Definition: ERF_EBPolygon.H:233
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real area() const noexcept
Definition: ERF_EBPolygon.H:164
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void set_area(amrex::Real const &a_area)
Definition: ERF_EBPolygon.H:72
AMREX_GPU_HOST void add_vertex(amrex::RealVect const &a_v, const std::string &msg, bool print_msg=false)
Definition: ERF_EBPolygon.H:43
void debug()
Definition: ERF_EBPolygon.H:239
int const m_cell_face
Definition: ERF_EBPolygon.H:247
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::RealVect normal() const noexcept
Definition: ERF_EBPolygon.H:202
int m_sorted
Definition: ERF_EBPolygon.H:258
amrex::RealVect const m_eb_normal
Definition: ERF_EBPolygon.H:250
static constexpr int m_max_vertices
Definition: ERF_EBPolygon.H:245
void report(int const a_id, amrex::RealVect a_v0)
Definition: ERF_EBPolygon.H:207
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void define()
Definition: ERF_EBPolygon.H:75
int m_num_vertices
Definition: ERF_EBPolygon.H:254
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:249
amrex::RealVect m_zdir
Definition: ERF_EBPolygon.H:264
real(c_double), private vi
Definition: ERF_module_mp_morr_two_moment.F90:219