HArD::Core2D
Hybrid Arbitrary Degree::Core 2D - Library to implement 2D schemes with edge and cell polynomials as unknowns
Loading...
Searching...
No Matches
Polytope2D.hpp
Go to the documentation of this file.
1// standard libraries
2#include <vector> // std::vector
3#include <algorithm> // std::find
4#include <fstream> // std::ofstream
5#include <assert.h> // to avoid using the assert from Eigen
6
7// external linking to Eigen is required
8#include <Eigen/Dense> // Eigen::Matrix, Eigen::MatrixXd, Eigen::FullPivLU
9
10// path to Math specified so that external linking is NOT required
11#include <../Math/math.hpp> // Math::factorial, Math::sgn
12
13#ifndef _POLYTOPE2D_HPP
14#define _POLYTOPE2D_HPP
15
16namespace Mesh2D
17{
18 inline constexpr int DIMENSION = 2;
19
20 using VectorRd = Eigen::Matrix<double, DIMENSION, 1>;
21 using VectorZd = Eigen::Matrix<int, DIMENSION, 1>;
22
23 template <size_t object_dim>
24 using Simplex = std::array<VectorRd, object_dim + 1>;
25
26 template <size_t object_dim>
27 using Simplices = std::vector<Simplex<object_dim>>;
28
30 template <size_t object_dim>
32
34 template <size_t object_dim>
36
37
44 // ----------------------------------------------------------------------------
45 // Polytope class definition
46 // ----------------------------------------------------------------------------
47
53 template <size_t object_dim>
55 {
56 public:
58 Polytope(size_t index, Simplices<object_dim> simplices);
59
61 Polytope(size_t index, Simplex<object_dim> simplex);
62
64 Polytope(size_t index, VectorRd vertex);
65
67 Polytope();
68
70 ~Polytope();
71
72 // inline size_t dim() const { return object_dim; }
73
74 inline size_t global_index() const { return _index; }
75 inline double diam() const { return _diameter; }
76 inline VectorRd center_mass() const { return _center_mass; }
77 inline double measure() const { return _measure; }
78 inline Simplices<object_dim> get_simplices() const { return _simplices; }
79 inline void set_global_index(const size_t idx) { _index = idx; }
80 inline bool is_boundary() const { return _is_boundary; }
81 inline void set_boundary(bool val) { _is_boundary = val; }
82
83 inline std::vector<Polytope<0> *> get_vertices() const { return _vertices; }
84 inline std::vector<Polytope<1> *> get_edges() const { return _edges; }
85 inline std::vector<Polytope<DIMENSION - 1> *> get_faces() const { return _edges; }
86 inline std::vector<Polytope<DIMENSION> *> get_cells() const { return _cells; }
87
88 inline size_t n_vertices() const { return _vertices.size(); }
89 inline size_t n_edges() const { return _edges.size(); }
90 inline size_t n_faces() const { return _edges.size(); }
91 inline size_t n_cells() const { return _cells.size(); }
92
93 Polytope<0> *vertex(const size_t i) const;
94 Polytope<1> *edge(const size_t i) const;
95 Polytope<DIMENSION - 1> *face(const size_t i) const;
96 Polytope<DIMENSION> *cell(const size_t i) const;
97
102
103 int index_vertex(const Polytope<0> *vertex) const;
104 int index_edge(const Polytope<1> *edge) const;
105 int index_face(const Polytope<DIMENSION - 1> *face) const;
106 int index_cell(const Polytope<DIMENSION> *cell) const;
107
108 VectorRd coords() const;
109
110 VectorRd face_normal(const size_t face_index) const;
111 VectorRd edge_normal(const size_t edge_index) const;
112
113 int face_orientation(const size_t face_index) const;
114 int edge_orientation(const size_t edge_index) const;
115 int vertex_orientation(const size_t vertex_index) const;
116
117 VectorRd normal() const;
118 VectorRd tangent() const;
119
121
122 void plot_simplices(std::ofstream *out) const;
123 void plot(std::ofstream *out) const;
124
125 private:
126 size_t _index;
127 VectorRd _center_mass;
128 double _measure;
129 double _diameter;
130 bool _is_boundary;
131 Simplices<object_dim> _simplices;
132 VectorRd _normal; // uninitialised unless object_dim == DIMENSION - 1 (face)
133 VectorRd _tangent; // uninitialised unless object_dim == 1 (edge)
134 std::vector<int> _face_directions; // empty unless object_dim == DIMENSION (cell)
135
136 std::vector<Polytope<0> *> _vertices;
137 std::vector<Polytope<1> *> _edges;
138 // std::vector<Polytope<DIMENSION - 1>*> _faces;
139 std::vector<Polytope<DIMENSION> *> _cells;
140 };
141
144
147
149 using Face = Polytope<DIMENSION - 1>;
150
153
155
156 // -----------------------------------------------------------------
157 // ----------- Implementation of templated functions ---------------
158 // -----------------------------------------------------------------
159
160 template <size_t object_dim>
162 {
163 VectorRd center_mass = VectorRd::Zero();
164
165 for (auto &coord : simplex)
166 {
167 for (size_t i = 0; i < DIMENSION; ++i)
168 {
169 center_mass(i) += coord(i);
170 }
171 }
172 return center_mass / (object_dim + 1);
173 }
174
175 template <size_t object_dim>
177 {
178 Eigen::MatrixXd CM_mat = Eigen::MatrixXd::Zero(object_dim + 2, object_dim + 2);
179 for (size_t i = 0; i < object_dim + 1; ++i)
180 {
181 VectorRd i_coords = simplex[i];
182 for (size_t j = i + 1; j < object_dim + 1; ++j)
183 {
184 VectorRd j_coords = simplex[j];
185 double norm = (j_coords - i_coords).norm();
186 CM_mat(i, j) = norm * norm;
187 CM_mat(j, i) = CM_mat(i, j);
188 }
189 CM_mat(i, object_dim + 1) = 1;
190 CM_mat(object_dim + 1, i) = 1;
191 }
192
193 // Calculate Cayley-Menger determinant
194 double det = CM_mat.determinant();
195
196 double scaling = std::pow(Math::factorial(object_dim), 2) * std::pow(2, object_dim);
197
198 return std::sqrt(std::abs(det / scaling));
199 }
200
201 template <size_t object_dim>
203 : _index(index), _simplices(simplices)
204 {
205 assert(object_dim <= DIMENSION);
206
207 if (object_dim == 0 || object_dim == 1)
208 {
209 assert(simplices.size() == 1);
210 }
211
212 _is_boundary = false; // by default, is_boundary is set to false. If polytope is on boundary, set is_boundary to true upon construction of the mesh.
213
214 _measure = 0.0;
215 _center_mass = VectorRd::Zero();
216 std::vector<VectorRd> vertex_coords;
217 for (auto &simplex : simplices)
218 {
219 // assert(simplex.size() == _dim + 1);
220 double measure_of_simplex = simplex_measure<object_dim>(simplex);
221 _measure += measure_of_simplex;
222 _center_mass += measure_of_simplex * simplex_center_mass<object_dim>(simplex);
223 for (auto &coord : simplex)
224 {
225 if (std::find(vertex_coords.begin(), vertex_coords.end(), coord) == vertex_coords.end())
226 {
227 vertex_coords.push_back(coord); // if coord not already in vertex_coords, add it
228 }
229 }
230 }
231 _center_mass /= _measure;
232
233 _diameter = 0.0;
234 for (auto it = vertex_coords.begin(); it != vertex_coords.end(); ++it)
235 {
236 for (auto jt = it; jt != vertex_coords.end(); ++jt)
237 {
238 _diameter = std::max(_diameter, (*it - *jt).norm());
239 }
240 }
241
242 if (object_dim == DIMENSION - 1) // find the tangent and normal
243 {
244 _tangent = (this->get_simplices()[0][1] - this->get_simplices()[0][0]).normalized();
245 _normal = VectorRd(-_tangent(1), _tangent(0));
246 }
247 }
248
249 template <size_t object_dim>
250 Polytope<object_dim>::Polytope(size_t index, Simplex<object_dim> simplex) // simplex
251 : Polytope(index, Simplices<object_dim>(1, simplex))
252 {
253 }
254
255 template <size_t object_dim>
256 Polytope<object_dim>::Polytope(size_t index, VectorRd vertex) // vertex
257 : Polytope(index, Simplex<object_dim>({vertex}))
258 {
259 assert(object_dim == 0); // must be a zero dimensional object to use vertex constructor
260 }
261
262 template <size_t object_dim>
264
265 template <size_t object_dim>
267
268 template <size_t object_dim>
270 {
271 assert(std::find(_vertices.begin(), _vertices.end(), vertex) == _vertices.end()); // ensure vertex does not already exist in _vertices
272 _vertices.push_back(vertex);
273 }
274
275 template <size_t object_dim>
277 {
278 assert(std::find(_edges.begin(), _edges.end(), edge) == _edges.end());
279 _edges.push_back(edge);
280 }
281
282 template <size_t object_dim>
284 {
285 assert(std::find(_edges.begin(), _edges.end(), face) == _edges.end());
286 _edges.push_back(face);
287 }
288
289 template <size_t object_dim>
291 {
292 assert(std::find(_cells.begin(), _cells.end(), cell) == _cells.end());
293 _cells.push_back(cell);
294 }
295
296 template <size_t object_dim>
298 {
299 assert(i < _vertices.size());
300 return _vertices[i];
301 }
302
303 template <size_t object_dim>
305 {
306 assert(i < _edges.size());
307 return _edges[i];
308 }
309
310 template <size_t object_dim>
312 {
313 assert(i < _edges.size());
314 return _edges[i];
315 }
316
317 template <size_t object_dim>
319 {
320 assert(i < _cells.size());
321 return _cells[i];
322 }
323
324 template <size_t object_dim>
325 void Polytope<object_dim>::construct_face_normals() // not very efficient - probably room for improvement
326 {
327 assert(object_dim == DIMENSION);
328 for (size_t iF = 0; iF < _edges.size(); ++iF)
329 {
330 VectorRd normal = _edges[iF]->normal();
331 Simplex<object_dim - 1> face_simplex = _edges[iF]->get_simplices()[0];
332 VectorRd center = VectorRd::Zero();
333 double count;
334 for (auto &cell_simplex : this->get_simplices())
335 {
336 count = 0;
337 for (size_t i = 0; (i < cell_simplex.size()) && count < 2; ++i)
338 {
339 if (std::find(face_simplex.begin(), face_simplex.end(), cell_simplex[i]) == face_simplex.end()) // requires numerical precision
340 {
341 ++count;
342 }
343 }
344 if (count == 1) // only don't share one coordinate
345 {
346 center = simplex_center_mass<object_dim>(cell_simplex);
347 break;
348 }
349 }
350 assert(count == 1);
351 _face_directions.push_back(Math::sgn((_edges[iF]->center_mass() - center).dot(normal)));
352 assert(_face_directions[iF] != 0);
353 }
354 }
355
356 template <size_t object_dim>
357 VectorRd Polytope<object_dim>::face_normal(const size_t face_index) const
358 {
359 assert(object_dim == DIMENSION);
360 assert(face_index < _edges.size());
361 return _face_directions[face_index] * _edges[face_index]->normal();
362 }
363
364 template <size_t object_dim>
365 VectorRd Polytope<object_dim>::edge_normal(const size_t edge_index) const
366 {
367 return this->face_normal(edge_index);
368 }
369
370 template <size_t object_dim>
371 VectorRd Polytope<object_dim>::coords() const // only for vertices
372 {
373 assert(object_dim == 0); // can only return coordinate of a vertex
374 return this->get_simplices()[0][0]; // only has one simplex, with one coordinate
375 }
376
377 template <size_t object_dim>
379 {
380 assert(object_dim == DIMENSION - 1);
381 return _normal;
382 }
383
384 template <size_t object_dim>
386 {
387 assert(object_dim == 1);
388 return _tangent;
389 // return (this->get_vertices()[1]->coords() - this->get_vertices()[0]->coords()).normalized();
390 }
391
392 template <size_t object_dim>
394 {
395 auto itr = std::find(_vertices.begin(), _vertices.end(), vertex);
396 if (itr != _vertices.end())
397 {
398 return itr - _vertices.begin();
399 }
400 else
401 {
402 throw "Vertex not found";
403 }
404 }
405
406 template <size_t object_dim>
408 {
409 auto itr = std::find(_edges.begin(), _edges.end(), edge);
410 if (itr != _edges.end())
411 {
412 return itr - _edges.begin();
413 }
414 else
415 {
416 throw "Edge not found";
417 }
418 }
419
420 template <size_t object_dim>
422 {
423 auto itr = std::find(_edges.begin(), _edges.end(), face);
424 if (itr != _edges.end())
425 {
426 return itr - _edges.begin();
427 }
428 else
429 {
430 throw "Face not found";
431 }
432 }
433
434 template <size_t object_dim>
436 {
437 auto itr = std::find(_cells.begin(), _cells.end(), cell);
438 if (itr != _cells.end())
439 {
440 return itr - _cells.begin();
441 }
442 else
443 {
444 throw "Cell not found";
445 }
446 }
447
448 template <size_t object_dim>
449 int Polytope<object_dim>::face_orientation(const size_t face_index) const
450 {
451 assert(object_dim == DIMENSION);
452 assert(face_index < _edges.size());
453 return _face_directions[face_index];
454 }
455
456 template <size_t object_dim>
457 int Polytope<object_dim>::edge_orientation(const size_t edge_index) const
458 {
459 assert(object_dim == 2);
460 assert(edge_index < _edges.size());
461 return _face_directions[edge_index];
462 }
463
464 template <size_t object_dim>
465 int Polytope<object_dim>::vertex_orientation(const size_t vertex_index) const
466 {
467 assert(object_dim == 1);
468 assert(vertex_index < _vertices.size());
469 return ( (_vertices[vertex_index]->coords()-_center_mass).dot(this->tangent()) > 0 ? 1 : -1);
470 }
471
472 template <size_t object_dim>
473 void Polytope<object_dim>::plot_simplices(std::ofstream *out) const
474 {
475 assert(object_dim > 0);
476 for (auto &simplex : _simplices)
477 {
478 for (size_t i = 0; i < object_dim + 1; ++i)
479 {
480 size_t i_next = (i + 1) % (object_dim + 1);
481 *out << simplex[i](0) << " " << simplex[i](1) << std::endl;
482 *out << simplex[i_next](0) << " " << simplex[i_next](1) << std::endl;
483 *out << std::endl;
484 }
485 }
486 }
487
488 template <size_t object_dim>
489 void Polytope<object_dim>::plot(std::ofstream *out) const
490 {
491 assert(object_dim > 0);
492 for (size_t i = 0; i < _vertices.size(); ++i)
493 {
494 size_t i_next = (i + 1) % _vertices.size();
495 *out << _vertices[i]->coords()(0) << " " << _vertices[i]->coords()(1) << std::endl;
496 *out << _vertices[i_next]->coords()(0) << " " << _vertices[i_next]->coords()(1) << std::endl;
497 *out << std::endl;
498 }
499 }
500
501} // namespace Mesh2D
502
503#endif
A Vertex is a Polytope with object_dim = 0.
Definition Polytope2D.hpp:55
for i
Definition convergence_analysis.m:48
for j
Definition convergence_analysis.m:19
it
Definition extract_phi_min_max.m:16
VectorRd normal() const
Return the normal of a Face.
Definition Polytope2D.hpp:378
double measure() const
Return the Lebesgue measure of the Polytope.
Definition Polytope2D.hpp:77
void construct_face_normals()
Set the directions of the face normals of a cell.
Definition Polytope2D.hpp:325
int index_cell(const Polytope< DIMENSION > *cell) const
Returns the local index of a cell.
Definition Polytope2D.hpp:435
int index_edge(const Polytope< 1 > *edge) const
Returns the local index of an edge.
Definition Polytope2D.hpp:407
void add_edge(Polytope< 1 > *edge)
Add an edge to the Polytope.
Definition Polytope2D.hpp:276
VectorRd center_mass() const
Return the center mass of the Polytope.
Definition Polytope2D.hpp:76
void plot(std::ofstream *out) const
Plot the polytope to out.
Definition Polytope2D.hpp:489
std::vector< Polytope< DIMENSION > * > get_cells() const
Return the cells of the Polytope.
Definition Polytope2D.hpp:86
VectorRd tangent() const
Return the tangent of a Edge.
Definition Polytope2D.hpp:385
void set_global_index(const size_t idx)
Set the global index.
Definition Polytope2D.hpp:79
size_t n_vertices() const
Return the number of vertices of the Polytope.
Definition Polytope2D.hpp:88
void plot_simplices(std::ofstream *out) const
Plot the simplices to out.
Definition Polytope2D.hpp:473
VectorRd face_normal(const size_t face_index) const
Return the outer normal of a Cell towards the Face located at face_index.
Definition Polytope2D.hpp:357
size_t n_edges() const
Return the number of edges of the Polytope.
Definition Polytope2D.hpp:89
int index_face(const Polytope< DIMENSION - 1 > *face) const
Returns the local index of a face.
Definition Polytope2D.hpp:421
void add_vertex(Polytope< 0 > *vertex)
Add a vertex to the Polytope.
Definition Polytope2D.hpp:269
void add_cell(Polytope< DIMENSION > *cell)
Add a cell to the Polytope.
Definition Polytope2D.hpp:290
int index_vertex(const Polytope< 0 > *vertex) const
Returns the local index of a vertex.
Definition Polytope2D.hpp:393
Polytope< DIMENSION > * cell(const size_t i) const
Return the i-th cell of the Polytope.
Definition Polytope2D.hpp:318
int vertex_orientation(const size_t vertex_index) const
Return the orientation of a Vertex.
Definition Polytope2D.hpp:465
std::vector< Polytope< DIMENSION - 1 > * > get_faces() const
Return the faces of the Polytope.
Definition Polytope2D.hpp:85
double diam() const
Return the diameter of the Polytope.
Definition Polytope2D.hpp:75
~Polytope()
Definition Polytope2D.hpp:266
Polytope< DIMENSION - 1 > * face(const size_t i) const
Return the i-th face of the Polytope.
Definition Polytope2D.hpp:311
void add_face(Polytope< DIMENSION - 1 > *face)
Add a face to the Polytope.
Definition Polytope2D.hpp:283
void set_boundary(bool val)
Set the boundary value of the Polytope.
Definition Polytope2D.hpp:81
size_t n_faces() const
Return the number of faces of the Polytope.
Definition Polytope2D.hpp:90
Polytope< 1 > * edge(const size_t i) const
Return the i-th edge of the Polytope.
Definition Polytope2D.hpp:304
std::vector< Polytope< 0 > * > get_vertices() const
Return the vertices of the Polytope.
Definition Polytope2D.hpp:83
bool is_boundary() const
Return true if Polytope is a boundary object, false otherwise.
Definition Polytope2D.hpp:80
VectorRd edge_normal(const size_t edge_index) const
Return the edge normal of a 2D object.
Definition Polytope2D.hpp:365
double simplex_measure(Simplex< object_dim > simplex)
Definition Polytope2D.hpp:176
size_t global_index() const
Return the global index of the Polytope.
Definition Polytope2D.hpp:74
std::vector< Polytope< 1 > * > get_edges() const
Return the edges of the Polytope.
Definition Polytope2D.hpp:84
int face_orientation(const size_t face_index) const
Return the orientation of a Face.
Definition Polytope2D.hpp:449
Polytope()
Destructor.
Definition Polytope2D.hpp:263
Simplices< object_dim > get_simplices() const
Return the simplices making up the Polytope.
Definition Polytope2D.hpp:78
int edge_orientation(const size_t edge_index) const
Return the orientation of a Edge.
Definition Polytope2D.hpp:457
Polytope< 0 > * vertex(const size_t i) const
Return the i-th vertex of the Polytope.
Definition Polytope2D.hpp:297
VectorRd simplex_center_mass(Simplex< object_dim > simplex)
Method to find the Lebesgue measure of an arbitrary simplex in arbitrary space.
Definition Polytope2D.hpp:161
VectorRd coords() const
Return the coordinates of a Vertex.
Definition Polytope2D.hpp:371
size_t n_cells() const
Return the number of cells of the Polytope.
Definition Polytope2D.hpp:91
end Read size then branch according to sparse or dense format count
Definition mmread.m:75
const int sgn(T val)
Definition math.hpp:42
const size_t factorial(size_t n)
Definition math.hpp:12
Definition Mesh2D.hpp:7
std::array< VectorRd, object_dim+1 > Simplex
Definition Polytope2D.hpp:24
constexpr int DIMENSION
Definition Polytope2D.hpp:18
std::vector< Simplex< object_dim > > Simplices
Method to find the center mass of an arbitrary simplex in arbitrary space.
Definition Polytope2D.hpp:29
Eigen::Matrix< int, DIMENSION, 1 > VectorZd
Definition Polytope2D.hpp:21
Eigen::Matrix< double, DIMENSION, 1 > VectorRd
Definition Polytope2D.hpp:20