Manicore
Library to implement schemes on n-dimensionnal manifolds.
dcell.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 DCELL_HPP_INCLUDED
19 #define DCELL_HPP_INCLUDED
20 
21 #include "exterior_algebra.hpp"
22 #include "geometry.hpp"
23 
24 #include <vector>
25 #include <set>
26 #include <memory>
27 
32 namespace Manicore {
35 
37 
40  template<size_t dimension>
41  class dCell_graph {
42  public:
44  typedef std::array<std::vector<dCell_graph>,dimension+1> Collection;
45 
47  dCell_graph(size_t id ,
48  std::vector<size_t> const & map_ids );
50 
51  dCell_graph(Collection const & ,
52  size_t d ,
53  size_t id ,
54  std::vector<size_t> const & map_ids ,
55  std::vector<size_t> const & bd );
56 
58  size_t get_id() const {return _bd_ids[_d][0];}
60  std::vector<size_t> const & get_map_ids() const {return _map_ids;}
62  std::vector<size_t> const & get_boundary(size_t dim ) const {return _bd_ids[dim];}
64  std::vector<size_t> const & get_relative_map(size_t dim ) const {return _bd_rel_maps[dim];}
66  size_t global_to_local(size_t d_boundary ,size_t i_b ) const;
67  private:
68  size_t _d;
69  std::vector<size_t> _map_ids;
70  std::array<std::vector<size_t>,dimension+1> _bd_ids;
71  std::array<std::vector<size_t>,dimension> _bd_rel_maps; // relative ids of the corresponding map in the boundary
72  size_t _find_map(size_t id) const;
73  };
74 
76 
82  template<size_t dimension,size_t d>
83  class dCell_map {
84  public:
86  static constexpr size_t cell_dim = d;
87 
89 
93  dCell_map(Eigen::Vector<double,dimension> const &center_mass ,
94  Eigen::Matrix<double,dimension,d> const &flat_map ,
95  double diam ,
96  std::vector<Simplex<d>> const &triangulation );
98  dCell_map(std::vector<std::unique_ptr<ParametrizedMap<dimension,d>>> & maps,
99  std::vector<std::unique_ptr<ParametrizedDerivedMap<dimension,d>>> & pullback_maps ,
100  std::vector<Simplex<d>> const &triangulation );
101 
103 
105  bool is_flat() const {return _is_flat;}
106  // Geometry
108  std::vector<Simplex<d>> const & get_reference_elem() const {return _triangulation;}
109 
111  Eigen::Vector<double,dimension> evaluate_I(size_t rel_map_id ,
112  Eigen::Vector<double,d> const &x ) const;
113 
115  Eigen::Vector<double,d> evaluate_J(size_t rel_map_id ,
116  Eigen::Vector<double,dimension> const &x ) const;
117  // Metric
119  double evaluate_poly_on_ref(Eigen::Vector<double,d> const &x ,
120  size_t i_pbasis ,
121  int r ) const;
122 
124  double evaluate_poly_pullback(size_t rel_map_id ,
125  Eigen::Vector<double,dimension> const &x ,
126  size_t i_pbasis ,
127  int r ) const;
128 
130  Eigen::Matrix<double,dimension,d> evaluate_DI(size_t rel_map_id ,
131  Eigen::Vector<double,d> const &x ) const;
132 
134  Eigen::Matrix<double,d,dimension> evaluate_DJ(size_t rel_map_id ,
135  Eigen::Vector<double,dimension> const &x ) const;
136 
138 
139  template<size_t l> Eigen::Matrix<double,Dimension::ExtDim(l,d),Dimension::ExtDim(l,dimension)>
140  evaluate_DI_p(size_t rel_map_id ,
141  Eigen::Vector<double,d> const &x ) const; // Return the pullback by I of the basis of l-forms
142 
144 
145  template<size_t l> Eigen::Matrix<double,Dimension::ExtDim(l,dimension),Dimension::ExtDim(l,d)>
146  evaluate_DJ_p(size_t rel_map_id ,
147  Eigen::Vector<double,dimension> const &x ) const; // Return the pullback by J of the basis of l-forms
148 
149  // Orientation
151 
156  int get_orientation(size_t rel_map_id ,
157  Eigen::Vector<double,dimension> const &x ,
158  Eigen::Matrix<double,dimension,d-1> const &pM
159  ) const requires(d>1);
160 
161  private:
162  Eigen::Vector<double,dimension> _center_mass; // Used when _is_flat is true
163  Eigen::Matrix<double,dimension,d> _flat_map; // Used when _is_flat is true and d<dimension
164  double _diam; // Used when _is_flat is true
165  std::vector<std::unique_ptr<ParametrizedMap<dimension,d>>> _maps; // Used when _is_flat is false
166  std::vector<std::unique_ptr<ParametrizedDerivedMap<dimension,d>>> _pullback_maps; // Used when _is_flat is false
167  const bool _is_flat; // Element and all its boundaries are flat, it must also correspond to a single map for d>0
168 
169  std::vector<Simplex<d>> _triangulation; // Used to compute integrals
170  };
171 
173 
174  template<size_t dimension>
175  class dCell_map<dimension,0> { // Specialize for vertices
176  public:
177  dCell_map(std::vector<Eigen::Vector<double,dimension>> const &coords ) : _locs(coords) {};
178 
180  Eigen::Vector<double,dimension> const & coord(size_t map_rel_id ) const {return _locs[map_rel_id];}
181 
182  private:
183  std::vector<Eigen::Vector<double,dimension>> _locs;
184  };
186 
187  // ---------------------------------------------------------------------------------------------------------
188  // Implementation
189  // ---------------------------------------------------------------------------------------------------------
190  // ---------------------------------------------------------------------------------------------------------
191  // Graph
192 
193  template<size_t dimension>
194  dCell_graph<dimension>::dCell_graph(size_t id, std::vector<size_t> const & map_ids)
195  : _d(0), _map_ids(map_ids) {
196  _bd_ids[_d] = std::vector<size_t>{id};
197  }
198 
199  template<size_t dimension>
200  dCell_graph<dimension>::dCell_graph(Collection const &coll,size_t d, size_t id, std::vector<size_t> const & map_ids, std::vector<size_t> const & bd)
201  : _d(d), _map_ids(map_ids) {
202  assert(d > 0);
203  // Insert map of faces
204  _bd_ids[d] = std::vector<size_t>{id};
205  _bd_ids[d-1] = bd;
206  for (size_t i = 0; i < bd.size(); ++i) {
207  _bd_rel_maps[d-1].push_back(coll[d-1][bd[i]]._find_map(_map_ids[0]));
208  }
209  // Iterate lower dimensions
210  for (size_t dim = d-1; dim > 0; --dim) {
211  std::set<size_t> clist;
212  for (size_t i = 0; i < _bd_ids[dim].size(); ++i) {
213  std::vector<size_t> const & cb = coll[dim][_bd_ids[dim][i]].get_boundary(dim-1);
214  for (size_t j = 0; j < cb.size(); ++j) {
215  clist.insert(cb[j]);
216  }
217  }
218  for (auto const &p : clist) {
219  _bd_ids[dim-1].push_back(p);
220  _bd_rel_maps[dim-1].push_back(coll[dim-1][p]._find_map(_map_ids[0]));
221  }
222  }
223  }
224 
225  // This is relative to the principal map of the object (to _map_ids[0])
226  template<size_t dimension>
227  size_t dCell_graph<dimension>::_find_map(size_t id) const {
228  for (size_t i = 0; i < _map_ids.size(); ++i) {
229  if (_map_ids[i] == id) return i;
230  }
231  return _map_ids.size();
232  }
233 
234  template<size_t dimension>
235  size_t dCell_graph<dimension>::global_to_local(size_t d_boundary,size_t i_b) const
236  {
237  for (size_t i = 0; i < _bd_ids[d_boundary].size(); ++ i) {
238  if (_bd_ids[d_boundary][i] == i_b) return i;
239  }
240  assert(false);
241  return _bd_ids[d_boundary].size();
242  }
243 
244  // ---------------------------------------------------------------------------------------------------------
245  // Map
246 
247  template<size_t dimension,size_t d>
248  dCell_map<dimension,d>::dCell_map(Eigen::Vector<double,dimension> const &center_mass,
249  Eigen::Matrix<double,dimension,d> const &flat_map,
250  double diam, std::vector<Simplex<d>> const &triangulation)
251  : _center_mass(center_mass), _flat_map(flat_map), _diam(diam), _is_flat(true), _triangulation(triangulation)
252  {}
253 
254  template<size_t dimension,size_t d>
256  std::vector<std::unique_ptr<ParametrizedDerivedMap<dimension,d>>> & pullback_maps,
257  std::vector<Simplex<d>> const &triangulation)
258  : _maps(std::move(maps)), _pullback_maps(std::move(pullback_maps)), _is_flat(false), _triangulation(triangulation)
259  {}
260 
261  template<size_t dimension,size_t d>
262  Eigen::Vector<double,dimension> dCell_map<dimension,d>::evaluate_I(size_t rel_map_id, Eigen::Vector<double,d> const &x) const
263  {
264  if (_is_flat) {
265  if constexpr(dimension == d) {
266  return x*_diam + _center_mass;
267  } else {
268  return _flat_map*x*_diam + _center_mass;
269  }
270  } else {
271  assert(rel_map_id < _maps.size());
272  return _maps[rel_map_id]->I(x);
273  }
274  }
275 
276  template<size_t dimension,size_t d>
277  Eigen::Vector<double,d> dCell_map<dimension,d>::evaluate_J(size_t rel_map_id, Eigen::Vector<double,dimension> const &x) const
278  {
279  if (_is_flat) {
280  if constexpr(dimension == d) {
281  return (x - _center_mass)/_diam;
282  } else {
283  return _flat_map.transpose()*(x - _center_mass)/_diam;
284  }
285  } else {
286  assert(rel_map_id < _maps.size());
287  return _maps[rel_map_id]->J(x);
288  }
289  }
290 
292  // Evaluations
293  template<size_t dimension,size_t d>
294  double dCell_map<dimension,d>::evaluate_poly_on_ref(Eigen::Vector<double,d> const &x,size_t i_pbasis,int r) const
295  {
296  assert((i_pbasis < Dimension::PolyDim(r,d)) && "Index out of range");
297  auto const & power = Monomial_powers<d>::complete(r)[i_pbasis];
298  double rv = std::pow(x(0),power[0]);
299  for (size_t i = 1; i < d; ++i) {
300  rv *= std::pow(x(i),power[i]);
301  }
302  return rv;
303  }
304 
305  template<size_t dimension,size_t d>
306  double dCell_map<dimension,d>::evaluate_poly_pullback(size_t rel_map_id, Eigen::Vector<double,dimension> const &x,size_t i_pbasis,int r) const
307  {
308  return evaluate_poly_on_ref(evaluate_J(rel_map_id,x),i_pbasis,r);
309  }
310 
311  template<size_t dimension,size_t d>
312  Eigen::Matrix<double,dimension,d> dCell_map<dimension,d>::evaluate_DI(size_t rel_map_id, Eigen::Vector<double,d> const &x) const
313  {
314  if (_is_flat) {
315  if constexpr(dimension == d) {
316  return Eigen::Matrix<double,d,d>::Identity()*_diam;
317  } else {
318  return _flat_map*_diam;
319  }
320  } else {
321  return _pullback_maps[rel_map_id]->DI(x);
322  }
323  }
324 
325  template<size_t dimension,size_t d>
326  Eigen::Matrix<double,d,dimension> dCell_map<dimension,d>::evaluate_DJ(size_t rel_map_id, Eigen::Vector<double,dimension> const &x) const
327  {
328  if (_is_flat) {
329  if constexpr(dimension == d) {
330  return Eigen::Matrix<double,d,d>::Identity()/_diam;
331  } else {
332  return _flat_map/_diam;
333  }
334  } else {
335  return _pullback_maps[rel_map_id]->DJ(x);
336  }
337  }
338 
339  template<size_t dimension,size_t d>
340  template<size_t l>
341  Eigen::Matrix<double,Dimension::ExtDim(l,d),Dimension::ExtDim(l,dimension)> dCell_map<dimension,d>::evaluate_DI_p(size_t rel_map_id, Eigen::Vector<double,d> const &x) const
342  {
343  if (_is_flat) {
344  if constexpr(dimension == d) {
345  return Eigen::Matrix<double,Dimension::ExtDim(l,d),Dimension::ExtDim(l,d)>::Identity()*std::pow(_diam,l);
346  } else {
347  return Compute_pullback<l,d,dimension>::compute(_flat_map*_diam);
348  }
349  } else {
350  return Compute_pullback<l,d,dimension>::compute(_pullback_maps[rel_map_id]->DI(x));
351  }
352  }
353 
354  template<size_t dimension,size_t d>
355  template<size_t l>
356  Eigen::Matrix<double,Dimension::ExtDim(l,dimension),Dimension::ExtDim(l,d)> dCell_map<dimension,d>::evaluate_DJ_p(size_t rel_map_id, Eigen::Vector<double,dimension> const &x) const
357  {
358  if (_is_flat) {
359  if constexpr(dimension == d) {
360  return Eigen::Matrix<double,Dimension::ExtDim(l,d),Dimension::ExtDim(l,d)>::Identity()*std::pow(1/_diam,l);
361  } else {
362  return Compute_pullback<l,dimension,d>::compute(_flat_map.transpose()/_diam);
363  }
364  } else {
365  return Compute_pullback<l,dimension,d>::compute(_pullback_maps[rel_map_id]->DJ(x));
366  }
367  }
368 
369  template<size_t dimension,size_t d>
371  Eigen::Vector<double,dimension> const &x,
372  Eigen::Matrix<double,dimension,d-1> const &pM) const requires(d>1)
373  {
374  auto const Jx = evaluate_J(rel_map_id,x);
375  for (auto const &S : _triangulation) {
376  if (Geometry::inside<d>(Jx,S)) {
377  auto mid = Geometry::middleSimplex<d>(S);
378  auto DI = evaluate_DI(rel_map_id,Jx);
379  Eigen::Matrix<double,dimension,d> cmpM;
380  cmpM.rightCols(d-1) = pM;
381  cmpM.leftCols(1) = DI*(Jx - mid).normalized();
382  double tmp = (evaluate_DJ(rel_map_id,x)*cmpM).determinant();
383  assert(std::abs(tmp) > 1e-10 && "Volume form is 0");
384  return (tmp > 0.)? 1 : -1;
385  }
386  }
387  assert(false && "Point outside of element");
388  return 0.;
389  }
390 
391 } // Namespace
392 
393 #endif
394 
Manage topological relations between cells.
Definition: dcell.hpp:41
size_t get_id() const
Return the global index of the cell.
Definition: dcell.hpp:58
dCell_graph(size_t id, std::vector< size_t > const &map_ids)
Constructor for vertex (0-cell)
Definition: dcell.hpp:194
std::array< std::vector< dCell_graph >, dimension+1 > Collection
Type to store the topological data of every cell.
Definition: dcell.hpp:44
std::vector< size_t > const & get_relative_map(size_t dim) const
Return the index of the parametrization of the cell of dimension dim on the boundary,...
Definition: dcell.hpp:64
std::vector< size_t > const & get_map_ids() const
Return the id of the charts corresponding to its parametrizations.
Definition: dcell.hpp:60
size_t global_to_local(size_t d_boundary, size_t i_b) const
Return the index of the i_b d_boundary-cell relative to this cell.
Definition: dcell.hpp:235
std::vector< size_t > const & get_boundary(size_t dim) const
Return the global index of the cell of dimension dim on its boundary.
Definition: dcell.hpp:62
dCell_map(std::vector< Eigen::Vector< double, dimension >> const &coords)
Definition: dcell.hpp:177
Eigen::Vector< double, dimension > const & coord(size_t map_rel_id) const
Return the location of the vertex in a given chart.
Definition: dcell.hpp:180
Manage the geometry of a cell.
Definition: dcell.hpp:83
Eigen::Matrix< double, Dimension::ExtDim(l, d), Dimension::ExtDim(l, dimension)> evaluate_DI_p(size_t rel_map_id, Eigen::Vector< double, d > const &x) const
Compute the action of the pullback of l-forms by the parametrization.
Definition: dcell.hpp:341
int get_orientation(size_t rel_map_id, Eigen::Vector< double, dimension > const &x, Eigen::Matrix< double, dimension, d-1 > const &pM) const requires(d >1)
Return the relative orientation.
Definition: dcell.hpp:370
static constexpr size_t cell_dim
Dimension of the cell
Definition: dcell.hpp:86
double evaluate_poly_on_ref(Eigen::Vector< double, d > const &x, size_t i_pbasis, int r) const
Evaluate a scalar polynomial on the reference element.
Definition: dcell.hpp:294
Eigen::Matrix< double, d, dimension > evaluate_DJ(size_t rel_map_id, Eigen::Vector< double, dimension > const &x) const
Evaluate the differential of the inverse mapping.
Definition: dcell.hpp:326
Eigen::Vector< double, d > evaluate_J(size_t rel_map_id, Eigen::Vector< double, dimension > const &x) const
Evaluate the inverse mapping from the chart to the reference element.
Definition: dcell.hpp:277
dCell_map(Eigen::Vector< double, dimension > const &center_mass, Eigen::Matrix< double, dimension, d > const &flat_map, double diam, std::vector< Simplex< d >> const &triangulation)
Flat constructor.
Definition: dcell.hpp:248
Eigen::Matrix< double, Dimension::ExtDim(l, dimension), Dimension::ExtDim(l, d)> evaluate_DJ_p(size_t rel_map_id, Eigen::Vector< double, dimension > const &x) const
Compute the action of the pullback of l-forms by the inverse mapping.
Definition: dcell.hpp:356
std::vector< Simplex< d > > const & get_reference_elem() const
Return the reference element as a collection of simplexes.
Definition: dcell.hpp:108
Eigen::Vector< double, dimension > evaluate_I(size_t rel_map_id, Eigen::Vector< double, d > const &x) const
Evaluate the parametrization from the reference element to a chart.
Definition: dcell.hpp:262
double evaluate_poly_pullback(size_t rel_map_id, Eigen::Vector< double, dimension > const &x, size_t i_pbasis, int r) const
Evaluate the pullback of a scalar polynomial on the chart.
Definition: dcell.hpp:306
bool is_flat() const
Is the cell flat.
Definition: dcell.hpp:105
Eigen::Matrix< double, dimension, d > evaluate_DI(size_t rel_map_id, Eigen::Vector< double, d > const &x) const
Evaluate the differential of the parametrization.
Definition: dcell.hpp:312
dCell_map(std::vector< std::unique_ptr< ParametrizedMap< dimension, d >>> &maps, std::vector< std::unique_ptr< ParametrizedDerivedMap< dimension, d >>> &pullback_maps, std::vector< Simplex< d >> const &triangulation)
General constructor.
Definition: dcell.hpp:255
The methods in this file are meant to compute the action of everything that is independent of the atl...
Helpers to compute geometric quantities.
constexpr size_t ExtDim(size_t l, size_t d)
Dimension of the exterior algebra .
Definition: exterior_dimension.hpp:37
constexpr size_t PolyDim(int r, size_t d)
Dimension of .
Definition: exterior_dimension.hpp:43
requires(d > 0 &&d<=dimension) struct dCell_mass
Compute the mass matrices of a d-cell.
Definition: dcell_integral.hpp:17
Definition: maxwell.hpp:21
std::array< Eigen::Vector< double, d >, d+1 > Simplex
Array of d+1 points of .
Definition: definitions.hpp:16
static Eigen::Matrix< double, Dimension::ExtDim(l, d1), Dimension::ExtDim(l, d2)> compute(Eigen::MatrixBase< Derived > const &A)
Definition: exterior_algebra.hpp:211
static std::vector< std::array< size_t, d > > const & complete(const int r)
Basis of polynomial of at most degree r.
Definition: exterior_algebra.hpp:312
First order differentials of the parametrizations.
Definition: definitions.hpp:38
Used for the parametrization of the mesh elements.
Definition: definitions.hpp:23