HArD::Core3D
Hybrid Arbitrary Degree::Core 3D - Library to implement 3D schemes with vertex, edge, face and cell polynomials as unknowns
MeshObject.hpp
Go to the documentation of this file.
1 #include <array>
2 #include <vector>
3 #include <map>
4 #include <iostream>
5 #include <cmath>
6 #include <Eigen/Dense>
7 #include <math.hpp>
8 #include <algorithm>
9 // #include <Eigen/FullPivLU>
10 
11 #ifndef _MESHOBJECT_HPP
12 #define _MESHOBJECT_HPP
13 
14 namespace MeshND
15 {
16  template <size_t space_dim>
17  using VectorRd = Eigen::Matrix<double, space_dim, 1>;
18 
19  template <size_t space_dim>
20  using VectorZd = Eigen::Matrix<int, space_dim, 1>;
21 
22  template <size_t space_dim, size_t object_dim>
23  using Simplex = std::array<VectorRd<space_dim>, object_dim + 1>;
24 
25  template <size_t space_dim, size_t object_dim>
26  using Simplices = std::vector<Simplex<space_dim, object_dim>>;
27 
29  template <size_t space_dim, size_t object_dim>
31 
33  template <size_t space_dim, size_t object_dim>
35 
46  // ----------------------------------------------------------------------------
47  // MeshObject class definition
48  // ----------------------------------------------------------------------------
49 
55  template <size_t space_dim, size_t object_dim>
56  class MeshObject
57  {
58  public:
60  MeshObject(size_t index, Simplices<space_dim, object_dim> simplices);
61 
63  MeshObject(size_t index, Simplex<space_dim, object_dim> simplex);
64 
66  MeshObject(size_t index, VectorRd<space_dim> vertex);
67 
69  MeshObject();
70 
72  ~MeshObject();
73 
74  // inline size_t dim() const { return object_dim; }
75 
77  inline size_t global_index() const { return _index; }
79  inline double diam() const { return _diameter; }
81  inline VectorRd<space_dim> center_mass() const { return _center_mass; }
83  inline double measure() const { return _measure; }
84 
86  inline Simplices<space_dim, object_dim> get_simplices() const { return _simplices; }
87  inline Simplices<space_dim, object_dim>& set_simplices() { return _simplices; }
89  inline void set_global_index(const size_t idx) { _index = idx; }
91  inline bool is_boundary() const { return _is_boundary; }
93  inline void set_boundary(bool val) { _is_boundary = val; }
95  inline bool is_flat() const { return _is_flat; }
96 
98  inline std::vector<MeshObject<space_dim, 0>*> get_vertices() const { return _vertices; }
100  inline std::vector<MeshObject<space_dim, 1>*> get_edges() const { return _edges; }
102  inline std::vector<MeshObject<space_dim, space_dim - 1>*> get_faces() const { return _faces; }
104  inline std::vector<MeshObject<space_dim, space_dim>*> get_cells() const { return _cells; }
105 
107  inline size_t n_vertices() const { return _vertices.size(); }
109  inline size_t n_edges() const { return _edges.size(); }
111  inline size_t n_faces() const { return _faces.size(); }
113  inline size_t n_cells() const { return _cells.size(); }
114 
115  MeshObject<space_dim, 0>* vertex(const size_t i) const;
116  MeshObject<space_dim, 1>* edge(const size_t i) const;
117  MeshObject<space_dim, space_dim - 1>* face(const size_t i) const;
118  MeshObject<space_dim, space_dim>* cell(const size_t i) const;
119 
124 
125  int index_vertex(const MeshObject<space_dim, 0>* vertex) const;
126  int index_edge(const MeshObject<space_dim, 1>* edge) const;
129 
130  VectorRd<space_dim> coords() const;
131  void set_coords(const VectorRd<space_dim> & x);
132 
133  VectorRd<space_dim> face_normal(const size_t face_index) const;
134  VectorRd<space_dim> edge_normal(const size_t edge_index) const;
135 
136  int face_orientation(const size_t face_index) const;
137  int edge_orientation(const size_t edge_index) const;
138 
139  int induced_orientation(const size_t index) const;
140 
141  VectorRd<space_dim> normal() const;
142  VectorRd<space_dim> tangent() const;
143  Eigen::Matrix<double,space_dim,2> face_tangent() const;
144 
146 
147  private:
148  size_t _index;
149  VectorRd<space_dim> _center_mass;
150  double _measure;
151  double _diameter;
152  bool _is_boundary;
153  bool _is_flat; // To record non-planar faces
155  VectorRd<space_dim> _normal; // uninitialised unless object_dim == space_dim - 1 (face)
156  std::vector<int> _face_directions; // empty unless object_dim == space_dim (cell)
157 
158  std::vector<MeshObject<space_dim, 0>*> _vertices;
159  std::vector<MeshObject<space_dim, 1>*> _edges;
160  std::vector<MeshObject<space_dim, space_dim - 1>*> _faces;
161  std::vector<MeshObject<space_dim, space_dim>*> _cells;
162  };
163 
165  template <size_t space_dim>
167 
169  template <size_t space_dim>
171 
173  template <size_t space_dim>
174  using Face = MeshObject<space_dim, space_dim - 1>;
175 
177  template <size_t space_dim>
179 
181 
182  // -----------------------------------------------------------------
183  // ----------- Implementation of templated functions ---------------
184  // -----------------------------------------------------------------
185 
186  template <size_t space_dim, size_t object_dim>
188  {
189  VectorRd<space_dim> center_mass = Eigen::VectorXd::Zero(space_dim);
190 
191  for (auto& coord : simplex)
192  {
193  for (size_t i = 0; i < space_dim; ++i)
194  {
195  center_mass(i) += coord(i);
196  }
197  }
198  return center_mass / (object_dim + 1);
199  }
200 
201  template <size_t space_dim, size_t object_dim>
203  {
204  Eigen::MatrixXd CM_mat = Eigen::MatrixXd::Zero(object_dim + 2, object_dim + 2);
205  for (size_t i = 0; i < object_dim + 1; ++i)
206  {
207  VectorRd<space_dim> i_coords = simplex[i];
208  for (size_t j = i + 1; j < object_dim + 1; ++j)
209  {
210  VectorRd<space_dim> j_coords = simplex[j];
211  double norm = (j_coords - i_coords).norm();
212  CM_mat(i, j) = norm * norm;
213  CM_mat(j, i) = CM_mat(i, j);
214  }
215  CM_mat(i, object_dim + 1) = 1;
216  CM_mat(object_dim + 1, i) = 1;
217  }
218 
219  // Calculate Cayley-Menger determinant
220  double det = CM_mat.determinant();
221  double scaling = std::pow(Math::factorial(object_dim), 2) * std::pow(2, object_dim);
222 
223  return std::sqrt(std::abs(det / scaling));
224  }
225 
226  template <size_t space_dim, size_t object_dim>
228  : _index(index), _simplices(simplices)
229  {
230  assert(space_dim >= object_dim);
231  assert(space_dim >= 2);
232 
233  if (object_dim == 0 || object_dim == 1)
234  {
235  assert(simplices.size() == 1);
236  }
237 
238  _is_boundary = false;
239 
240  _measure = 0.0;
241  _center_mass = Eigen::VectorXd::Zero(space_dim);
242  std::vector<VectorRd<space_dim>> vertex_coords;
243  for (auto& simplex : simplices)
244  {
245  // assert(simplex.size() == _dim + 1);
246  double tmp = simplex_measure<space_dim, object_dim>(simplex);
247  _measure += tmp;
248  _center_mass += tmp * simplex_center_mass<space_dim, object_dim>(simplex);
249  for (auto& coord : simplex)
250  {
251  if (std::find(vertex_coords.begin(), vertex_coords.end(), coord) == vertex_coords.end())
252  {
253  vertex_coords.push_back(coord); // if coord not already in vertex_coords, add it
254  }
255  }
256  }
257  _center_mass /= _measure;
258 
259  _diameter = 0.0;
260  for (auto it = vertex_coords.begin(); it != vertex_coords.end(); ++it)
261  {
262  for (auto jt = it; jt != vertex_coords.end(); ++jt)
263  {
264  _diameter = std::max(_diameter, (*it - *jt).norm()); // probably more efficient methods
265  }
266  }
267 
268  _is_flat = true;
269 
270  if (object_dim == space_dim - 1) // find the normal to the face and check if it is flat
271  {
272  // We compute the normal using the most perpendicular pair of vectors created from the center to any vertex
273  // Find all points in the face that are not the center of mass
274  std::vector<VectorRd<space_dim>> points_in_face;
275  for (size_t i = 0; i < _simplices.size(); ++i)
276  {
277  for (size_t j = 0; j < space_dim; ++j)
278  {
279  if( (std::find(points_in_face.begin(), points_in_face.end(), _simplices[i][j]) == points_in_face.end()) && ( (_simplices[i][j]-_center_mass).norm()>1e-8 * _diameter) )
280  {
281  points_in_face.push_back(_simplices[i][j]);
282  }
283  }
284  }
285 
287  double norm_perp_vec = 0.;
288  for (size_t iV = 0 ; iV < points_in_face.size(); iV++){
289  VectorRd<space_dim> t1 = (points_in_face[iV] - _center_mass).normalized();
290  for (size_t iVp = iV+1; iVp < points_in_face.size(); iVp++){
291  VectorRd<space_dim> t2 = (points_in_face[iVp] - _center_mass).normalized();
292  VectorRd<space_dim> tmp = t1.cross(t2);
293  double norm_tmp = tmp.norm();
294  if (norm_tmp > norm_perp_vec){
295  perp_vec = tmp;
296  norm_perp_vec = norm_tmp;
297  }
298  }
299  }
300  _normal = perp_vec / norm_perp_vec;
301 
302  // Checking that the face is planar: all points_in_face should lie in the plane orthogonal to _normal at the center of mass
303  for (size_t iV = 0; iV < points_in_face.size(); iV++){
304  VectorRd<space_dim> v_xF = points_in_face[iV]-_center_mass;
305  if (std::abs( v_xF.dot(_normal) ) > 1e-8 * v_xF.norm()){
306  _is_flat = false;
307  }
308  }
309 
310  }
311  }
312 
313  template <size_t space_dim, size_t object_dim>
315  : MeshObject(index, Simplices<space_dim, object_dim>(1, simplex))
316  {
317  }
318 
319  template <size_t space_dim, size_t object_dim>
321  : MeshObject(index, Simplex<space_dim, object_dim>({ vertex }))
322  {
323  assert(object_dim == 0);
324  }
325 
326  template <size_t space_dim, size_t object_dim>
328 
329  template <size_t space_dim, size_t object_dim>
331 
332  template <size_t space_dim, size_t object_dim>
334  {
335  assert(std::find(_vertices.begin(), _vertices.end(), vertex) == _vertices.end());
336  _vertices.push_back(vertex);
337  }
338 
339  template <size_t space_dim, size_t object_dim>
341  {
342  assert(std::find(_edges.begin(), _edges.end(), edge) == _edges.end());
343  _edges.push_back(edge);
344  if (space_dim == 2)
345  {
346  assert(std::find(_faces.begin(), _faces.end(), reinterpret_cast<MeshObject<space_dim, space_dim - 1> *>(edge)) == _faces.end());
347  _faces.push_back(reinterpret_cast<MeshObject<space_dim, space_dim - 1> *>(edge));
348  }
349  }
350 
351  template <size_t space_dim, size_t object_dim>
353  {
354  assert(std::find(_faces.begin(), _faces.end(), face) == _faces.end());
355  _faces.push_back(face);
356  if (space_dim == 2)
357  {
358  assert(std::find(_edges.begin(), _edges.end(), reinterpret_cast<MeshObject<space_dim, 1> *>(face)) == _edges.end());
359  _edges.push_back(reinterpret_cast<MeshObject<space_dim, 1> *>(face));
360  }
361  }
362 
363  template <size_t space_dim, size_t object_dim>
365  {
366  assert(std::find(_cells.begin(), _cells.end(), cell) == _cells.end());
367  _cells.push_back(cell);
368  }
369 
370  template <size_t space_dim, size_t object_dim>
372  {
373  assert(i < _vertices.size());
374  return _vertices[i];
375  }
376 
377  template <size_t space_dim, size_t object_dim>
379  {
380  assert(i < _edges.size());
381  return _edges[i];
382  }
383 
384  template <size_t space_dim, size_t object_dim>
385  MeshObject<space_dim, space_dim - 1>* MeshObject<space_dim, object_dim>::face(const size_t i) const
386  {
387  assert(i < _faces.size());
388  return _faces[i];
389  }
390 
391  template <size_t space_dim, size_t object_dim>
393  {
394  assert(i < _cells.size());
395  return _cells[i];
396  }
397 
398  template <size_t space_dim, size_t object_dim>
399  void MeshObject<space_dim, object_dim>::construct_face_orientations() // not very efficient - probably room for improvement
400  {
401  assert(object_dim == space_dim);
402  for (size_t iF = 0; iF < _faces.size(); ++iF)
403  {
404  VectorRd<space_dim> normal = _faces[iF]->normal();
405  Simplex<space_dim, object_dim - 1> face_simplex = _faces[iF]->get_simplices()[0];
406  VectorRd<space_dim> center = Eigen::VectorXd::Zero(space_dim);
407  double count;
408  for (auto& cell_simplex : this->get_simplices())
409  {
410  count = 0;
411  for (size_t i = 0; (i < cell_simplex.size()) && count < 2; ++i)
412  {
413  if (std::find(face_simplex.begin(), face_simplex.end(), cell_simplex[i]) == face_simplex.end())
414  {
415  ++count;
416  }
417  }
418  if (count == 1) // only don't share one coordinate
419  {
420  center = simplex_center_mass<space_dim, object_dim>(cell_simplex);
421  break;
422  }
423  }
424  assert(count == 1);
425  // _face_directions.push_back(Math::sgn((_faces[iF]->center_mass() - _center_mass).dot(normal))); // star shaped wrt center mass
426  _face_directions.push_back(Math::sgn((_faces[iF]->center_mass() - center).dot(normal)));
427  assert(_face_directions[iF] != 0);
428  }
429  }
430 
431  template <size_t space_dim, size_t object_dim>
433  {
434  assert(object_dim == space_dim);
435  assert(face_index < _faces.size());
436  return _face_directions[face_index] * _faces[face_index]->normal();
437  }
438 
439  template <size_t space_dim, size_t object_dim>
441  {
442  assert(object_dim == 2);
443  if (space_dim == 2)
444  {
445  return this->face_normal(edge_index);
446  }
447  if (space_dim == 3)
448  {
449  VectorRd<space_dim> edge_normal = _normal.cross(_edges[edge_index]->tangent()); // unit vector as normal and tangent are orthogonal unit vectors
450  return edge_normal;
451  }
452  }
453 
454  template <size_t space_dim, size_t object_dim>
456  {
457  assert(object_dim == 0);
458  return this->get_simplices()[0][0];
459  }
460 
461  template <size_t space_dim, size_t object_dim>
463  {
464  assert(object_dim == 0);
465  this->set_simplices()[0][0] = x;
466  }
467 
468  template <size_t space_dim, size_t object_dim>
470  {
471  assert(object_dim == space_dim - 1);
472  return _normal;
473  }
474 
475  template <size_t space_dim, size_t object_dim>
477  {
478  assert(object_dim == 1);
479  return (this->get_vertices()[1]->coords() - this->get_vertices()[0]->coords()).normalized();
480  }
481 
482  template <size_t space_dim, size_t object_dim>
483  Eigen::Matrix<double,space_dim,2> MeshObject<space_dim, object_dim>::face_tangent() const
484  {
485  assert(object_dim == 2);
486  Eigen::Matrix<double,space_dim,2> rv;
487  rv.col(0) = edge(0)->tangent();
488  rv.col(1) = edge_normal(0);
489  return rv;
490  }
491 
492  template <size_t space_dim, size_t object_dim>
494  {
495  auto itr = std::find(_vertices.begin(), _vertices.end(), vertex);
496  if (itr != _vertices.end())
497  {
498  return itr - _vertices.begin();
499  }
500  else
501  {
502  throw "Vertex not found";
503  }
504  }
505 
506  template <size_t space_dim, size_t object_dim>
508  {
509  auto itr = std::find(_edges.begin(), _edges.end(), edge);
510  if (itr != _edges.end())
511  {
512  return itr - _edges.begin();
513  }
514  else
515  {
516  throw "Edge not found";
517  }
518  }
519 
520  template <size_t space_dim, size_t object_dim>
522  {
523  auto itr = std::find(_faces.begin(), _faces.end(), face);
524  if (itr != _faces.end())
525  {
526  return itr - _faces.begin();
527  }
528  else
529  {
530  throw "Face not found";
531  }
532  }
533 
534  template <size_t space_dim, size_t object_dim>
536  {
537  auto itr = std::find(_cells.begin(), _cells.end(), cell);
538  if (itr != _cells.end())
539  {
540  return itr - _cells.begin();
541  }
542  else
543  {
544  throw "Cell not found";
545  }
546  }
547  template <size_t space_dim, size_t object_dim>
548  int MeshObject<space_dim, object_dim>::face_orientation(const size_t face_index) const
549  {
550  assert(object_dim == space_dim);
551  assert(face_index < _faces.size());
552  return _face_directions[face_index];
553  }
554  template <size_t space_dim, size_t object_dim>
555  int MeshObject<space_dim, object_dim>::edge_orientation(const size_t edge_index) const
556  {
557  assert(object_dim == 2);
558  assert(edge_index < _edges.size());
559  return Math::sgn((_edges[edge_index]->center_mass() - this->center_mass()).dot(this->edge_normal(edge_index))); // assuming face is star-shaped wrt face-center !!
560  }
561  template <size_t space_dim, size_t object_dim>
563  {
564  assert((object_dim == 2 && index < _edges.size())||(object_dim == 3 && index < _faces.size()));
565  if constexpr(object_dim == 2) {
566  VectorRd<space_dim> const n = edge_orientation(index)*edge_normal(index),
567  t = edge(index)->tangent();
568  Eigen::Matrix<double,space_dim,2> const ab = face_tangent();
569  return Math::sgn(ab.col(0).dot(n)*ab.col(1).dot(t) - ab.col(0).dot(t)*ab.col(1).dot(n));
570  // If vol_f = da^db, vol_E = dt and n is the outward unit vector
571  // then da^db = (da(n)*db(t) - da(t)*db(n))dn^dt, hence i_{n}(da^db) = (da(n)*db(t) - da(t)*db(n))dn^dt
572  // The induced orientation on E is then sgn(da(n)*db(t) - da(t)*db(n)) dt
573  // sgn(da(n)*db(t) - da(t)*db(n)) should be equal to da(n)*db(t) - da(t)*db(n)
574  } else { // object_dim == 3
575  Eigen::Matrix<double,space_dim,object_dim> nab;
576  nab.rightCols(2) = face(index)->face_tangent();
577  nab.leftCols(1) = face_normal(index); // This seems inconsistent with the behavior in 2D, why does this one is outer and not edge_orientation?
578  return Math::sgn(nab.determinant());
579  // We assume that the volume form on T is dx^dy^dz, then dx^dy^dz = det(n,a,b) dn^da^db
580  // The induced orientation on F is then sign(det(n,a,b))
581  }
582  }
583 
584 } // namespace MeshND
585 
586 #endif
Generic class to describe a cell, face, edge or vertex.
Definition: MeshObject.hpp:57
int index_edge(const MeshObject< space_dim, 1 > *edge) const
Returns the local index of an edge.
Definition: MeshObject.hpp:507
~MeshObject()
Destructor.
Definition: MeshObject.hpp:330
double simplex_measure(Simplex< space_dim, object_dim > simplex)
Method to find the Lebesgue measure of an arbitrary simplex in arbitrary space.
Definition: MeshObject.hpp:202
int face_orientation(const size_t face_index) const
Return the orientation of a Face.
Definition: MeshObject.hpp:548
void add_face(MeshObject< space_dim, space_dim - 1 > *face)
Add a face to the MeshObject.
Definition: MeshObject.hpp:352
int edge_orientation(const size_t edge_index) const
Return the orientation of a Edge (multiplied by edge_normal, gives the outer normal to the face)
Definition: MeshObject.hpp:555
std::vector< MeshObject< space_dim, 1 > * > get_edges() const
Returns the edges of the MeshObject.
Definition: MeshObject.hpp:100
size_t n_vertices() const
Returns the number of vertices of the MeshObject.
Definition: MeshObject.hpp:107
VectorRd< space_dim > simplex_center_mass(Simplex< space_dim, object_dim > simplex)
Method to find the center mass of an arbitrary simplex in arbitrary space.
Definition: MeshObject.hpp:187
MeshObject< space_dim, space_dim - 1 > * face(const size_t i) const
Returns the i-th face of the MeshObject.
Definition: MeshObject.hpp:385
size_t n_cells() const
Returns the number of cells of the MeshObject.
Definition: MeshObject.hpp:113
MeshObject< space_dim, space_dim > * cell(const size_t i) const
Returns the i-th cell of the MeshObject.
Definition: MeshObject.hpp:392
VectorRd< space_dim > face_normal(const size_t face_index) const
Return the outer normal of a Cell towards the Face located at face_index.
Definition: MeshObject.hpp:432
double diam() const
Returns the diameter of the MeshObject.
Definition: MeshObject.hpp:79
std::vector< MeshObject< space_dim, 0 > * > get_vertices() const
Returns the vertices of the MeshObject.
Definition: MeshObject.hpp:98
Simplices< space_dim, object_dim > & set_simplices()
Definition: MeshObject.hpp:87
VectorRd< space_dim > coords() const
Return the coordinates of a Vertex.
Definition: MeshObject.hpp:455
std::vector< MeshObject< space_dim, space_dim > * > get_cells() const
Return the cells of the MeshObject.
Definition: MeshObject.hpp:104
int induced_orientation(const size_t index) const
Return 1 if the volume form on the boundary is positively oriented, -1 else.
Definition: MeshObject.hpp:562
void add_edge(MeshObject< space_dim, 1 > *edge)
Add an edge to the MeshObject.
Definition: MeshObject.hpp:340
Eigen::Matrix< double, space_dim, 2 > face_tangent() const
Return the tangent space of a Face.
Definition: MeshObject.hpp:483
VectorRd< space_dim > center_mass() const
Returns the center mass of the MeshObject.
Definition: MeshObject.hpp:81
double measure() const
Definition: MeshObject.hpp:83
size_t global_index() const
Returns the global index of the MeshObject.
Definition: MeshObject.hpp:77
void set_boundary(bool val)
Set the boundary value of the MeshObject.
Definition: MeshObject.hpp:93
void set_coords(const VectorRd< space_dim > &x)
Set the coordinates of a Vertex.
Definition: MeshObject.hpp:462
MeshObject< space_dim, 1 > * edge(const size_t i) const
Returns the i-th edge of the MeshObject.
Definition: MeshObject.hpp:378
size_t n_faces() const
Returns the number of faces of the MeshObject.
Definition: MeshObject.hpp:111
int index_face(const MeshObject< space_dim, space_dim - 1 > *face) const
Returns the local index of a face.
Definition: MeshObject.hpp:521
void add_vertex(MeshObject< space_dim, 0 > *vertex)
Add a vertex to the MeshObject.
Definition: MeshObject.hpp:333
bool is_boundary() const
Returns true if MeshObject is a boundary object, false otherwise.
Definition: MeshObject.hpp:91
size_t n_edges() const
Returns the number of edges of the MeshObject.
Definition: MeshObject.hpp:109
MeshObject()
Null constructor.
Definition: MeshObject.hpp:327
MeshObject< space_dim, 0 > * vertex(const size_t i) const
Returns the i-th vertex of the MeshObject.
Definition: MeshObject.hpp:371
int index_cell(const MeshObject< space_dim, space_dim > *cell) const
Returns the local index of a cell.
Definition: MeshObject.hpp:535
void set_global_index(const size_t idx)
Set the global index.
Definition: MeshObject.hpp:89
VectorRd< space_dim > normal() const
Return the normal of a Face.
Definition: MeshObject.hpp:469
bool is_flat() const
Returns true if MeshObject is flat (only relevant for faces), false otherwise.
Definition: MeshObject.hpp:95
VectorRd< space_dim > edge_normal(const size_t edge_index) const
Return the edge normal of a 2D object.
Definition: MeshObject.hpp:440
Simplices< space_dim, object_dim > get_simplices() const
Returns the simplices making up the MeshObject.
Definition: MeshObject.hpp:86
VectorRd< space_dim > tangent() const
Return the tangent of a Edge.
Definition: MeshObject.hpp:476
std::vector< MeshObject< space_dim, space_dim - 1 > * > get_faces() const
Returns the faces of the MeshObject.
Definition: MeshObject.hpp:102
void add_cell(MeshObject< space_dim, space_dim > *cell)
Add a cell to the MeshObject.
Definition: MeshObject.hpp:364
void construct_face_orientations()
Set the directions of the face normals of a cell.
Definition: MeshObject.hpp:399
int index_vertex(const MeshObject< space_dim, 0 > *vertex) const
Returns the local index of a vertex.
Definition: MeshObject.hpp:493
const int sgn(T val)
Definition: math.hpp:41
const size_t factorial(size_t n)
Definition: math.hpp:11
Definition: MeshND.hpp:13
Eigen::Matrix< double, space_dim, 1 > VectorRd
Definition: MeshObject.hpp:17
Eigen::Matrix< int, space_dim, 1 > VectorZd
Definition: MeshObject.hpp:20
std::vector< Simplex< space_dim, object_dim > > Simplices
Definition: MeshObject.hpp:26
std::array< VectorRd< space_dim >, object_dim+1 > Simplex
Definition: MeshObject.hpp:23