Manicore
Library to implement schemes on n-dimensionnal manifolds.
mesh.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023 Marien Hanot <marien-lorenzo.hanot@umontpellier.fr>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef MESH_HPP_INCLUDED
19 #define MESH_HPP_INCLUDED
20 
21 #include "dcell.hpp"
22 #include "loader.hpp" // Needed to destruct the loader
23 
24 #include <memory>
25 
33 namespace Manicore {
34 
35  template<size_t> class Mesh_builder;
36 
39 
41 
52  template<size_t dimension>
53  class Mesh
54  {
55  public:
57  size_t n_cells(size_t d ) const {return _cells_graph[d].size();}
58 
59  // Interface to the graph structure
61  std::vector<size_t> const & get_map_ids(size_t d ,
62  size_t i_cell ) const
63  {return _cells_graph[d][i_cell].get_map_ids();}
64 
66  std::vector<size_t> const & get_boundary(size_t d_boundary ,
67  size_t d ,
68  size_t i_cell ) const
69  {return _cells_graph[d][i_cell].get_boundary(d_boundary);}
70 
72 
74  std::vector<size_t> const & get_relative_map(size_t d_boundary ,
75  size_t d ,
76  size_t i_cell ) const
77  {return _cells_graph[d][i_cell].get_relative_map(d_boundary);}
78 
80 
83  size_t global_to_local(size_t d_boundary ,
84  size_t d ,
85  size_t i_b ,
86  size_t i_cell ) const
87  {return _cells_graph[d][i_cell].global_to_local(d_boundary,i_b);}
88 
90 
91  int get_boundary_orientation(size_t d ,
92  size_t i_cell ,
93  size_t j_bd ) const;
94 
96 
98  Eigen::Vector3d get_3D_embedding (size_t m_id ,
99  Eigen::Vector<double,dimension> const &x ) const
100  {return _maps[m_id]->I(x);}
102 
108  Eigen::Matrix<double,3,dimension> get_3D_pushforward (size_t m_id ,
109  Eigen::Vector<double,dimension> const &x ) const
110  {return _maps_pullback[m_id]->DI(x);}
111 
112  // Access to the geometric structure
114 
115  template<size_t d> dCell_map<dimension,d> const & get_cell_map(size_t i) const;
116 
117  // Access to the metric structure
119  Eigen::Matrix<double,dimension,dimension> metric (size_t m_id ,
120  Eigen::Vector<double,dimension> const &x ) const
121  {return _metric_maps[m_id]->metric(x);} // On the tangent space
122 
124  Eigen::Matrix<double,dimension,dimension> metric_inv (size_t m_id ,
125  Eigen::Vector<double,dimension> const &x ) const
126  {return _metric_maps[m_id]->metric_inv(x);} // On the cotangent space
127 
129  double volume_form (size_t m_id ,
130  Eigen::Vector<double,dimension> const &x ) const
131  {return _metric_maps[m_id]->volume(x);}
132 
134  int orientationTopCell(size_t i_cell) const
135  {
136  return _metric_maps[get_map_ids(dimension,i_cell)[0]]->orientation;
137  }
138 
140 
144  template<size_t k,int d> Eigen::Matrix<double,Dimension::ExtDim(d-k,d),Dimension::ExtDim(k,d)>
145  getHodge(size_t i_cell ,
146  Eigen::Vector<double,d> const &x ) const; // Compute the Hodge star operator on the i_cell-th d-cell at x
147 
148  private:
149  static constexpr size_t _max_dim = 3;
150  Mesh() requires(dimension <= _max_dim) {;}
151  friend class Mesh_builder<dimension>;
152  typename dCell_graph<dimension>::Collection _cells_graph;
153  std::unique_ptr<Maps_loader<dimension>> _loader_ref; // Tie the life of the shared library to the mesh (must be destroyed AFTER every pointer to any mapping
154  std::vector<std::unique_ptr<ParametrizedMap<3,dimension>>> _maps;
155  std::vector<std::unique_ptr<ParametrizedDerivedMap<3,dimension>>> _maps_pullback;
156  std::vector<std::unique_ptr<ParametrizedMetricMap<dimension>>> _metric_maps;
157  // TODO use the generic solution of the class PEC
158  std::vector<dCell_map<dimension,0>> _geo0;
159  std::vector<dCell_map<dimension,1>> _geo1;
160  std::vector<dCell_map<dimension,2>> _geo2;
161  std::vector<dCell_map<dimension,3>> _geo3;
162  };
164 
165  // ---------------------------------------------------------------------------------------------------------
166  // Implementation
167  // ---------------------------------------------------------------------------------------------------------
168  template<size_t dimension>
169  int Mesh<dimension>::get_boundary_orientation(size_t d, size_t i_cell, size_t j_bd) const
170  {
171  size_t i_bd_abs = get_boundary(d-1,d,i_cell)[j_bd];
172  size_t bd_rel_map = get_relative_map(d-1,d,i_cell)[j_bd];
173  auto get_orientation = [&]<size_t _d>(auto&& get_orientation)
174  {
175  if constexpr(_d == dimension+1) {
176  assert(false && "Dimension too high or low");
177  return 0;
178  } else {
179  if (_d == d) {
180  auto const & E = get_cell_map<_d-1>(i_bd_abs);
181  auto x = Geometry::middleSimplex<_d-1>(E.get_reference_elem()[0]);
182  auto pM = E.evaluate_DI(bd_rel_map,x);
183  if (d == dimension) {
184  return get_cell_map<_d>(i_cell).get_orientation(0,E.evaluate_I(bd_rel_map,x),pM)*orientationTopCell(i_cell);
185  } else {
186  return get_cell_map<_d>(i_cell).get_orientation(0,E.evaluate_I(bd_rel_map,x),pM);
187  }
188  } else {
189  return get_orientation.template operator()<_d+1>(get_orientation);
190  }
191  }
192  };
193  return get_orientation.template operator()<2>(get_orientation); // Start at dim(T) = 2, since the boundary must be at least of dimension 1
194  }
195 
196  // Doxygen wrongly assumes this is an overload, prevent it from duplicating the entry
198  template<size_t dimension>
199  template<size_t d>
201  {
202  static_assert(d <= _max_dim);
203  if constexpr (d == 0) return _geo0[i];
204  else if constexpr (d == 1) return _geo1[i];
205  else if constexpr (d == 2) return _geo2[i];
206  else return _geo3[i];
207  }
209 
210  template<size_t dimension>
211  template<size_t k,int d> Eigen::Matrix<double,Dimension::ExtDim(d-k,d),Dimension::ExtDim(k,d)>
212  Mesh<dimension>::getHodge(size_t i_cell, Eigen::Vector<double,d> const &x) const
213  {
214  auto const & F = get_cell_map<d>(i_cell);
215  auto const Ix = F.evaluate_I(0,x);
216  Eigen::Matrix<double,d,d> invGF;
217  double sqrtdetG;
218  if constexpr(d == dimension) { // TODO check if this is actually faster
219  auto const DJ = F.evaluate_DJ(0,Ix);
220  invGF = DJ*metric_inv(get_map_ids(d,i_cell)[0],Ix)*DJ.transpose();
221  sqrtdetG = volume_form(get_map_ids(d,i_cell)[0],Ix) * std::abs(F.evaluate_DI(0,x).determinant())*orientationTopCell(i_cell);
222  } else {
223  auto const DI = F.evaluate_DI(0,x);
224  Eigen::Matrix<double,d,d> pullbackMetric = DI.transpose()*metric(get_map_ids(d,i_cell)[0],Ix)*DI;
225  invGF = (pullbackMetric).inverse();
226  sqrtdetG = std::sqrt(pullbackMetric.determinant());
227  }
228  auto const partialDet = Compute_pullback<k,d,d>::compute(invGF);
229  auto const &complBasis = ComplBasis<k,d>::compute();
230  return sqrtdetG*complBasis*partialDet;
231  // ComplBasis does not duplicate indices, hence there is no 1/(d-k)! term
232  }
233 
234 } // Namespace
235 
236 #endif
237 
static Eigen::Matrix< double, Dimension::ExtDim(d-l, d), Dimension::ExtDim(l, d)> const & compute()
Definition: exterior_algebra.hpp:126
Main data structure for the mesh.
Definition: mesh.hpp:54
int orientationTopCell(size_t i_cell) const
Return the relative orientation of a top dimensional cell with respect to the manifold.
Definition: mesh.hpp:134
std::vector< size_t > const & get_boundary(size_t d_boundary, size_t d, size_t i_cell) const
Return a list filled with the global index of the elements on the boundary of the given dimension.
Definition: mesh.hpp:66
std::vector< size_t > const & get_map_ids(size_t d, size_t i_cell) const
Return the map_ids of the i_cell-th d-cell.
Definition: mesh.hpp:61
double volume_form(size_t m_id, Eigen::Vector< double, dimension > const &x) const
Evaluate the scaling factor of the volume form.
Definition: mesh.hpp:129
Eigen::Matrix< double, dimension, dimension > metric(size_t m_id, Eigen::Vector< double, dimension > const &x) const
Evaluate the metric (of the tangent space)
Definition: mesh.hpp:119
dCell_map< dimension, d > const & get_cell_map(size_t i) const
Return the i-th dCell_map.
Eigen::Matrix< double, dimension, dimension > metric_inv(size_t m_id, Eigen::Vector< double, dimension > const &x) const
Evaluate the metric (of the cotangent space)
Definition: mesh.hpp:124
int get_boundary_orientation(size_t d, size_t i_cell, size_t j_bd) const
Return the relative orientation of the j-th (d-1)-boundary of the i-th d-cell.
Definition: mesh.hpp:169
Eigen::Matrix< double, Dimension::ExtDim(d-k, d), Dimension::ExtDim(k, d)> getHodge(size_t i_cell, Eigen::Vector< double, d > const &x) const
Evaluate the hodge star operator.
Definition: mesh.hpp:212
std::vector< size_t > const & get_relative_map(size_t d_boundary, size_t d, size_t i_cell) const
The index for the mapping (of index 0) used on the element among the mappings of the boundary.
Definition: mesh.hpp:74
size_t global_to_local(size_t d_boundary, size_t d, size_t i_b, size_t i_cell) const
Return the local index of the i_b d_boundary-cell with respect to the icell-th d-cell.
Definition: mesh.hpp:83
size_t n_cells(size_t d) const
Return the number of cell of a given dimension.
Definition: mesh.hpp:57
Eigen::Matrix< double, 3, dimension > get_3D_pushforward(size_t m_id, Eigen::Vector< double, dimension > const &x) const
Interface to the extrinsic mapping.
Definition: mesh.hpp:108
Eigen::Vector3d get_3D_embedding(size_t m_id, Eigen::Vector< double, dimension > const &x) const
Interface to the extrinsic mapping.
Definition: mesh.hpp:98
std::array< std::vector< dCell_graph >, dimension+1 > Collection
Type to store the topological data of every cell.
Definition: dcell.hpp:44
Manage the geometry of a cell.
Definition: dcell.hpp:83
Store the geometrical description of each cell and their topological relations.
constexpr size_t ExtDim(size_t l, size_t d)
Dimension of the exterior algebra .
Definition: exterior_dimension.hpp:37
requires(d > 0 &&d<=dimension) struct dCell_mass
Compute the mass matrices of a d-cell.
Definition: dcell_integral.hpp:17
Load the mesh description given as a shared library for use in Manicore.
Eigen::Vector< double, d > middleSimplex(Simplex< d > const &S)
Compute the centroid of a simplex S.
Definition: geometry.hpp:77
Definition: maxwell.hpp:21
static Eigen::Matrix< double, Dimension::ExtDim(l, d1), Dimension::ExtDim(l, d2)> compute(Eigen::MatrixBase< Derived > const &A)
Definition: exterior_algebra.hpp:211