Manicore
Library to implement schemes on n-dimensionnal manifolds.
integral.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 INTEGRAL_HPP_INCLUDED
19 #define INTEGRAL_HPP_INCLUDED
20 
21 #include "quadraturerule.hpp"
22 #include "mesh.hpp"
23 
28 namespace Manicore {
29 
36 
37  // TODO add a cache
38  // Ensure that mesh survives this class
40 
46  template<size_t dimension,size_t d> requires(d > 0 && d <= dimension)
47  class Integral {
48  public:
50  Integral(const Mesh<dimension>* mesh ) : _mesh(mesh) {;}
51 
53  QuadratureRule<d> generate_quad(size_t i_cell , int dqr ) const
54  {
55  return generate_quadrature_rule(_mesh->template get_cell_map<d>(i_cell),dqr);
56  }
57 
59 
61  Eigen::MatrixXd evaluate_scalar_quad(size_t i_cell ,
62  int r ,
63  QuadratureRule<d> const & quad ) const;
65 
67  Eigen::MatrixXd evaluate_scalar_quad_tr(size_t i_cell ,
68  size_t bd_rel_index ,
69  int r ,
70  QuadratureRule<d-1> const & quad ) const requires(d > 1);
71 
73 
74  Eigen::VectorXd evaluate_volume_form(size_t i_cell ,QuadratureRule<d> const & quad ) const;
75 
77 
80  template<size_t l>
81  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d),Dimension::ExtDim(l,d)>>
82  evaluate_exterior_quad(size_t i_cell ,
83  QuadratureRule<d> const & quad ) const;
84 
86 
89  template<size_t l>
90  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d-1),Dimension::ExtDim(l,d)>>
91  evaluate_exterior_quad_tr(size_t i_cell ,
92  size_t bd_rel_index ,
93  QuadratureRule<d-1> const & quad ) const requires(d > 1);
94 
96 
100  template<size_t l>
101  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d-1),Dimension::ExtDim(l,d)>>
102  evaluate_exterior_quad_star_tr(size_t i_cell ,
103  size_t bd_rel_index ,
104  QuadratureRule<d-1> const & quad ) const requires(d > 1);
105 
107  const Mesh<dimension>* mesh() const {return _mesh;}
108  private:
109  const Mesh<dimension>* _mesh; // Do not own the mesh
110  };
112 
113  // ---------------------------------------------------------------------------------------------------------
114  // Implementation
115  // ---------------------------------------------------------------------------------------------------------
116  template<size_t dimension,size_t d> requires(d > 0 && d <= dimension)
117  Eigen::MatrixXd Integral<dimension,d>::evaluate_scalar_quad(
118  size_t i_cell, // Object id
119  int r, // Polynomial degree
120  QuadratureRule<d> const & quad) const
121  {
122  auto const & F = _mesh->template get_cell_map<d>(i_cell);
123  const size_t nbp = quad.size();
124  Eigen::MatrixXd rv(nbp,Dimension::PolyDim(r,d));
125 
126  for (size_t iqr = 0; iqr < nbp; ++iqr) {
127  auto const x = quad[iqr].vector;
128  for (size_t i_b = 0; i_b < Dimension::PolyDim(r,d); ++i_b) {
129  rv(iqr,i_b) = F.evaluate_poly_on_ref(x,i_b,r);
130  }
131  }
132  return rv;
133  }
134 
135  template<size_t dimension,size_t d> requires(d > 0 && d <= dimension)
136  Eigen::MatrixXd Integral<dimension,d>::evaluate_scalar_quad_tr(
137  size_t i_cell, // Object id
138  size_t bd_rel_index,
139  int r, // Polynomial degree
140  QuadratureRule<d-1> const & quad) const requires(d > 1)
141  {
142  auto const & T = _mesh->template get_cell_map<d>(i_cell);
143  auto const & F = _mesh->template get_cell_map<d-1>(_mesh->get_boundary(d-1,d,i_cell)[bd_rel_index]);
144  size_t bd_map = _mesh->get_relative_map(d-1,d,i_cell)[bd_rel_index];
145 
146  const size_t nbp = quad.size();
147  Eigen::MatrixXd rv(nbp,Dimension::PolyDim(r,d));
148 
149  for (size_t iqr = 0; iqr < nbp; ++iqr) {
150  auto const Ix = F.evaluate_I(bd_map,quad[iqr].vector);
151  for (size_t i_b = 0; i_b < Dimension::PolyDim(r,d); ++i_b) {
152  rv(iqr,i_b) = T.evaluate_poly_pullback(0,Ix,i_b,r);
153  }
154  }
155  return rv;
156  }
157 
158 
159  template<size_t dimension,size_t d> requires(d > 0 && d <= dimension)
160  Eigen::VectorXd Integral<dimension,d>::evaluate_volume_form(size_t i_cell,QuadratureRule<d> const & quad) const
161  {
162  auto const & F = _mesh->template get_cell_map<d>(i_cell);
163  const size_t nbp = quad.size();
164  Eigen::VectorXd rv(nbp);
165 
166  for (size_t iqr = 0; iqr < nbp; ++iqr) {
167  auto const x = quad[iqr].vector;
168  auto const DI = F.evaluate_DI(0,x);
169  if constexpr(d == dimension) {
170  rv(iqr) = _mesh->volume_form(_mesh->get_map_ids(d,i_cell)[0],F.evaluate_I(0,x))*DI.determinant();
171  } else {
172  rv(iqr) = std::sqrt((DI.transpose()*_mesh->metric(_mesh->get_map_ids(d,i_cell)[0],F.evaluate_I(0,x))*DI).determinant());
173  }
174  }
175  return rv;
176  }
177 
178  template<size_t dimension,size_t d> requires(d > 0 && d <= dimension)
179  template<size_t l>
180  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d),Dimension::ExtDim(l,d)>> Integral<dimension,d>::evaluate_exterior_quad(size_t i_cell,QuadratureRule<d> const & quad) const
181  {
182  auto const & F = _mesh->template get_cell_map<d>(i_cell);
183  const size_t nbp = quad.size();
184  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d),Dimension::ExtDim(l,d)>> rv;
185  rv.reserve(nbp);
186 
187  for (size_t iqr = 0; iqr < nbp; ++iqr) {
188  auto const x = quad[iqr].vector;
189  auto const Ix = F.evaluate_I(0,x);
190 
191  if constexpr(dimension == d) { // TODO Check if this is actually faster
192  auto const Jp = F.template evaluate_DJ_p<l>(0,Ix);
193  rv.emplace_back(Jp.transpose()*Compute_ExtGram<l>::compute(_mesh->metric_inv(_mesh->get_map_ids(d,i_cell)[0],Ix))*Jp);
194  } else { // Compute the pullback of the metric, and then inverse it. Can we avoid this computation?
195  auto const DI = F.evaluate_DI(0,x);
196  Eigen::Matrix<double,d,d> invIpG = (DI.transpose()*_mesh->metric(_mesh->get_map_ids(d,i_cell)[0],Ix)*DI).inverse();
197  rv.emplace_back(Compute_ExtGram<l>::compute(invIpG));
198  }
199  }
200 
201  return rv;
202  }
203 
204  template<size_t dimension,size_t d> requires(d > 0 && d <= dimension)
205  template<size_t l>
206  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d-1),Dimension::ExtDim(l,d)>> Integral<dimension,d>::evaluate_exterior_quad_tr(size_t i_cell,size_t bd_rel_index, QuadratureRule<d-1> const & quad) const requires(d > 1)
207  {
208  auto const & T = _mesh->template get_cell_map<d>(i_cell);
209  auto const & F = _mesh->template get_cell_map<d-1>(_mesh->get_boundary(d-1,d,i_cell)[bd_rel_index]);
210  size_t bd_map = _mesh->get_relative_map(d-1,d,i_cell)[bd_rel_index];
211 
212  const size_t nbp = quad.size();
213  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d-1),Dimension::ExtDim(l,d)>> rv;
214  rv.reserve(nbp);
215 
216  for (size_t iqr = 0; iqr < nbp; ++iqr) {
217  auto const x = quad[iqr].vector;
218  auto const Ix = F.evaluate_I(bd_map,x);
219  auto const DIF = F.evaluate_DI(bd_map,x);
220  auto const IpF = F.template evaluate_DI_p<l>(bd_map,x);
221  auto const JpT = T.template evaluate_DJ_p<l>(0,Ix);
222  Eigen::Matrix<double,d-1,d-1> invIpG = (DIF.transpose()*_mesh->metric(_mesh->get_map_ids(d,i_cell)[0],Ix)*DIF).inverse();
223  rv.emplace_back(Compute_ExtGram<l>::compute(invIpG)*IpF*JpT);
224  }
225 
226  return rv;
227  }
228 
229  template<size_t dimension,size_t d> requires(d > 0 && d <= dimension)
230  template<size_t l>
231  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d-1),Dimension::ExtDim(l,d)>> Integral<dimension,d>::evaluate_exterior_quad_star_tr(size_t i_cell,size_t bd_rel_index, QuadratureRule<d-1> const & quad) const requires(d > 1)
232  {
233  auto const & T = _mesh->template get_cell_map<d>(i_cell);
234  auto const & F = _mesh->template get_cell_map<d-1>(_mesh->get_boundary(d-1,d,i_cell)[bd_rel_index]);
235  size_t bd_map = _mesh->get_relative_map(d-1,d,i_cell)[bd_rel_index];
236 
237  const size_t nbp = quad.size();
238  std::vector<Eigen::Matrix<double,Dimension::ExtDim(l,d-1),Dimension::ExtDim(l,d)>> rv;
239  rv.reserve(nbp);
240 
241  for (size_t iqr = 0; iqr < nbp; ++iqr) {
242  auto const x = quad[iqr].vector;
243  auto const Ix = F.evaluate_I(bd_map,x);
244  auto const JIx = T.evaluate_J(0,Ix);
245  auto const DIF = F.evaluate_DI(bd_map,x);
246  Eigen::Matrix<double,d-1,d-1> invIpG = (DIF.transpose()*_mesh->metric(_mesh->get_map_ids(d,i_cell)[0],Ix)*DIF).inverse();
247  auto const IpF = F.template evaluate_DI_p<l>(bd_map,x);
248  auto const JpT = T.template evaluate_DJ_p<l>(0,Ix);
249  Eigen::Matrix<double,Dimension::ExtDim(l,d),Dimension::ExtDim(d-l,d)>
250  starR = _mesh->template getHodge<d-l,d>(i_cell,JIx)*(((l*(d-l))%2)? -1. : 1.);
251  Eigen::Matrix<double,Dimension::ExtDim(d-1-l,d-1),Dimension::ExtDim(l,d-1)>
252  starL = _mesh->template getHodge<l,d-1>(_mesh->get_boundary(d-1,d,i_cell)[bd_rel_index],x);
253  rv.emplace_back(Compute_ExtGram<d-1-l>::compute(invIpG)*starL*IpF*JpT*starR);
254  }
255 
256  return rv;
257  }
258 } // end namespace
259 
260 #endif
261 
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
Compute and store the topological and geometrical data of the mesh.
Definition: maxwell.hpp:21
Wrapper to provide an uniform interface to every quadrature rule.
static Eigen::Matrix< double, Dimension::ExtDim(l, Eigen::internal::traits< Derived >::RowsAtCompileTime), Dimension::ExtDim(l, Eigen::internal::traits< Derived >::RowsAtCompileTime)> compute(Eigen::MatrixBase< Derived > const &g)
Definition: exterior_algebra.hpp:287