Manicore
Library to implement schemes on n-dimensionnal manifolds.
exterior_objects.hpp
Go to the documentation of this file.
1 // Core data structure for spaces and operators on manifolds.
2 //
3 /*
4  * Copyright (c) 2023 Marien Hanot <marien-lorenzo.hanot@umontpellier.fr>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef EXTERIOR_OBJECT_HPP
21 #define EXTERIOR_OBJECT_HPP
22 
23 #include "exterior_algebra.hpp"
24 
25 // Linear algebra utilities
26 #include <unsupported/Eigen/KroneckerProduct> // Used to couple the action on polynomial and on the exterior algebra
27 
28 namespace Manicore {
47  // Exterior algebra
49 
51  template<size_t l, size_t d>
53  public:
54  typedef Eigen::Matrix<double, Dimension::ExtDim(l-1,d), Dimension::ExtDim(l,d)> ExtAlgMatType;
55 
57  static const ExtAlgMatType & get_transform(size_t i) {
58  return _transforms.at(i);
59  }
60 
62  static void init() noexcept {
63  static_assert(0 < l && l <= d,"Error: Tried to generate Koszul basis outside the range [1,d]");
64  if (initialized == 1) return;
65  initialized = 1;
66  ExteriorBasis<l-1,d>::init(); // ensure that the exterior basis is initialized
67  ExteriorBasis<l,d>::init(); // ensure that the exterior basis is initialized
68  for (size_t i = 0; i < d; ++i) {
69  _transforms[i].setZero();
70  }
71  if (l == 1) { // special case, ext_basis = \emptyset
72  for (size_t i = 0; i < d; ++i) {
73  _transforms[i](0,i) = 1;
74  }
75  return;
76  }
77  for (size_t i = 0; i < Dimension::ExtDim(l-1,d); ++i) {
78  int sign = 1;
79  size_t try_pos = 0;
80  const std::array<size_t, l-1> & cbasis = ExteriorBasis<l-1,d>::expand_basis(i);
81  std::array<size_t,l> basis_cp;
82  std::copy(cbasis.cbegin(),cbasis.cend(),basis_cp.begin()+1);
83  // basis_cp contains a copy of cbasis with one more slot
84  for (size_t j = 0; j < d; ++j) {
85  if (try_pos == l-1 || j < cbasis[try_pos]) { // insert here
86  basis_cp[try_pos] = j;
87  _transforms[j](i,ExteriorBasis<l,d>::index_from_tuple(basis_cp)) = sign;
88  } else { // j == cbasis[try_pos]
89  basis_cp[try_pos] = basis_cp[try_pos+1];
90  ++try_pos;
91  sign = -sign;
92  continue;
93  }
94  }
95  }
96  }; // end init()
97 
98  private:
99  static inline int initialized = 0;
100  static inline std::array<ExtAlgMatType,d> _transforms;
101  };
102 
104  template<size_t l, size_t d>
106  public:
107  typedef Eigen::Matrix<double, Dimension::ExtDim(l+1,d), Dimension::ExtDim(l,d)> ExtAlgMatType;
108 
110  static const ExtAlgMatType & get_transform(size_t i) {
111  return _transforms.at(i);
112  }
113 
115  static void init() noexcept {
116  static_assert(l < d,"Error: Tried to generate diff basis outside the range [0,d-1]");
117  if (initialized == 1) return;
118  initialized = 1;
120  for (size_t i = 0; i < d; ++i) {
121  _transforms[i] = Koszul_exterior<l+1,d>::get_transform(i).transpose().eval();
122  }
123  };
124  private:
125  static inline int initialized = 0;
126  static inline std::array<ExtAlgMatType,d> _transforms;
127  };
128 
130  // Polynomial algebra
132 
134  template<size_t d, size_t index>
136  static Eigen::MatrixXd get (const int r) {
137  static_assert(index < d,"Error: Tried to take the koszul operator on a direction outside the dimension");
138  Eigen::MatrixXd M = Eigen::MatrixXd::Zero(Dimension::HDim(r+1,d), Dimension::HDim(r,d));
139  for (size_t i = 0; i < Dimension::HDim(r,d); ++i) {
140  std::array<size_t, d> current = Monomial_powers<d>::homogeneous(r)[i];
141  current.at(index) += 1;
142  size_t val = std::find(Monomial_powers<d>::homogeneous(r+1).cbegin(),
143  Monomial_powers<d>::homogeneous(r+1).cend(),current)
144  - Monomial_powers<d>::homogeneous(r+1).cbegin();
145  M(val,i) = 1.;
146  }
147  return M;
148  }
149  };
150 
152  template<size_t d, size_t index>
154  static Eigen::MatrixXd get (const int r) {
155  static_assert(index < d,"Error: Tried to take the differential operator on a direction outside the dimension");
156  assert(r > 0 && "Error: Cannot generate a matrix for the differential on P_0");
157  Eigen::MatrixXd M = Eigen::MatrixXd::Zero(Dimension::HDim(r-1,d), Dimension::HDim(r,d));
158  for (size_t i = 0; i < Dimension::HDim(r,d); ++i) {
159  std::array<size_t, d> current = Monomial_powers<d>::homogeneous(r)[i];
160  size_t cval = current.at(index);
161  if (cval == 0) continue; // Zero on that col
162  current.at(index) -= 1;
163  size_t val = std::find(Monomial_powers<d>::homogeneous(r-1).cbegin(),
164  Monomial_powers<d>::homogeneous(r-1).cend(),current)
165  - Monomial_powers<d>::homogeneous(r-1).cbegin();
166  M(val,i) = cval;
167  }
168  return M;
169  }
170  };
171 
173  // Coupling polynomial and exterior
175  /* Couple the part on the exterior algebra and the part on polynomials
176  */
177 
180 
182  template<size_t l, size_t d>
183  struct Koszul_full {
185  static Eigen::MatrixXd get (const int r ) {
186  if constexpr (l==0 || l > d) {
187  return Eigen::MatrixXd(0,0);
188  }
189  Eigen::MatrixXd M(Dimension::PLDim(r+1,l-1,d),Dimension::PLDim(r,l,d));
190  M.setZero();
191  if (Dimension::PLDim(r+1,l-1,d) > 0 && Dimension::PLDim(r,l,d) > 0) {
192  Eigen::MatrixXd scalar_part(Dimension::PolyDim(r+1,d),Dimension::PolyDim(r,d));
193  init_loop_for<0>(r,scalar_part,M);
194  }
195  return M;
196  }
197 
198  private:
199  template<size_t i, typename T> static void init_loop_for(int r, T & scalar_part,T & M) {
200  if constexpr(i < d) {
201  scalar_part.setZero();
202  int offset_l = Dimension::HDim(0,d);
203  int offset_c = 0;
204  for (int s = 0; s <= r; ++s) {
205  int inc_l = Dimension::HDim(s+1,d);
206  int inc_c = Dimension::HDim(s,d);
207  scalar_part.block(offset_l,offset_c,inc_l,inc_c) = Koszul_homogeneous_mat<d,i>::get(s);
208  offset_l += inc_l;
209  offset_c += inc_c;
210  }
211  M += Eigen::KroneckerProduct(Koszul_exterior<l,d>::get_transform(i),scalar_part);
212  init_loop_for<i+1>(r,scalar_part,M);
213  }
214  }
215  };
216 
218  template<size_t l, size_t d>
219  struct Diff_full {
221  static Eigen::MatrixXd get (const int r ) {
222  if (l >= d) {
223  return Eigen::MatrixXd(0,0);
224  }
225  Eigen::MatrixXd M(Dimension::PLDim(r-1,l+1,d),Dimension::PLDim(r,l,d));
226  M.setZero();
227  if (Dimension::PLDim(r-1,l+1,d) > 0 || Dimension::PLDim(r,l,d) > 0) {
228  Eigen::MatrixXd scalar_part(Dimension::PolyDim(r-1,d),Dimension::PolyDim(r,d));
229  init_loop_for<0>(r,scalar_part,M);
230  }
231  return M;
232  };
233 
235  static Eigen::MatrixXd get_as_degr (const int r ) {
236  auto inj = Eigen::KroneckerProduct(Eigen::Matrix<double,Dimension::ExtDim(l+1,d),Dimension::ExtDim(l+1,d)>::Identity(),
237  Eigen::MatrixXd::Identity(Dimension::PolyDim(r,d),Dimension::PolyDim(r-1,d)));
238  return inj*get(r);
239  };
240 
241  private:
242  template<size_t i,typename T> static void init_loop_for(int r,T &scalar_part,T &M) {
243  if constexpr (i < d) {
244  scalar_part.setZero();
245  int offset_l = 0;
246  int offset_c = Dimension::HDim(0,d);
247  for (int s = 0; s < r; ++s) {
248  int inc_l = Dimension::HDim(s,d);
249  int inc_c = Dimension::HDim(s+1,d);
250  scalar_part.block(offset_l,offset_c,inc_l,inc_c) = Diff_homogeneous_mat<d,i>::get(s+1);
251  offset_l += inc_l;
252  offset_c += inc_c;
253  }
254  M += Eigen::KroneckerProduct(Diff_exterior<l,d>::get_transform(i),scalar_part);
255  init_loop_for<i+1>(r,scalar_part,M);
256  }
257  }
258  };
259 
261  template<size_t d>
264  static void init(int r )
265  {
266  init_loop_for<0,1>(r+1);
267  }
268 
269  private:
270  template<size_t l,size_t k> static void init_loop_for(int r) {
271  if constexpr(k <= d) {
272  if constexpr(l < k) {
274  init_loop_for<l+1,k>(r);
275  } else {
277  init_loop_for<0,k+1>(r);
278  }
279  }
280  }
281  };
283 
284 } // End namespace
285 
286 #endif
Diff operator on the exterior algebra.
Definition: exterior_objects.hpp:105
Eigen::Matrix< double, Dimension::ExtDim(l+1, d), Dimension::ExtDim(l, d)> ExtAlgMatType
Definition: exterior_objects.hpp:107
static const ExtAlgMatType & get_transform(size_t i)
Return the action of the Diff operator on the i-th basis of the exterior algebra.
Definition: exterior_objects.hpp:110
static void init() noexcept
Initialize the Diff operator.
Definition: exterior_objects.hpp:115
static const size_t index_from_tuple(const std::array< size_t, l > &tuple)
Search the index corresponding to the given tuple. Throw if not found.
Definition: exterior_algebra.hpp:90
static const std::array< size_t, l > & expand_basis(size_t i)
Return the coefficient of the basis at the given index.
Definition: exterior_algebra.hpp:83
static void init() noexcept
Initialize the exterior algebra basis. Must be called at least once before use.
Definition: exterior_algebra.hpp:66
Koszul operator on the exterior algebra.
Definition: exterior_objects.hpp:52
static const ExtAlgMatType & get_transform(size_t i)
Return the action of the Koszul operator on the i-th basis of the exterior algebra.
Definition: exterior_objects.hpp:57
static void init() noexcept
Initialize the Koszul operator.
Definition: exterior_objects.hpp:62
Eigen::Matrix< double, Dimension::ExtDim(l-1, d), Dimension::ExtDim(l, d)> ExtAlgMatType
Definition: exterior_objects.hpp:54
The methods in this file are meant to compute the action of everything that is independent of the atl...
constexpr size_t ExtDim(size_t l, size_t d)
Dimension of the exterior algebra .
Definition: exterior_dimension.hpp:37
constexpr size_t PLDim(int r, size_t l, size_t d)
Dimension of .
Definition: exterior_dimension.hpp:55
constexpr size_t PolyDim(int r, size_t d)
Dimension of .
Definition: exterior_dimension.hpp:43
constexpr size_t HDim(int r, size_t d)
Dimension of homogeneous polynomials .
Definition: exterior_dimension.hpp:49
Definition: maxwell.hpp:23
Differential operator from to .
Definition: exterior_objects.hpp:219
static Eigen::MatrixXd get_as_degr(const int r)
Differential operator from to .
Definition: exterior_objects.hpp:235
static Eigen::MatrixXd get(const int r)
Differential operator from to .
Definition: exterior_objects.hpp:221
Generate the matrices for the Differential operator on homogeneous monomial.
Definition: exterior_objects.hpp:153
static Eigen::MatrixXd get(const int r)
Definition: exterior_objects.hpp:154
Initialize every class related to the polynomial degree r.
Definition: exterior_objects.hpp:262
static void init(int r)
Initialize up to degree r.
Definition: exterior_objects.hpp:264
Koszul operator from to .
Definition: exterior_objects.hpp:183
static Eigen::MatrixXd get(const int r)
Koszul operator from to .
Definition: exterior_objects.hpp:185
Generate the matrices for the Koszul operator on homogeneous monomial.
Definition: exterior_objects.hpp:135
static Eigen::MatrixXd get(const int r)
Definition: exterior_objects.hpp:136
Generate a basis of monomial powers of degree r.
Definition: exterior_algebra.hpp:304
static std::vector< std::array< size_t, d > > const & homogeneous(const int r)
Basis of homogeneous polynomial of degree r.
Definition: exterior_algebra.hpp:306
static void init(const int r)
Initialise the basis for degree up to r. Must be called at least once before use.
Definition: exterior_algebra.hpp:318