HArD::Core3D
Hybrid Arbitrary Degree::Core 3D - Library to implement 3D schemes with vertex, edge, face and cell polynomials as unknowns
basis.hpp
Go to the documentation of this file.
1 // Core data structures and methods required to implement the discrete de Rham sequence in 3D
2 //
3 // Provides:
4 // - Full and partial polynomial spaces on the element, faces, and edges
5 // - Generic routines to create quadrature nodes over cells and faces of the mesh
6 //
7 // Authors: Daniele Di Pietro (daniele.di-pietro@umontpellier.fr)
8 // Jerome Droniou (jerome.droniou@monash.edu)
9 
10 /*
11  *
12  * This library was developed around HHO methods, although some parts of it have a more
13  * general purpose. If you use this code or part of it in a scientific publication,
14  * please mention the following book as a reference for the underlying principles
15  * of HHO schemes:
16  *
17  * The Hybrid High-Order Method for Polytopal Meshes: Design, Analysis, and Applications.
18  * D. A. Di Pietro and J. Droniou. Modeling, Simulation and Applications, vol. 19.
19  * Springer International Publishing, 2020, xxxi + 525p. doi: 10.1007/978-3-030-37203-3.
20  * url: https://hal.archives-ouvertes.fr/hal-02151813.
21  *
22  */
23 
24 #ifndef BASIS_HPP
25 #define BASIS_HPP
26 
27 #include <boost/multi_array.hpp>
28 
29 #include <mesh.hpp>
30 #include <iostream>
31 
33 
34 #include <quadraturerule.hpp>
35 
36 namespace HArDCore3D
37 {
38 
50  constexpr int dimspace = 3;
51  typedef Eigen::Matrix3d MatrixRd;
52 
53  template <typename T>
54  using FType = std::function<T(const VectorRd&)>;
55 
56  template <typename T>
57  using CellFType = std::function<T(const VectorRd&, const Cell *)>;
58 
59  template <typename T>
60  using BasisQuad = boost::multi_array<T, 2>;
61 
63  {
64  Scalar = 0,
65  Vector = 1,
66  Matrix = 2
67  };
68 
69  //-----------------------------------------------------------------------------
70  // Powers of monomial basis
71  //-----------------------------------------------------------------------------
72 
74  template<typename GeometricSupport>
76  {
77  // Only specializations are relevant
78  };
79 
80  template<>
82  {
83  // Powers of homogeneous polynomials of degree L
84  static std::vector<VectorZd> homogeneous(const size_t L)
85  {
86  std::vector<VectorZd> powers;
88  for (size_t i = 0; i <= L; i++)
89  {
90  for (size_t j = 0; i + j <= L; j++)
91  {
92  powers.push_back(VectorZd(i, j, L - i - j));
93  } // for j
94  } // for i
95  return powers;
96  }
97 
98  // Powers for degrees from 0 to degree
99  static std::vector<VectorZd> complete(const size_t degree)
100  {
101  std::vector<VectorZd> powers;
102  powers.reserve( PolynomialSpaceDimension<Cell>::Poly(degree) );
103  for (size_t l = 0; l <= degree; l++)
104  {
105  std::vector<VectorZd> pow_hom = homogeneous(l);
106  for (VectorZd p : pow_hom){
107  powers.push_back(p);
108  }
109  } // for l
110  return powers;
111  }
112  };
113 
114  template<>
116  {
117  // Powers of homogeneous polynomials of degree L
118  static std::vector<Eigen::Vector2i> homogeneous(const size_t L)
119  {
120  std::vector<Eigen::Vector2i> powers;
122  for (size_t i = 0; i <= L; i++)
123  {
124  powers.push_back(Eigen::Vector2i(i, L - i));
125  } // for i
126  return powers;
127  }
128 
129  // Powers for degrees from 0 to degree
130  static std::vector<Eigen::Vector2i> complete(size_t degree)
131  {
132  std::vector<Eigen::Vector2i> powers;
133  powers.reserve( PolynomialSpaceDimension<Face>::Poly(degree) );
134  for (size_t l = 0; l <= degree; l++)
135  {
136  std::vector<Eigen::Vector2i> pow_hom = homogeneous(l);
137  for (Eigen::Vector2i p : pow_hom){
138  powers.push_back(p);
139  }
140  } // for l
141 
142  return powers;
143  }
144  };
145 
146  //----------------------------------------------------------------------
147  //----------------------------------------------------------------------
148  // SCALAR MONOMIAL BASIS
149  //----------------------------------------------------------------------
150  //----------------------------------------------------------------------
151 
154  {
155  public:
156  typedef double FunctionValue;
159  typedef double DivergenceValue;
161 
163 
164  constexpr static const TensorRankE tensorRank = Scalar;
165  constexpr static const bool hasAncestor = false;
166  static const bool hasFunction = true;
167  static const bool hasGradient = true;
168  static const bool hasCurl = false;
169  static const bool hasDivergence = false;
170  static const bool hasHessian = true;
171  static const bool hasCurlCurl = false;
172 
175  const Cell &T,
176  size_t degree
177  );
178 
180  inline size_t dimension() const
181  {
182  return (m_degree >= 0 ? (m_degree * (m_degree + 1) * (2 * m_degree + 1) + 9 * m_degree * (m_degree + 1) + 12 * (m_degree + 1)) / 12 : 0);
183  }
184 
186  FunctionValue function(size_t i, const VectorRd &x) const;
187 
189  GradientValue gradient(size_t i, const VectorRd &x) const;
190 
192  HessianValue hessian(size_t i, const VectorRd &x) const;
193 
195  inline size_t max_degree() const
196  {
197  return m_degree;
198  }
199 
201  inline VectorZd powers(size_t i) const
202  {
203  return m_powers[i];
204  }
205 
206  private:
208  inline VectorRd _coordinate_transform(const VectorRd &x) const
209  {
210  return (x - m_xT) / m_hT;
211  }
212 
213  Cell m_T;
214  size_t m_degree;
215  VectorRd m_xT;
216  double m_hT;
217  std::vector<VectorZd> m_powers;
218  };
219 
220 
221  //------------------------------------------------------------------------------
222 
225  {
226  public:
227  typedef double FunctionValue;
230  typedef double DivergenceValue;
232 
234 
235  typedef Eigen::Matrix<double, 2, dimspace> JacobianType;
236 
237  constexpr static const TensorRankE tensorRank = Scalar;
238  constexpr static const bool hasAncestor = false;
239  static const bool hasFunction = true;
240  static const bool hasGradient = true;
241  static const bool hasCurl = true;
242  static const bool hasDivergence = false;
243  static const bool hasHessian = true;
244  static const bool hasCurlCurl = false;
245 
248  const Face &F,
249  size_t degree
250  );
251 
253  inline size_t dimension() const
254  {
255  return (m_degree + 1) * (m_degree + 2) / 2;
256  }
257 
259  FunctionValue function(size_t i, const VectorRd &x) const;
260 
262  GradientValue gradient(size_t i, const VectorRd &x) const;
263 
265  CurlValue curl(size_t i, const VectorRd &x) const;
266 
268  HessianValue hessian(size_t i, const VectorRd &x) const;
269 
271  inline size_t max_degree() const
272  {
273  return m_degree;
274  }
275 
277  inline const VectorRd &normal() const
278  {
279  return m_nF;
280  }
281 
283  inline const JacobianType &jacobian() const
284  {
285  return m_jacobian;
286  }
287 
289  inline const JacobianType coordinates_system() const
290  {
291  return m_jacobian * m_hF;
292  }
293 
295  inline Eigen::Vector2i powers(size_t i) const
296  {
297  return m_powers[i];
298  }
299 
300  private:
302  inline Eigen::Vector2d _coordinate_transform(const VectorRd &x) const
303  {
304  return m_jacobian * (x - m_xF);
305  }
306 
307  size_t m_degree;
308  VectorRd m_xF;
309  double m_hF;
310  VectorRd m_nF;
311  JacobianType m_jacobian;
312  std::vector<Eigen::Vector2i> m_powers;
313  };
314 
315  //------------------------------------------------------------------------------
316 
319  {
320  public:
321  typedef double FunctionValue;
324  typedef double DivergenceValue;
325  typedef double HessianValue;
326 
328 
329  constexpr static const TensorRankE tensorRank = Scalar;
330  constexpr static const bool hasAncestor = false;
331  static const bool hasFunction = true;
332  static const bool hasGradient = true;
333  static const bool hasCurl = false;
334  static const bool hasDivergence = false;
335  static const bool hasHessian = false;
336  static const bool hasCurlCurl = false;
337 
340  const Edge &E,
341  size_t degree
342  );
343 
345  inline size_t dimension() const
346  {
347  return m_degree + 1;
348  }
349 
351  FunctionValue function(size_t i, const VectorRd &x) const;
352 
354  GradientValue gradient(size_t i, const VectorRd &x) const;
355 
357  inline size_t max_degree() const
358  {
359  return m_degree;
360  }
361 
362  private:
363  inline double _coordinate_transform(const VectorRd &x) const
364  {
365  return (x - m_xE).dot(m_tE) / m_hE;
366  }
367 
368  size_t m_degree;
369  VectorRd m_xE;
370  double m_hE;
371  VectorRd m_tE;
372  };
373 
374  //------------------------------------------------------------------------------
375  //------------------------------------------------------------------------------
376  // DERIVED BASIS
377  //------------------------------------------------------------------------------
378  //------------------------------------------------------------------------------
379 
380  //----------------------------FAMILY------------------------------------------
381  //
383 
386  template <typename BasisType>
387  class Family
388  {
389  public:
390  typedef typename BasisType::FunctionValue FunctionValue;
391  typedef typename BasisType::GradientValue GradientValue;
392  typedef typename BasisType::CurlValue CurlValue;
393  typedef typename BasisType::DivergenceValue DivergenceValue;
394  typedef typename BasisType::HessianValue HessianValue;
395 
396  typedef typename BasisType::GeometricSupport GeometricSupport;
397 
398  constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
399  constexpr static const bool hasAncestor = true;
400  static const bool hasFunction = BasisType::hasFunction;
401  static const bool hasGradient = BasisType::hasGradient;
402  static const bool hasCurl = BasisType::hasCurl;
403  static const bool hasDivergence = BasisType::hasDivergence;
404  static const bool hasHessian = BasisType::hasHessian;
405  static const bool hasCurlCurl = BasisType::hasCurlCurl;
406 
407  typedef BasisType AncestorType;
408 
411  const BasisType &basis,
412  const Eigen::MatrixXd &matrix
413  )
414  : m_basis(basis),
415  m_matrix(matrix)
416  {
417  assert((size_t)matrix.cols() == basis.dimension() || "Inconsistent family initialization");
418  }
419 
421  inline size_t dimension() const
422  {
423  return m_matrix.rows();
424  }
425 
427  FunctionValue function(size_t i, const VectorRd &x) const
428  {
429  static_assert(hasFunction, "Call to function() not available");
430 
431  FunctionValue f = m_matrix(i, 0) * m_basis.function(0, x);
432  for (auto j = 1; j < m_matrix.cols(); j++)
433  {
434  f += m_matrix(i, j) * m_basis.function(j, x);
435  } // for j
436  return f;
437  }
438 
440  FunctionValue function(size_t i, size_t iqn, const boost::multi_array<FunctionValue, 2> &ancestor_value_quad) const
441  {
442  static_assert(hasFunction, "Call to function() not available");
443 
444  FunctionValue f = m_matrix(i, 0) * ancestor_value_quad[0][iqn];
445  for (auto j = 1; j < m_matrix.cols(); j++)
446  {
447  f += m_matrix(i, j) * ancestor_value_quad[j][iqn];
448  } // for j
449  return f;
450  }
451 
452 
454  GradientValue gradient(size_t i, const VectorRd &x) const
455  {
456  static_assert(hasGradient, "Call to gradient() not available");
457 
458  GradientValue G = m_matrix(i, 0) * m_basis.gradient(0, x);
459  for (auto j = 1; j < m_matrix.cols(); j++)
460  {
461  G += m_matrix(i, j) * m_basis.gradient(j, x);
462  } // for j
463  return G;
464  }
465 
467  GradientValue gradient(size_t i, size_t iqn, const boost::multi_array<GradientValue, 2> &ancestor_gradient_quad) const
468  {
469  static_assert(hasGradient, "Call to gradient() not available");
470 
471  GradientValue G = m_matrix(i, 0) * ancestor_gradient_quad[0][iqn];
472  for (auto j = 1; j < m_matrix.cols(); j++)
473  {
474  G += m_matrix(i, j) * ancestor_gradient_quad[j][iqn];
475  } // for j
476  return G;
477  }
478 
480  CurlValue curl(size_t i, const VectorRd &x) const
481  {
482  static_assert(hasCurl, "Call to curl() not available");
483 
484  CurlValue C = m_matrix(i, 0) * m_basis.curl(0, x);
485  for (auto j = 1; j < m_matrix.cols(); j++)
486  {
487  C += m_matrix(i, j) * m_basis.curl(j, x);
488  } // for j
489  return C;
490  }
491 
493  CurlValue curl(size_t i, size_t iqn, const boost::multi_array<CurlValue, 2> &ancestor_curl_quad) const
494  {
495  static_assert(hasCurl, "Call to curl() not available");
496 
497  CurlValue C = m_matrix(i, 0) * ancestor_curl_quad[0][iqn];
498  for (auto j = 1; j < m_matrix.cols(); j++)
499  {
500  C += m_matrix(i, j) * ancestor_curl_quad[j][iqn];
501  } // for j
502  return C;
503  }
504 
506  DivergenceValue divergence(size_t i, const VectorRd &x) const
507  {
508  static_assert(hasDivergence, "Call to divergence() not available");
509 
510  DivergenceValue D = m_matrix(i, 0) * m_basis.divergence(0, x);
511  for (auto j = 1; j < m_matrix.cols(); j++)
512  {
513  D += m_matrix(i, j) * m_basis.divergence(j, x);
514  } // for j
515  return D;
516  }
517 
519  DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<DivergenceValue, 2> &ancestor_divergence_quad) const
520  {
521  static_assert(hasDivergence, "Call to divergence() not available");
522 
523  DivergenceValue D = m_matrix(i, 0) * ancestor_divergence_quad[0][iqn];
524  for (auto j = 1; j < m_matrix.cols(); j++)
525  {
526  D += m_matrix(i, j) * ancestor_divergence_quad[j][iqn];
527  } // for j
528  return D;
529  }
530 
532  HessianValue hessian(size_t i, const VectorRd &x) const
533  {
534  static_assert(hasHessian, "Call to hessian() not available");
535 
536  HessianValue H = m_matrix(i, 0) * m_basis.hessian(0, x);
537  for (auto j = 1; j < m_matrix.cols(); j++)
538  {
539  H += m_matrix(i, j) * m_basis.hessian(j, x);
540  } // for j
541  return H;
542  }
543 
545  HessianValue hessian(size_t i, size_t iqn, const boost::multi_array<HessianValue, 2> &ancestor_hessian_quad) const
546  {
547  static_assert(hasHessian, "Call to hessian() not available");
548 
549  HessianValue H = m_matrix(i, 0) * ancestor_hessian_quad[0][iqn];
550  for (auto j = 1; j < m_matrix.cols(); j++)
551  {
552  H += m_matrix(i, j) * ancestor_hessian_quad[j][iqn];
553  } // for j
554  return H;
555  }
556 
558  inline const Eigen::MatrixXd & matrix() const
559  {
560  return m_matrix;
561  }
562 
564  constexpr inline const BasisType &ancestor() const
565  {
566  return m_basis;
567  }
568 
570  inline size_t max_degree() const
571  {
572  return m_basis.max_degree();
573  }
574 
575  private:
576  BasisType m_basis;
577  Eigen::MatrixXd m_matrix;
578  };
579 
580  //----------------------TENSORIZED--------------------------------------------------------
581 
583 
607  template <typename ScalarFamilyType, size_t N>
609  {
610  public:
611  typedef typename Eigen::Matrix<double, N, 1> FunctionValue;
612  typedef typename Eigen::Matrix<double, N, dimspace> GradientValue;
614  typedef double DivergenceValue;
615  typedef void HessianValue;
616 
617  typedef typename ScalarFamilyType::GeometricSupport GeometricSupport;
618 
619  constexpr static const TensorRankE tensorRank = Vector;
620  constexpr static const bool hasAncestor = true;
621  static const bool hasFunction = ScalarFamilyType::hasFunction;
622  static const bool hasGradient = ScalarFamilyType::hasGradient;
623  // We know how to compute the curl and divergence if gradient is available, and
624  // if we tensorize at the dimension of the space
625  static const bool hasDivergence = (ScalarFamilyType::hasGradient && N == dimspace);
626  static const bool hasCurl = (ScalarFamilyType::hasGradient && N == dimspace);
627  static const bool hasHessian = false;
628  static const bool hasCurlCurl = (ScalarFamilyType::hasHessian && N == dimspace);
629 
630  typedef ScalarFamilyType AncestorType;
631 
632  TensorizedVectorFamily(const ScalarFamilyType &scalar_family)
633  : m_scalar_family(scalar_family)
634  {
635  static_assert(ScalarFamilyType::tensorRank == Scalar,
636  "Vector family can only be constructed from scalar families");
637  }
638 
640  inline size_t dimension() const
641  {
642  return m_scalar_family.dimension() * N;
643  }
644 
646  FunctionValue function(size_t i, const VectorRd &x) const
647  {
648  static_assert(hasFunction, "Call to function() not available");
649 
650  FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
651  ek(i / m_scalar_family.dimension()) = 1.;
652  return ek * m_scalar_family.function(i % m_scalar_family.dimension(), x);
653  }
654 
656  FunctionValue function(size_t i, size_t iqn, const boost::multi_array<double, 2> &ancestor_value_quad) const
657  {
658  static_assert(hasFunction, "Call to function() not available");
659 
660  FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
661  ek(i / m_scalar_family.dimension()) = 1.;
662  return ek * ancestor_value_quad[i % m_scalar_family.dimension()][iqn];
663  }
664 
666  GradientValue gradient(size_t i, const VectorRd &x) const
667  {
668  static_assert(hasGradient, "Call to gradient() not available");
669 
670  GradientValue G = Eigen::Matrix<double, N, dimspace>::Zero();
671  G.row(i / m_scalar_family.dimension()) = m_scalar_family.gradient(i % m_scalar_family.dimension(), x);
672  return G;
673  }
674 
676  GradientValue gradient(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
677  {
678  static_assert(hasGradient, "Call to gradient() not available");
679 
680  GradientValue G = Eigen::Matrix<double, N, dimspace>::Zero();
681  G.row(i / m_scalar_family.dimension()) = ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn];
682  return G;
683  }
684 
686  CurlValue curl(size_t i, const VectorRd &x) const
687  {
688  static_assert(hasCurl, "Call to curl() not available");
689 
690  VectorRd ek = VectorRd::Zero();
691  ek(i / m_scalar_family.dimension()) = 1.;
692  return m_scalar_family.gradient(i % m_scalar_family.dimension(), x).cross(ek);
693  }
694 
696  CurlValue curl(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
697  {
698  static_assert(hasCurl, "Call to curl() not available");
699 
700  VectorRd ek = VectorRd::Zero();
701  ek(i / m_scalar_family.dimension()) = 1.;
702  return ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn].cross(ek);
703  }
704 
706  DivergenceValue divergence(size_t i, const VectorRd &x) const
707  {
708  static_assert(hasDivergence, "Call to divergence() not available");
709 
710  return m_scalar_family.gradient(i % m_scalar_family.dimension(), x)(i / m_scalar_family.dimension());
711  }
712 
714  DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
715  {
716  static_assert(hasDivergence, "Call to divergence() not available");
717 
718  return ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn](i / m_scalar_family.dimension());
719  }
720 
722  CurlValue curlcurl(size_t i, const VectorRd &x) const
723  {
724  static_assert(hasCurlCurl, "Call to curlcurl() not available");
725 
726  FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
727  int p = i / m_scalar_family.dimension();
728  ek(p) = 1.;
729  typename ScalarFamilyType::HessianValue hess = m_scalar_family.hessian(i % m_scalar_family.dimension(), x);
730  return - hess.trace() * ek + hess.col(p);
731  }
732 
734  CurlValue curlcurl(size_t i, size_t iqn, const boost::multi_array<typename ScalarFamilyType::HessianValue, 2> &ancestor_hessian_quad) const
735  {
736  static_assert(hasCurlCurl, "Call to curlcurl() not available");
737 
738  FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
739  int p = i / m_scalar_family.dimension();
740  ek(p) = 1.;
741  typename ScalarFamilyType::HessianValue hess = ancestor_hessian_quad[i % m_scalar_family.dimension()][iqn];
742  return - hess.trace() * ek + hess.col(p);
743  }
744 
745 
747  constexpr inline const ScalarFamilyType &ancestor() const
748  {
749  return m_scalar_family;
750  }
751 
753  inline size_t max_degree() const
754  {
755  return m_scalar_family.max_degree();
756  }
757 
758  private:
759  ScalarFamilyType m_scalar_family;
760  };
761 
762  //----------------------MATRIX FAMILY--------------------------------------------------------
763 
765 
770  // Useful formulas to manipulate this basis (all indices starting from 0):
771  // the i-th element in the basis is f_{i%r} E_{i/r}
772  // the matrix E_m has 1 at position (m%N, m/N)
773  // the element f_aE_b is the i-th in the family with i = ( [b/N]N + [b%N] )r + a
774  template<typename ScalarFamilyType, size_t N>
776  {
777  public:
778  typedef typename Eigen::Matrix<double, N, N> FunctionValue;
779  typedef void GradientValue;
780  typedef void CurlValue;
781  typedef typename Eigen::Matrix<double, N, 1> DivergenceValue;
782  typedef void HessianValue;
783 
784  typedef typename ScalarFamilyType::GeometricSupport GeometricSupport;
785 
786  constexpr static const TensorRankE tensorRank = Matrix;
787  constexpr static const bool hasAncestor = true;
788  static const bool hasFunction = ScalarFamilyType::hasFunction;
789  static const bool hasGradient = false;
790  static const bool hasDivergence = ( ScalarFamilyType::hasGradient && N==dimspace );
791  static const bool hasCurl = false;
792  static const bool hasHessian = false;
793  static const bool hasCurlCurl = false;
794 
795  typedef ScalarFamilyType AncestorType;
796 
797  MatrixFamily(const ScalarFamilyType & scalar_family)
798  : m_scalar_family(scalar_family),
799  m_E(N*N),
800  m_transposeOperator(Eigen::MatrixXd::Zero(scalar_family.dimension()*N*N, scalar_family.dimension()*N*N))
801  {
802  static_assert(ScalarFamilyType::tensorRank == Scalar,
803  "Vector family can only be constructed from scalar families");
804 
805  // Construct the basis for NxN matrices
806  for (size_t j = 0; j < N; j++){
807  for (size_t i = 0; i < N; i++){
808  m_E[j*N + i] = Eigen::Matrix<double, N, N>::Zero();
809  m_E[j*N + i](i,j) = 1.;
810  }
811  }
812 
813  // Construct the transpose operator
814  for (size_t i = 0; i < dimension(); i++){
815  // The i-th basis element is sent to the j-th basis element s.t. j%r=i%r, (j/r)%N=(i/r)/N, (j/r)/N=(i/r)%N
816  size_t r = m_scalar_family.dimension();
817  size_t j = ( ( (i/r)%N )*N + (i/r)/N ) * r + (i%r);
818  m_transposeOperator(i,j) = 1.;
819  }
820  }
821 
823  inline size_t dimension() const
824  {
825  return m_scalar_family.dimension() * N * N;
826  }
827 
829  FunctionValue function(size_t i, const VectorRd & x) const
830  {
831  static_assert(hasFunction, "Call to function() not available");
832 
833  return m_scalar_family.function(i % m_scalar_family.dimension(), x) * m_E[i / m_scalar_family.dimension()];
834  }
835 
837  FunctionValue function(size_t i, size_t iqn, const boost::multi_array<double, 2> &ancestor_value_quad) const
838  {
839  static_assert(hasFunction, "Call to function() not available");
840 
841  return ancestor_value_quad[i % m_scalar_family.dimension()][iqn] * m_E[i / m_scalar_family.dimension()];
842  }
843 
845  DivergenceValue divergence(size_t i, const VectorRd & x) const
846  {
847  static_assert(hasDivergence, "Call to divergence() not available");
848 
849  Eigen::Matrix<double, N, 1> V = m_E[i/m_scalar_family.dimension()].col( (i/m_scalar_family.dimension()) /N);
850  return m_scalar_family.gradient(i % m_scalar_family.dimension(), x)( (i / m_scalar_family.dimension()) / N) * V;
851  }
852 
854  DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
855  {
856  static_assert(hasDivergence, "Call to divergence() not available");
857 
858  Eigen::Matrix<double, N, 1> V = m_E[i/m_scalar_family.dimension()].col( (i/m_scalar_family.dimension()) /N);
859  return ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn]( (i / m_scalar_family.dimension()) / N) * V;
860  }
861 
863  inline const ScalarFamilyType &ancestor() const
864  {
865  return m_scalar_family;
866  }
867 
869  inline const size_t matrixSize() const
870  {
871  return N;
872  }
873 
875  inline const Eigen::MatrixXd transposeOperator() const
876  {
877  return m_transposeOperator;
878  }
879 
881  inline const Eigen::MatrixXd symmetriseOperator() const
882  {
883  return (Eigen::MatrixXd::Identity(dimension(), dimension()) + m_transposeOperator)/2;
884  }
885 
887  const Eigen::MatrixXd symmetricBasis() const
888  {
889  size_t dim_scalar = m_scalar_family.dimension();
890  Eigen::MatrixXd symOpe = symmetriseOperator();
891 
892  Eigen::MatrixXd SB = Eigen::MatrixXd::Zero(dim_scalar * N*(N+1)/2, dimension());
893 
894  // The matrix consists in selecting certain rows of symmetriseOperator, corresponding to the lower triangle part
895  // To select these rows, we loop over the columns of the underlying matrices, and get the rows in symmetriseOperator()
896  // corresponding to the lower triangular part of each column
897  size_t position = 0;
898  for (size_t i = 0; i<N; i++){
899  // Skip the first i*dim_scalar elements in the column (upper triangle) in symOpe, take the remaining (N-i)*dim_scalar
900  SB.middleRows(position, (N-i)*dim_scalar) = symOpe.middleRows(i*(N+1)*dim_scalar, (N-i)*dim_scalar);
901  // update current position
902  position += (N-i)*dim_scalar;
903  }
904 
905  return SB;
906  }
907 
908  private:
909  ScalarFamilyType m_scalar_family;
910  std::vector<Eigen::Matrix<double, N, N>> m_E;
911  Eigen::MatrixXd m_transposeOperator;
912  };
913 
914 
915  //----------------------TANGENT FAMILY--------------------------------------------------------
916 
918  template <typename ScalarFamilyType>
920  {
921  public:
925  typedef double DivergenceValue;
926  typedef Eigen::Matrix2d HessianValue;
927 
929 
930  constexpr static const TensorRankE tensorRank = Vector;
931  constexpr static const bool hasAncestor = true;
932  static const bool hasFunction = true;
933  static const bool hasGradient = false;
934  static const bool hasCurl = false;
935  static const bool hasDivergence = ScalarFamilyType::hasGradient;
936  static const bool hasHessian = false;
937  static const bool hasCurlCurl = ScalarFamilyType::hasHessian;
938 
939  typedef ScalarFamilyType AncestorType;
940 
943  const ScalarFamilyType &scalar_family,
944  const Eigen::Matrix<double, 2, dimspace> &generators
945  )
946  : m_scalar_family(scalar_family),
947  m_generators(generators),
948  m_normal( ( generators.row(0).cross(generators.row(1)) ).normalized() )
949  {
950  static_assert(ScalarFamilyType::hasFunction, "Call to function() not available");
951  static_assert(std::is_same<typename ScalarFamilyType::GeometricSupport, Face>::value,
952  "Tangent families can only be defined on faces");
953  }
954 
956  inline size_t dimension() const
957  {
958  return m_scalar_family.dimension() * 2;
959  }
960 
962  inline FunctionValue function(size_t i, const VectorRd &x) const
963  {
964  return m_generators.row(i / m_scalar_family.dimension()) * m_scalar_family.function(i % m_scalar_family.dimension(), x);
965  }
966 
968  inline DivergenceValue divergence(size_t i, const VectorRd &x) const
969  {
970  return m_generators.row(i / m_scalar_family.dimension()).dot(m_scalar_family.gradient(i % m_scalar_family.dimension(), x));
971  }
972 
974  inline CurlValue curlcurl(size_t i, const VectorRd &x) const
975  {
976  return m_normal.cross(
977  m_scalar_family.hessian(i % m_scalar_family.dimension(), x) *
978  (m_normal.cross(m_generators.row(i / m_scalar_family.dimension())) ) );
979  }
980 
982  constexpr inline const ScalarFamilyType &ancestor() const
983  {
984  return m_scalar_family;
985  }
986 
988  inline size_t max_degree() const
989  {
990  return m_scalar_family.max_degree();
991  }
992 
994  inline Eigen::Matrix<double, 2, dimspace> generators() const
995  {
996  return m_generators;
997  }
998 
999 
1000  private:
1001  ScalarFamilyType m_scalar_family;
1002  Eigen::Matrix<double, 2, dimspace> m_generators;
1003  VectorRd m_normal; // unit normal
1004  };
1005 
1006  //--------------------SHIFTED BASIS----------------------------------------------------------
1007 
1009 
1010  template <typename BasisType>
1012  {
1013  public:
1014  typedef typename BasisType::FunctionValue FunctionValue;
1015  typedef typename BasisType::GradientValue GradientValue;
1016  typedef typename BasisType::CurlValue CurlValue;
1017  typedef typename BasisType::DivergenceValue DivergenceValue;
1018  typedef typename BasisType::HessianValue HessianValue;
1019 
1020  typedef typename BasisType::GeometricSupport GeometricSupport;
1021 
1022  constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
1023  constexpr static const bool hasAncestor = true;
1024  static const bool hasFunction = BasisType::hasFunction;
1025  static const bool hasGradient = BasisType::hasGradient;
1026  static const bool hasCurl = BasisType::hasCurl;
1027  static const bool hasDivergence = BasisType::hasDivergence;
1028  static const bool hasHessian = BasisType::hasHessian;
1029  static const bool hasCurlCurl = BasisType::hasCurlCurl;
1030 
1031  typedef BasisType AncestorType;
1032 
1035  const BasisType &basis,
1036  const int shift
1037  )
1038  : m_basis(basis),
1039  m_shift(shift)
1040  {
1041  // Do nothing
1042  }
1043 
1045  inline size_t dimension() const
1046  {
1047  return m_basis.dimension() - m_shift;
1048  }
1049 
1051  inline size_t shift() const
1052  {
1053  return m_shift;
1054  }
1055 
1057  constexpr inline const BasisType &ancestor() const
1058  {
1059  return m_basis;
1060  }
1061 
1063  inline size_t max_degree() const
1064  {
1065  return m_basis.max_degree();
1066  }
1067 
1069  inline FunctionValue function(size_t i, const VectorRd &x) const
1070  {
1071  static_assert(hasFunction, "Call to function() not available");
1072 
1073  return m_basis.function(i + m_shift, x);
1074  }
1075 
1077  inline GradientValue gradient(size_t i, const VectorRd &x) const
1078  {
1079  static_assert(hasGradient, "Call to gradient() not available");
1080 
1081  return m_basis.gradient(i + m_shift, x);
1082  }
1083 
1085  inline CurlValue curl(size_t i, const VectorRd &x) const
1086  {
1087  static_assert(hasCurl, "Call to curl() not available");
1088 
1089  return m_basis.curl(i + m_shift, x);
1090  }
1091 
1093  inline DivergenceValue divergence(size_t i, const VectorRd &x) const
1094  {
1095  static_assert(hasDivergence, "Call to divergence() not available");
1096 
1097  return m_basis.divergence(i + m_shift, x);
1098  }
1099 
1101  inline HessianValue hessian(size_t i, const VectorRd &x) const
1102  {
1103  static_assert(hasHessian, "Call to hessian() not available");
1104 
1105  return m_basis.hessian(i + m_shift, x);
1106  }
1107 
1108  private:
1109  BasisType m_basis;
1110  int m_shift;
1111  };
1112 
1113  //-----------------------RESTRICTED BASIS-------------------------------------------------------
1114 
1116 
1117  template <typename BasisType>
1119  {
1120  public:
1121  typedef typename BasisType::FunctionValue FunctionValue;
1122  typedef typename BasisType::GradientValue GradientValue;
1123  typedef typename BasisType::CurlValue CurlValue;
1124  typedef typename BasisType::DivergenceValue DivergenceValue;
1125  typedef typename BasisType::HessianValue HessianValue;
1126 
1127  typedef typename BasisType::GeometricSupport GeometricSupport;
1128 
1129  constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
1130  constexpr static const bool hasAncestor = true;
1131  static const bool hasFunction = BasisType::hasFunction;
1132  static const bool hasGradient = BasisType::hasGradient;
1133  static const bool hasCurl = BasisType::hasCurl;
1134  static const bool hasDivergence = BasisType::hasDivergence;
1135  static const bool hasHessian = BasisType::hasHessian;
1136  static const bool hasCurlCurl = BasisType::hasCurlCurl;
1137 
1138  typedef BasisType AncestorType;
1139 
1142  const BasisType &basis,
1143  const size_t &dimension
1144  )
1145  : m_basis(basis),
1146  m_dimension(dimension)
1147  {
1148  // Make sure that the provided dimension is smaller than the one
1149  // of the provided basis
1150  assert(dimension <= basis.dimension());
1151  }
1152 
1154  inline size_t dimension() const
1155  {
1156  return m_dimension;
1157  }
1158 
1160  constexpr inline const BasisType &ancestor() const
1161  {
1162  return m_basis;
1163  }
1164 
1166  inline size_t max_degree() const
1167  {
1168  // We need to find the degree based on the dimension, assumes the basis is hierarchical
1169  size_t deg = 0;
1170  while (PolynomialSpaceDimension<GeometricSupport>::Poly(deg) < m_dimension){
1171  deg++;
1172  }
1173  return deg;
1174  }
1175 
1177  inline FunctionValue function(size_t i, const VectorRd &x) const
1178  {
1179  static_assert(hasFunction, "Call to function() not available");
1180 
1181  return m_basis.function(i, x);
1182  }
1183 
1185  GradientValue gradient(size_t i, const VectorRd &x) const
1186  {
1187  static_assert(hasGradient, "Call to gradient() not available");
1188 
1189  return m_basis.gradient(i, x);
1190  }
1191 
1193  CurlValue curl(size_t i, const VectorRd &x) const
1194  {
1195  static_assert(hasCurl, "Call to curl() not available");
1196 
1197  return m_basis.curl(i, x);
1198  }
1199 
1201  DivergenceValue divergence(size_t i, const VectorRd &x) const
1202  {
1203  static_assert(hasDivergence, "Call to divergence() not available");
1204 
1205  return m_basis.divergence(i, x);
1206  }
1207 
1209  HessianValue hessian(size_t i, const VectorRd &x) const
1210  {
1211  static_assert(hasHessian, "Call to hessian() not available");
1212 
1213  return m_basis.hessian(i, x);
1214  }
1215 
1216  private:
1217  BasisType m_basis;
1218  size_t m_dimension;
1219  };
1220 
1221  //--------------------GRADIENT BASIS----------------------------------------------------------
1222 
1224 
1226  template <typename BasisType>
1228  {
1229  public:
1230  typedef typename BasisType::GradientValue FunctionValue;
1231  typedef void GradientValue;
1232  typedef void CurlValue;
1233  typedef void DivergenceValue;
1234  typedef void HessianValue;
1235 
1236  typedef typename BasisType::GeometricSupport GeometricSupport;
1237 
1238  constexpr static const TensorRankE tensorRank = (BasisType::tensorRank==Scalar ? Vector : Matrix);
1239  constexpr static const bool hasAncestor = true;
1240  static const bool hasFunction = true;
1241  static const bool hasGradient = false;
1242  static const bool hasCurl = false;
1243  static const bool hasDivergence = false;
1244  static const bool hasHessian = false;
1245  static const bool hasCurlCurl = false;
1246 
1247  typedef BasisType AncestorType;
1248 
1250  GradientBasis(const BasisType &basis)
1251  : m_scalar_basis(basis)
1252  {
1253  static_assert(BasisType::tensorRank == Scalar || BasisType::tensorRank == Vector,
1254  "Gradient basis can only be constructed starting from scalar or vector bases");
1255  static_assert(BasisType::hasGradient,
1256  "Gradient basis requires gradient() for the original basis to be available");
1257  // Do nothing
1258  }
1259 
1261  inline size_t dimension() const
1262  {
1263  return m_scalar_basis.dimension();
1264  }
1265 
1267  inline FunctionValue function(size_t i, const VectorRd &x) const
1268  {
1269  return m_scalar_basis.gradient(i, x);
1270  }
1271 
1273  constexpr inline const BasisType &ancestor() const
1274  {
1275  return m_scalar_basis;
1276  }
1277 
1278 
1279  private:
1280  BasisType m_scalar_basis;
1281  };
1282 
1283  //-------------------CURL BASIS-----------------------------------------------------------
1284 
1286 
1288  template <typename BasisType>
1290  {
1291  public:
1293  typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1294  typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1295  typedef double DivergenceValue;
1296  typedef Eigen::Matrix<double, dimspace, dimspace*dimspace> HessianValue;
1297 
1298  typedef typename BasisType::GeometricSupport GeometricSupport;
1299 
1300  constexpr static const TensorRankE tensorRank = Vector;
1301  constexpr static const bool hasAncestor = true;
1302  static const bool hasFunction = true;
1303  static const bool hasGradient = false;
1304  static const bool hasCurl = false;
1305  static const bool hasDivergence = false;
1306  static const bool hasHessian = false;
1307  static const bool hasCurlCurl = false;
1308 
1309  typedef BasisType AncestorType;
1310 
1312  CurlBasis(const BasisType &basis)
1313  : m_basis(basis)
1314  {
1315  static_assert((BasisType::tensorRank == Vector && std::is_same<typename BasisType::GeometricSupport, Cell>::value) ||
1316  (BasisType::tensorRank == Scalar && std::is_same<typename BasisType::GeometricSupport, Face>::value),
1317  "Curl basis can only be constructed starting from vector bases on elements or scalar bases on faces");
1318  static_assert(BasisType::hasCurl,
1319  "Curl basis requires curl() for the original basis to be available");
1320  }
1321 
1323  inline size_t dimension() const
1324  {
1325  return m_basis.dimension();
1326  }
1327 
1329  inline FunctionValue function(size_t i, const VectorRd &x) const
1330  {
1331  return m_basis.curl(i, x);
1332  }
1333 
1335  constexpr inline const BasisType &ancestor() const
1336  {
1337  return m_basis;
1338  }
1339 
1340 
1341  private:
1342  size_t m_degree;
1343  BasisType m_basis;
1344  };
1345 
1346 
1347  //--------------------DIVERGENCE BASIS----------------------------------------------------------
1348 
1350 
1351  template <typename BasisType>
1353  {
1354  public:
1355  typedef typename BasisType::DivergenceValue FunctionValue;
1356  typedef void GradientValue;
1357  typedef void CurlValue;
1358  typedef void DivergenceValue;
1359  typedef void HessianValue;
1360 
1361  typedef typename BasisType::GeometricSupport GeometricSupport;
1362 
1363  constexpr static const TensorRankE tensorRank = Scalar;
1364  constexpr static const bool hasAncestor = true;
1365  static const bool hasFunction = true;
1366  static const bool hasGradient = false;
1367  static const bool hasCurl = false;
1368  static const bool hasDivergence = false;
1369  static const bool hasHessian = false;
1370  static const bool hasCurlCurl = false;
1371 
1372  typedef BasisType AncestorType;
1373 
1375  DivergenceBasis(const BasisType &basis)
1376  : m_vector_basis(basis)
1377  {
1378  static_assert(BasisType::tensorRank == Vector || BasisType::tensorRank == Matrix,
1379  "Divergence basis can only be constructed starting from vector bases");
1380  static_assert(BasisType::hasDivergence,
1381  "Divergence basis requires divergence() for the original basis to be available");
1382  // Do nothing
1383  }
1384 
1386  inline size_t dimension() const
1387  {
1388  return m_vector_basis.dimension();
1389  }
1390 
1392  inline FunctionValue function(size_t i, const VectorRd &x) const
1393  {
1394  return m_vector_basis.divergence(i, x);
1395  }
1396 
1398  constexpr inline const BasisType &ancestor() const
1399  {
1400  return m_vector_basis;
1401  }
1402 
1403 
1404  private:
1405  BasisType m_vector_basis;
1406  };
1407 
1408 
1410  /* It is created as the DivergenceBasis of a TangentFamily obtained rotating the generators by -pi/2 in the oriented face */
1411  template <typename ScalarFamilyType>
1413  {
1414  // Take the generator and rotates them
1415  Eigen::MatrixXd gen = tangent_family.generators();
1416  VectorRd nF = F.normal();
1417  Eigen::MatrixXd rotated_gen = Eigen::MatrixXd::Zero(2, 3);
1418  rotated_gen.row(0) = VectorRd(gen.row(0)).cross(nF);
1419  rotated_gen.row(1) = VectorRd(gen.row(1)).cross(nF);
1420 
1421  TangentFamily<ScalarFamilyType> rotated_tangent_family(tangent_family.ancestor(), rotated_gen);
1422 
1423  return DivergenceBasis<TangentFamily<ScalarFamilyType>>(rotated_tangent_family);
1424  }
1425 
1426  //---------------------------------------------------------------------
1427  // BASES FOR THE KOSZUL COMPLEMENTS OF G^k, R^k
1428  //---------------------------------------------------------------------
1429 
1432  {
1433  public:
1435  typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1436  typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1437  typedef double DivergenceValue;
1438  typedef Eigen::Matrix<double, dimspace, dimspace*dimspace> HessianValue;
1439 
1441 
1442  constexpr static const TensorRankE tensorRank = Vector;
1443  constexpr static const bool hasAncestor = false;
1444  static const bool hasFunction = true;
1445  static const bool hasGradient = false;
1446  static const bool hasCurl = false;
1447  static const bool hasDivergence = true;
1448  static const bool hasHessian = false;
1449  static const bool hasCurlCurl = false;
1450 
1453  const Cell &T,
1454  size_t degree
1455  );
1456 
1458  inline size_t dimension() const
1459  {
1461  }
1462 
1464  FunctionValue function(size_t i, const VectorRd &x) const;
1465 
1467  DivergenceValue divergence(size_t i, const VectorRd &x) const;
1468 
1470  inline size_t max_degree() const
1471  {
1472  return m_degree;
1473  }
1474 
1476  inline VectorZd powers(size_t i) const
1477  {
1478  return m_powers[i];
1479  }
1480 
1481  private:
1483  inline VectorRd _coordinate_transform(const VectorRd &x) const
1484  {
1485  return (x - m_xT) / m_hT;
1486  }
1487 
1488  size_t m_degree;
1489  VectorRd m_xT;
1490  double m_hT;
1491  std::vector<VectorZd> m_powers;
1492  };
1493 
1495  // This basis is obtained by translation and scaling of the following basis of x \times (P^{k-1}(R^3))^3
1496  // (suggested by Daniel Mathews (daniel.mathews@monash.edu)):
1497  // {scalar monomials in (x1,x2,x3) of degree <= k-1} * {(0, x3, -x2), (-x3, 0, x1)}
1498  // and
1499  // {scalar monomials in (x1,x2) of degree <=k-1} * (x2, -x1, 0)
1500  // The vectors (0,x3,-x2), (-x3,0,x1) and (x2,-x1,0) are the "directions", the scalar factors in P^{k-1}
1501  // are given by m_powers
1503  {
1504  public:
1506  typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1508  typedef double DivergenceValue;
1509  typedef Eigen::Matrix<double, dimspace, dimspace*dimspace> HessianValue;
1510 
1512 
1513  constexpr static const TensorRankE tensorRank = Vector;
1514  constexpr static const bool hasAncestor = false;
1515  static const bool hasFunction = true;
1516  static const bool hasGradient = false;
1517  static const bool hasCurl = true;
1518  static const bool hasDivergence = false;
1519  static const bool hasHessian = false;
1520  static const bool hasCurlCurl = false;
1521 
1524  const Cell &T,
1525  size_t degree
1526  );
1527 
1529  inline size_t dimension() const
1530  {
1532  }
1533 
1535  FunctionValue function(size_t i, const VectorRd &x) const;
1536 
1538  CurlValue curl(size_t i, const VectorRd &x) const;
1539 
1541  inline size_t max_degree() const
1542  {
1543  return m_degree;
1544  }
1545 
1547  inline VectorZd powers(size_t i) const
1548  {
1549  return m_powers[i];
1550  }
1551 
1553  inline size_t dimPkmo() const
1554  {
1555  return m_dimPkmo3D;
1556  }
1557 
1558  private:
1560  inline VectorRd _coordinate_transform(const VectorRd &x) const
1561  {
1562  return (x - m_xT) / m_hT;
1563  }
1564 
1565  // To evaluate the value and curl of the "direction"
1566  VectorRd direction_value(size_t i, const VectorRd &x) const;
1567  VectorRd direction_curl(size_t i, const VectorRd &x) const;
1568 
1569  size_t m_degree; // Degree k of the basis
1570  VectorRd m_xT; // center of cell
1571  double m_hT; // diameter of cell
1572  size_t m_dimPkmo3D; // shorthand for dimension of P^{k-1}(R^3)
1573  size_t m_dimPkmo2D; // shorthand for dimension of P^{k-1}(R^2)
1574  std::vector<VectorZd> m_powers; // vector listing the powers of the scalar factors in the basis
1575 
1576  };
1577 
1580  {
1581  public:
1583  typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1584  typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1585  typedef double DivergenceValue;
1586  typedef Eigen::Matrix<double, dimspace, dimspace*dimspace> HessianValue;
1587 
1589 
1590  typedef Eigen::Matrix<double, 2, dimspace> JacobianType;
1591 
1592  constexpr static const TensorRankE tensorRank = Vector;
1593  constexpr static const bool hasAncestor = false;
1594  static const bool hasFunction = true;
1595  static const bool hasGradient = false;
1596  static const bool hasCurl = false;
1597  static const bool hasDivergence = true;
1598  static const bool hasHessian = false;
1599  static const bool hasCurlCurl = false;
1600 
1603  const Face &F,
1604  size_t degree
1605  );
1606 
1608  inline size_t dimension() const
1609  {
1611  }
1612 
1614  FunctionValue function(size_t i, const VectorRd &x) const;
1615 
1617  DivergenceValue divergence(size_t i, const VectorRd &x) const;
1618 
1620  inline const JacobianType &jacobian() const
1621  {
1622  return m_jacobian;
1623  }
1624 
1626  inline size_t max_degree() const
1627  {
1628  return m_degree;
1629  }
1630 
1632  inline Eigen::Vector2i powers(size_t i) const
1633  {
1634  return m_powers[i];
1635  }
1636 
1637  private:
1639  inline Eigen::Vector2d _coordinate_transform(const VectorRd &x) const
1640  {
1641  return m_jacobian * (x - m_xF);
1642  }
1643 
1644  size_t m_degree;
1645  VectorRd m_xF;
1646  double m_hF;
1647  JacobianType m_jacobian;
1648  std::vector<Eigen::Vector2i> m_powers;
1649  };
1650 
1651 
1654  {
1655  public:
1657  typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1658  typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1659  typedef double DivergenceValue;
1660  typedef Eigen::Matrix<double, dimspace, dimspace*dimspace> HessianValue;
1661 
1663 
1664  typedef Eigen::Matrix<double, 2, dimspace> JacobianType;
1665 
1666  constexpr static const TensorRankE tensorRank = Vector;
1667  constexpr static const bool hasAncestor = false;
1668  static const bool hasFunction = true;
1669  static const bool hasGradient = false;
1670  static const bool hasCurl = false;
1671  static const bool hasDivergence = false;
1672  static const bool hasHessian = false;
1673  static const bool hasCurlCurl = false;
1674 
1677  const Face &F,
1678  size_t degree
1679  );
1680 
1682  inline size_t dimension() const
1683  {
1685  }
1686 
1688  FunctionValue function(size_t i, const VectorRd &x) const;
1689 
1691  inline const VectorRd &normal() const
1692  {
1693  return m_nF;
1694  }
1695 
1697  inline const std::shared_ptr<RolyComplBasisFace> &rck() const
1698  {
1699  return m_Rck_basis;
1700  }
1701 
1702  private:
1703  size_t m_degree;
1704  VectorRd m_nF;
1705  std::shared_ptr<RolyComplBasisFace> m_Rck_basis;
1706  };
1707 
1708  //------------------------------------------------------------------------------
1709  // Free functions
1710  //------------------------------------------------------------------------------
1711 
1713  {
1719  CurlCurl
1720  };
1721 
1723  template <typename outValue, typename inValue, typename FunctionType>
1724  boost::multi_array<outValue, 2> transform_values_quad(
1725  const boost::multi_array<inValue, 2> &B_quad,
1726  const FunctionType &F
1727  )
1728  {
1729  boost::multi_array<outValue, 2> transformed_B_quad( boost::extents[B_quad.shape()[0]][B_quad.shape()[1]] );
1730 
1731  std::transform( B_quad.origin(), B_quad.origin() + B_quad.num_elements(), transformed_B_quad.origin(), F);
1732 
1733  return transformed_B_quad;
1734  }
1735 
1737 
1738  template <typename ScalarBasisType, size_t N>
1740  const ScalarBasisType & B,
1741  const std::vector<Eigen::VectorXd> & v
1742  )
1743  {
1744  size_t r = B.dimension();
1745  size_t k = v.size();
1746 
1747  Eigen::MatrixXd M = Eigen::MatrixXd::Zero(r*k, r*N);
1748 
1749  for (size_t i=0; i < k; i++){
1750  // Check the dimension of vector v[i]
1751  assert(v[i].size() == N);
1752 
1753  // Fill in M
1754  for (size_t j=0; j < N; j++){
1755  M.block(i*r, j*r, r, r) = v[i](j) * Eigen::MatrixXd::Identity(r,r);
1756  }
1757  }
1758 
1761  }
1762 
1763 
1765  inline static std::function<Eigen::MatrixXd(const Eigen::MatrixXd &)>
1766  symmetrise_matrix = [](const Eigen::MatrixXd & x)->Eigen::MatrixXd { return 0.5*(x+x.transpose());};
1767 
1769  inline static std::function<Eigen::MatrixXd(const Eigen::MatrixXd &)>
1770  skew_symmetrise_matrix = [](const Eigen::MatrixXd & x)->Eigen::MatrixXd { return 0.5*(x-x.transpose());};
1771 
1773 
1774  template <typename ScalarBasisType, size_t N>
1776  const ScalarBasisType & B
1777  )
1778  {
1779  size_t r = B.dimension();
1780  Eigen::MatrixXd M = Eigen::MatrixXd::Zero(r, r*N*N);
1781 
1782  for (size_t k=0; k < N; k++){
1783  M.block(0, k*r*(N+1), r, r) = Eigen::MatrixXd::Identity(r, r);
1784  }
1785 
1787  return Family<MatrixFamily<ScalarBasisType, N>>(matbasis, M);
1788  }
1789 
1790  //------------------------------------------------------------------------------
1791  // BASIS EVALUATIONS
1792  //------------------------------------------------------------------------------
1793 
1794  //-----------------------DETAILS FOR EVALUATIONS----------------------
1795 
1796  namespace detail
1797  {
1799 
1800  template <typename BasisType, BasisFunctionE BasisFunction>
1802  {
1803  };
1804 
1805  // Evaluate the function value at x
1806  template <typename BasisType>
1808  {
1809  static_assert(BasisType::hasFunction, "Call to function not available");
1810  typedef typename BasisType::FunctionValue ReturnValue;
1811  static inline ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
1812  {
1813  return basis.function(i, x);
1814  }
1815 
1816  // Computes function value at quadrature node iqn, knowing values of ancestor basis at quadrature nodes
1817  static inline ReturnValue evaluate(
1818  const BasisType &basis,
1819  size_t i,
1820  size_t iqn,
1821  const boost::multi_array<ReturnValue, 2> &ancestor_value_quad
1822  )
1823  {
1824  return basis.function(i, iqn, ancestor_value_quad);
1825  }
1826 
1827  };
1828 
1829  // Evaluate the gradient value at x
1830  template <typename BasisType>
1832  {
1833  static_assert(BasisType::hasGradient, "Call to gradient not available");
1834  typedef typename BasisType::GradientValue ReturnValue;
1835  static inline ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
1836  {
1837  return basis.gradient(i, x);
1838  }
1839 
1840  // Computes gradient value at quadrature node iqn, knowing gradients of ancestor basis at quadrature nodes
1841  static inline ReturnValue evaluate(
1842  const BasisType &basis,
1843  size_t i,
1844  size_t iqn,
1845  const boost::multi_array<ReturnValue, 2> &ancestor_gradient_quad
1846  )
1847  {
1848  return basis.gradient(i, iqn, ancestor_gradient_quad);
1849  }
1850  };
1851 
1852  // Evaluate the curl value at x
1853  template <typename BasisType>
1854  struct basis_evaluation_traits<BasisType, Curl>
1855  {
1856  static_assert(BasisType::hasCurl, "Call to curl not available");
1857  typedef typename BasisType::CurlValue ReturnValue;
1858  static inline ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
1859  {
1860  return basis.curl(i, x);
1861  }
1862 
1863  // Computes curl value at quadrature node iqn, knowing curls of ancestor basis at quadrature nodes
1864  static inline ReturnValue evaluate(
1865  const BasisType &basis,
1866  size_t i,
1867  size_t iqn,
1868  const boost::multi_array<ReturnValue, 2> &ancestor_curl_quad
1869  )
1870  {
1871  return basis.curl(i, iqn, ancestor_curl_quad);
1872  }
1873  };
1874 
1875  // Evaluate the divergence value at x
1876  template <typename BasisType>
1878  {
1879  static_assert(BasisType::hasDivergence, "Call to divergence not available");
1880  typedef typename BasisType::DivergenceValue ReturnValue;
1881  static inline ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
1882  {
1883  return basis.divergence(i, x);
1884  }
1885 
1886  // Computes divergence value at quadrature node iqn, knowing divergences of ancestor basis at quadrature nodes
1887  static inline ReturnValue evaluate(
1888  const BasisType &basis,
1889  size_t i,
1890  size_t iqn,
1891  const boost::multi_array<ReturnValue, 2> &ancestor_divergence_quad
1892  )
1893  {
1894  return basis.divergence(i, iqn, ancestor_divergence_quad);
1895  }
1896 
1897  };
1898 
1899  // Evaluate the hessian value at x
1900  template <typename BasisType>
1902  {
1903  static_assert(BasisType::hasHessian, "Call to hessian not available");
1904  typedef typename BasisType::HessianValue ReturnValue;
1905  static inline ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
1906  {
1907  return basis.hessian(i, x);
1908  }
1909 
1910  // Computes hessian value at quadrature node iqn, knowing hessian of ancestor basis at quadrature nodes
1911  static inline ReturnValue evaluate(
1912  const BasisType &basis,
1913  size_t i,
1914  size_t iqn,
1915  const boost::multi_array<ReturnValue, 2> &ancestor_hessian_quad
1916  )
1917  {
1918  return basis.hessian(i, iqn, ancestor_hessian_quad);
1919  }
1920 
1921  };
1922 
1923  // Evaluate the curl curl value at x
1924  template <typename BasisType>
1926  {
1927  static_assert(BasisType::hasCurlCurl, "Call to curl curl not available");
1928  typedef typename BasisType::CurlValue ReturnValue;
1929  static inline ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
1930  {
1931  return basis.curlcurl(i, x);
1932  }
1933 
1934  // Computes hessian value at quadrature node iqn, knowing hessian of ancestor basis at quadrature nodes
1935  static inline ReturnValue evaluate(
1936  const BasisType &basis,
1937  size_t i,
1938  size_t iqn,
1939  const boost::multi_array<ReturnValue, 2> &ancestor_curlcurl_quad
1940  )
1941  {
1942  return basis.curlcurl(i, iqn, ancestor_curlcurl_quad);
1943  }
1944 
1945  };
1946 
1947  //---------- TENSORIZED FAMILY EVALUATION TRAITS -----------------------------------------
1948  // Evaluate the value at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
1949  template <typename ScalarBasisType, size_t N>
1951  {
1952  static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasFunction, "Call to function not available");
1953 
1955  static const BasisFunctionE AncestorBasisFunction = Function; // Type of values needed from ancestor basis
1957 
1958  // Computes function values at x
1959  static inline ReturnValue evaluate(
1961  size_t i,
1962  const VectorRd &x
1963  )
1964  {
1965  return basis.function(i, x);
1966  }
1967 
1968  // Computes function value at quadrature node iqn, knowing ancestor basis at quadrature nodes
1969  static inline ReturnValue evaluate(
1971  size_t i,
1972  size_t iqn,
1973  const boost::multi_array<double, 2> &ancestor_basis_quad
1974  )
1975  {
1976  return basis.function(i, iqn, ancestor_basis_quad);
1977  }
1978  };
1979 
1980  // Evaluate the gradient at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
1981  template <typename ScalarBasisType, size_t N>
1983  {
1984  static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasGradient, "Call to gradient not available");
1985 
1987  static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
1989 
1990  // Computes gradient value at x
1991  static inline ReturnValue evaluate(
1993  size_t i,
1994  const VectorRd &x
1995  )
1996  {
1997  return basis.gradient(i, x);
1998  }
1999 
2000  // Computes gradient value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2001  static inline ReturnValue evaluate(
2003  size_t i,
2004  size_t iqn,
2005  const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2006  )
2007  {
2008  return basis.gradient(i, iqn, ancestor_basis_quad);
2009  }
2010  };
2011 
2012  // Evaluate the curl at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2013  template <typename ScalarBasisType, size_t N>
2015  {
2016  static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasCurl, "Call to curl not available");
2017 
2019  static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2021 
2022  // Computes curl values at x
2023  static inline ReturnValue evaluate(
2025  size_t i,
2026  const VectorRd &x
2027  )
2028  {
2029  return basis.curl(i, x);
2030  }
2031 
2032  // Computes curl values at quadrature node iqn, knowing ancestor basis at quadrature nodes
2033  static inline ReturnValue evaluate(
2035  size_t i,
2036  size_t iqn,
2037  const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2038  )
2039  {
2040  return basis.curl(i, iqn, ancestor_basis_quad);
2041  }
2042 
2043  };
2044 
2045  // Evaluate the divergence at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2046  template <typename ScalarBasisType, size_t N>
2048  {
2049  static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasDivergence, "Call to divergence not available");
2050 
2052  static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2054 
2055  // Computes divergence value at x
2056  static inline ReturnValue evaluate(
2058  size_t i,
2059  const VectorRd &x
2060  )
2061  {
2062  return basis.divergence(i, x);
2063  }
2064 
2065  // Computes divergence value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2066  static inline ReturnValue evaluate(
2068  size_t i,
2069  size_t iqn,
2070  const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2071  )
2072  {
2073  return basis.divergence(i, iqn, ancestor_basis_quad);
2074  }
2075 
2076  };
2077 
2078  // Evaluate the curl curl at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2079  template <typename ScalarBasisType, size_t N>
2081  {
2082  static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasCurlCurl, "Call to curl curl not available");
2083 
2085  static const BasisFunctionE AncestorBasisFunction = Hessian; // Type of values needed from ancestor basis
2087 
2088  // Computes curl curl value at x
2089  static inline ReturnValue evaluate(
2091  size_t i,
2092  const VectorRd &x
2093  )
2094  {
2095  return basis.curlcurl(i, x);
2096  }
2097 
2098  // Computes curl curl value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2099  static inline ReturnValue evaluate(
2101  size_t i,
2102  size_t iqn,
2103  const boost::multi_array<MatrixRd, 2> &ancestor_basis_quad
2104  )
2105  {
2106  return basis.curlcurl(i, iqn, ancestor_basis_quad);
2107  }
2108 
2109  };
2110 
2111  //---------- MATRIX FAMILY EVALUATION TRAITS -----------------------------------------
2112  // Evaluate the value at x of a MatrixFamily (includes information on the ancestor basis, to optimise eval_quad for matrix families)
2113  template <typename ScalarBasisType, size_t N>
2114  struct basis_evaluation_traits<MatrixFamily<ScalarBasisType, N>, Function>
2115  {
2116  static_assert(MatrixFamily<ScalarBasisType, N>::hasFunction, "Call to function not available");
2117 
2119  static const BasisFunctionE AncestorBasisFunction = Function; // Type of values needed from ancestor basis
2121 
2122  // Computes function values at x
2123  static inline ReturnValue evaluate(
2124  const MatrixFamily<ScalarBasisType, N> &basis,
2125  size_t i,
2126  const VectorRd &x
2127  )
2128  {
2129  return basis.function(i, x);
2130  }
2131 
2132  // Computes function value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2133  static inline ReturnValue evaluate(
2134  const MatrixFamily<ScalarBasisType, N> &basis,
2135  size_t i,
2136  size_t iqn,
2137  const boost::multi_array<double, 2> &ancestor_basis_quad
2138  )
2139  {
2140  return basis.function(i, iqn, ancestor_basis_quad);
2141  }
2142  };
2143 
2144  // Evaluate the divergence at x of a MatrixFamily (includes information on the ancestor basis, to optimise eval_quad for matrix families)
2145  template <typename ScalarBasisType, size_t N>
2146  struct basis_evaluation_traits<MatrixFamily<ScalarBasisType, N>, Divergence>
2147  {
2148  static_assert(MatrixFamily<ScalarBasisType, N>::hasDivergence, "Call to divergence not available");
2149 
2151  static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2153 
2154  // Computes divergence value at x
2155  static inline ReturnValue evaluate(
2156  const MatrixFamily<ScalarBasisType, N> &basis,
2157  size_t i,
2158  const VectorRd &x
2159  )
2160  {
2161  return basis.divergence(i, x);
2162  }
2163 
2164  // Computes divergence value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2165  static inline ReturnValue evaluate(
2166  const MatrixFamily<ScalarBasisType, N> &basis,
2167  size_t i,
2168  size_t iqn,
2169  const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2170  )
2171  {
2172  return basis.divergence(i, iqn, ancestor_basis_quad);
2173  }
2174 
2175  };
2176 
2177  } // end of namespace detail
2178 
2179 
2180  //-----------------------------------EVALUATE_QUAD--------------------------------------
2181 
2183  template <BasisFunctionE BasisFunction>
2185  {
2187  template <typename BasisType>
2188  static boost::multi_array<typename detail::basis_evaluation_traits<BasisType, BasisFunction>::ReturnValue, 2>
2190  const BasisType &basis,
2191  const QuadratureRule &quad
2192  )
2193  {
2195 
2196  boost::multi_array<typename traits::ReturnValue, 2>
2197  basis_quad(boost::extents[basis.dimension()][quad.size()]);
2198 
2199  for (size_t i = 0; i < basis.dimension(); i++)
2200  {
2201  for (size_t iqn = 0; iqn < quad.size(); iqn++)
2202  {
2203  basis_quad[i][iqn] = traits::evaluate(basis, i, quad[iqn].vector());
2204  } // for iqn
2205  } // for i
2206 
2207  return basis_quad;
2208  }
2209 
2211  template <typename BasisType>
2212  static boost::multi_array<typename detail::basis_evaluation_traits<Family<BasisType>, BasisFunction>::ReturnValue, 2>
2214  const Family<BasisType> &basis,
2215  const QuadratureRule &quad
2216  )
2217  {
2218  typedef detail::basis_evaluation_traits<Family<BasisType>, BasisFunction> traits;
2219 
2220  boost::multi_array<typename traits::ReturnValue, 2>
2221  basis_quad(boost::extents[basis.dimension()][quad.size()]);
2222 
2223  // Compute values at quadrature note on ancestor basis, and then do a transformation
2224  const auto &ancestor_basis = basis.ancestor();
2225  boost::multi_array<typename traits::ReturnValue, 2>
2226  ancestor_basis_quad = evaluate_quad<BasisFunction>::compute(ancestor_basis, quad);
2227 
2228  for (size_t iqn = 0; iqn < quad.size(); iqn++)
2229  {
2230  for (size_t i = 0; i < size_t(basis.matrix().rows()); i++){
2231  basis_quad[i][iqn] = traits::evaluate(basis, i, iqn, ancestor_basis_quad);
2232  }
2233  }
2234  return basis_quad;
2235  }
2236 
2238  template <typename BasisType, size_t N>
2239  static boost::multi_array<typename detail::basis_evaluation_traits<TensorizedVectorFamily<BasisType, N>, BasisFunction>::ReturnValue, 2>
2242  const QuadratureRule &quad
2243  )
2244  {
2246 
2247  boost::multi_array<typename traits::ReturnValue, 2>
2248  basis_quad(boost::extents[basis.dimension()][quad.size()]);
2249 
2250  const auto &ancestor_basis = basis.ancestor();
2251  const boost::multi_array<typename traits::AncestorBasisFunctionValue, 2> ancestor_basis_quad
2253 
2254  for (size_t i = 0; i < basis.dimension(); i++){
2255  for (size_t iqn = 0; iqn < quad.size(); iqn++){
2256  basis_quad[i][iqn] = traits::evaluate(basis, i, iqn, ancestor_basis_quad);
2257  }
2258  }
2259  return basis_quad;
2260  }
2261 
2263  template <typename BasisType, size_t N>
2264  static boost::multi_array<typename detail::basis_evaluation_traits<MatrixFamily<BasisType, N>, BasisFunction>::ReturnValue, 2>
2266  const MatrixFamily<BasisType, N> &basis,
2267  const QuadratureRule &quad
2268  )
2269  {
2270  typedef detail::basis_evaluation_traits<MatrixFamily<BasisType, N>, BasisFunction> traits;
2271 
2272  boost::multi_array<typename traits::ReturnValue, 2>
2273  basis_quad(boost::extents[basis.dimension()][quad.size()]);
2274 
2275  const auto &ancestor_basis = basis.ancestor();
2276  const boost::multi_array<typename traits::AncestorBasisFunctionValue, 2> ancestor_basis_quad
2278 
2279  for (size_t i = 0; i < basis.dimension(); i++){
2280  for (size_t iqn = 0; iqn < quad.size(); iqn++){
2281  basis_quad[i][iqn] = traits::evaluate(basis, i, iqn, ancestor_basis_quad);
2282  }
2283  }
2284  return basis_quad;
2285  }
2286 
2287  };
2288 
2289 
2290  //------------------------------------------------------------------------------
2291  // ORTHONORMALISATION
2292  //------------------------------------------------------------------------------
2293 
2302  template <typename T>
2303  Eigen::MatrixXd gram_schmidt(
2304  boost::multi_array<T, 2> &basis_eval,
2305  const std::function<double(size_t, size_t)> &inner_product
2306  )
2307  {
2308  auto induced_norm = [inner_product](size_t i) -> double {
2309  return std::sqrt(inner_product(i, i));
2310  };
2311 
2312  // Number of basis functions
2313  size_t Nb = basis_eval.shape()[0];
2314  // Number of quadrature nodes
2315  size_t Nqn = basis_eval.shape()[1];
2316 
2317  Eigen::MatrixXd B = Eigen::MatrixXd::Zero(Nb, Nb);
2318 
2319  // Normalise the first element
2320  double norm = induced_norm(0);
2321  for (size_t iqn = 0; iqn < Nqn; iqn++)
2322  {
2323  basis_eval[0][iqn] /= norm;
2324  } // for iqn
2325  B(0, 0) = 1. / norm;
2326 
2327  for (size_t ib = 1; ib < Nb; ib++)
2328  {
2329  // 'coeffs' represents the coefficients of the ib-th orthogonal function on the ON basis functions 0 to ib-1
2330  Eigen::RowVectorXd coeffs = Eigen::RowVectorXd::Zero(ib);
2331  for (size_t pb = 0; pb < ib; pb++)
2332  {
2333  coeffs(pb) = -inner_product(ib, pb);
2334  } // for pb
2335 
2336  // store the values of the orthogonalised ib-th basis function
2337  for (size_t pb = 0; pb < ib; pb++)
2338  {
2339  for (size_t iqn = 0; iqn < Nqn; iqn++)
2340  {
2341  basis_eval[ib][iqn] += coeffs(pb) * basis_eval[pb][iqn];
2342  } // for iqn
2343  } // for pb
2344 
2345  // normalise ib-th basis function
2346  double norm = induced_norm(ib);
2347  for (size_t iqn = 0; iqn < Nqn; iqn++)
2348  {
2349  basis_eval[ib][iqn] /= norm;
2350  } // for iqn
2351  coeffs /= norm;
2352  // Compute ib-th row of B.
2353  // B.topLeftCorner(ib, ib) contains the rows that represent the ON basis functions 0 to ib-1 on
2354  // the original basis. Multiplying on the left by coeffs gives the coefficients of the ON basis
2355  // functions on the original basis functions from 0 to ib-1.
2356  B.block(ib, 0, 1, ib) = coeffs * B.topLeftCorner(ib, ib);
2357  B(ib, ib) = 1. / norm;
2358  }
2359  return B;
2360  }
2361 
2362  //------------------------------------------------------------------------------
2363 
2365  double scalar_product(const double &x, const double &y);
2366 
2368  double scalar_product(const double &x, const Eigen::Matrix<double, 1, 1> &y);
2369 
2371  double scalar_product(const VectorRd &x, const VectorRd &y);
2372 
2374  template<int N>
2375  double scalar_product(const Eigen::Matrix<double, N, N> & x, const Eigen::Matrix<double, N, N> & y)
2376  {
2377  return (x.transpose() * y).trace();
2378  }
2379 
2381  template <typename Value>
2382  boost::multi_array<double, 2> scalar_product(
2383  const boost::multi_array<Value, 2> &basis_quad,
2384  const Value &v
2385  )
2386  {
2387  boost::multi_array<double, 2> basis_dot_v_quad(boost::extents[basis_quad.shape()[0]][basis_quad.shape()[1]]);
2388  std::transform(basis_quad.origin(), basis_quad.origin() + basis_quad.num_elements(),
2389  basis_dot_v_quad.origin(), [&v](const Value &x) -> double { return scalar_product(x,v); });
2390  return basis_dot_v_quad;
2391  }
2392 
2393 
2395  boost::multi_array<VectorRd, 2>
2397  const boost::multi_array<VectorRd, 2> &basis_quad,
2398  const VectorRd &v
2399  );
2400 
2402  template <typename BasisType>
2404  const BasisType &basis,
2405  const QuadratureRule &qr,
2406  boost::multi_array<typename BasisType::FunctionValue, 2> &basis_quad
2407  )
2408  {
2409  // Check that the basis evaluation and quadrature rule are coherent
2410  assert(basis.dimension() == basis_quad.shape()[0] && qr.size() == basis_quad.shape()[1]);
2411 
2412  // The inner product between the i-th and j-th basis vectors
2413  std::function<double(size_t, size_t)> inner_product = [&basis_quad, &qr](size_t i, size_t j) -> double {
2414  double r = 0.;
2415  for (size_t iqn = 0; iqn < qr.size(); iqn++)
2416  {
2417  r += qr[iqn].w * scalar_product(basis_quad[i][iqn], basis_quad[j][iqn]);
2418  } // for iqn
2419  return r;
2420  };
2421 
2422  Eigen::MatrixXd B = gram_schmidt(basis_quad, inner_product);
2423 
2424  return Family<BasisType>(basis, B);
2425  }
2426 
2428  /* This method is more robust that the previous one based on values at quadrature nodes */
2429  template <typename BasisType>
2431  const BasisType &basis,
2432  const Eigen::MatrixXd & GM
2433  )
2434  {
2435  // Check that the basis and Gram matrix are coherent
2436  assert(basis.dimension() == size_t(GM.rows()) && GM.rows() == GM.cols());
2437 
2438  Eigen::MatrixXd L = GM.llt().matrixL();
2439 
2440  return Family<BasisType>(basis, L.inverse());
2441  }
2442 
2443  //------------------------------------------------------------------------------
2444  // Gram matrices
2445  //------------------------------------------------------------------------------
2446 
2450  template <typename FunctionValue>
2451  Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> &B1,
2452  const boost::multi_array<FunctionValue, 2> &B2,
2453  const QuadratureRule &qr,
2454  const size_t nrows,
2455  const size_t ncols,
2456  const std::string sym = "nonsym"
2457  )
2458  {
2459  // Check that the basis evaluation and quadrature rule are coherent
2460  assert(qr.size() == B1.shape()[1] && qr.size() == B2.shape()[1]);
2461  // Check that we don't ask for more members of family than available
2462  assert(nrows <= B1.shape()[0] && ncols <= B2.shape()[0]);
2463 
2464  // Re-cast quadrature weights into ArrayXd to make computations faster
2465  Eigen::ArrayXd qr_weights = Eigen::ArrayXd::Zero(qr.size());
2466  for (size_t iqn = 0; iqn < qr.size(); iqn++)
2467  {
2468  qr_weights(iqn) = qr[iqn].w;
2469  }
2470 
2471  Eigen::MatrixXd M = Eigen::MatrixXd::Zero(nrows, ncols);
2472  for (size_t i = 0; i < nrows; i++)
2473  {
2474  size_t jcut = 0;
2475  if (sym == "sym")
2476  jcut = i;
2477  for (size_t j = 0; j < jcut; j++)
2478  {
2479  M(i, j) = M(j, i);
2480  }
2481  for (size_t j = jcut; j < ncols; j++)
2482  {
2483  std::vector<double> tmp(B1.shape()[1]);
2484  // Extract values at quadrature nodes for elements i of B1 and j of B2
2485  auto B1i = B1[boost::indices[i][boost::multi_array_types::index_range(0, B1.shape()[1])]];
2486  auto B2j = B2[boost::indices[j][boost::multi_array_types::index_range(0, B1.shape()[1])]];
2487  // Compute scalar product of B1i and B2j, and recast it as ArrayXd
2488  std::transform(B1i.begin(), B1i.end(), B2j.begin(), tmp.begin(), [](FunctionValue a, FunctionValue b) -> double { return scalar_product(a, b); });
2489  Eigen::ArrayXd tmp_array = Eigen::Map<Eigen::ArrayXd, Eigen::Unaligned>(tmp.data(), tmp.size());
2490  // Multiply by quadrature weights and sum (using .sum() of ArrayXd makes this step faster than a loop)
2491  M(i, j) = (qr_weights * tmp_array).sum();
2492 
2493  // Simple version with loop (replaces everything above after the for on j)
2494  /*
2495  for (size_t iqn = 0; iqn < qr.size(); iqn++) {
2496  M(i,j) += qr[iqn].w * scalar_product(B1[i][iqn], B2[j][iqn]);
2497  } // for iqn
2498  */
2499 
2500  } // for j
2501  } // for i
2502  return M;
2503  }
2504 
2508  template <typename FunctionValue>
2509  Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> &B1,
2510  const boost::multi_array<FunctionValue, 2> &B2,
2511  const QuadratureRule &qr,
2512  const std::string sym = "nonsym"
2513  )
2514  {
2515  return compute_gram_matrix<FunctionValue>(B1, B2, qr, B1.shape()[0], B2.shape()[0], sym);
2516  }
2517 
2519  template <typename FunctionValue>
2520  inline Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> &B,
2521  const QuadratureRule &qr
2522  )
2523  {
2524  return compute_gram_matrix<FunctionValue>(B, B, qr, "sym");
2525  }
2526 
2528  Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> &B1,
2529  const boost::multi_array<double, 2> &B2,
2530  const QuadratureRule &qr
2531  );
2532 
2536  Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<double, 2> &B1,
2537  const boost::multi_array<double, 2> &B2,
2538  const QuadratureRule &qr,
2539  const size_t nrows,
2540  const size_t ncols,
2541  const std::string sym = "nonsym"
2542  );
2543 
2547  Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<double, 2> &B1,
2548  const boost::multi_array<double, 2> &B2,
2549  const QuadratureRule &qr,
2550  const std::string sym = "nonsym"
2551  );
2552 
2556  Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> &B1,
2557  const boost::multi_array<VectorRd, 2> &B2,
2558  const QuadratureRule &qr,
2559  const size_t nrows,
2560  const size_t ncols,
2561  const std::string sym = "nonsym"
2562  );
2563 
2565  Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> &B1,
2566  const boost::multi_array<VectorRd, 2> &B2,
2567  const QuadratureRule &qr,
2568  const std::string sym = "nonsym"
2569  );
2570 
2572  template<typename ScalarFamilyType, size_t N>
2574  const boost::multi_array<double, 2> & scalar_family_quad,
2575  const QuadratureRule & qr
2576  )
2577  {
2578  Eigen::MatrixXd Gram = Eigen::MatrixXd::Zero(MatFam.dimension(), MatFam.dimension());
2579 
2580  // Gram matrix of the scalar family
2581  Eigen::MatrixXd scalarGram = compute_gram_matrix<double>(scalar_family_quad, qr);
2582  for (size_t i = 0; i < MatFam.dimension(); i = i+scalarGram.rows()){
2583  Gram.block(i, i, scalarGram.rows(), scalarGram.cols()) = scalarGram;
2584  }
2585 
2586  return Gram;
2587  }
2588 
2590  template <typename T>
2591  Eigen::VectorXd integrate(
2592  const FType<T> &f,
2593  const BasisQuad<T> &B,
2594  const QuadratureRule &qr,
2595  size_t n_rows = 0
2596  )
2597  {
2598  // If default, set n_rows to size of family
2599  if (n_rows == 0)
2600  {
2601  n_rows = B.shape()[0];
2602  }
2603 
2604  // Number of quadrature nodes
2605  const size_t num_quads = qr.size();
2606 
2607  // Check number of quadrature nodes is compatible with B
2608  assert(num_quads == B.shape()[1]);
2609 
2610  // Check that we don't ask for more members of family than available
2611  assert(n_rows <= B.shape()[0]);
2612 
2613  Eigen::VectorXd V = Eigen::VectorXd::Zero(n_rows);
2614 
2615  for (size_t iqn = 0; iqn < num_quads; iqn++)
2616  {
2617  double qr_weight = qr[iqn].w;
2618  T f_on_qr = f(qr[iqn].vector());
2619  for (size_t i = 0; i < n_rows; i++)
2620  {
2621  V(i) += qr_weight * scalar_product(B[i][iqn], f_on_qr);
2622  }
2623  }
2624 
2625  return V;
2626  }
2627 
2629  template <typename T, typename U>
2631  const FType<U> &f,
2632  const BasisQuad<T> &B1,
2633  const BasisQuad<T> &B2,
2634  const QuadratureRule &qr,
2635  size_t n_rows = 0,
2636  size_t n_cols = 0,
2637  const std::string sym = "nonsym"
2638  )
2639  {
2640  // If default, set n_rows and n_cols to size of families
2641  if (n_rows == 0 && n_cols == 0)
2642  {
2643  n_rows = B1.shape()[0];
2644  n_cols = B2.shape()[0];
2645  }
2646 
2647  // Number of quadrature nodes
2648  const size_t num_quads = qr.size();
2649  // Check number of quadrature nodes is compatible with B1 and B2
2650  assert(num_quads == B1.shape()[1] && num_quads == B2.shape()[1]);
2651  // Check that we don't ask for more members of family than available
2652  assert(n_rows <= B1.shape()[0] && n_cols <= B2.shape()[0]);
2653 
2654  Eigen::MatrixXd M = Eigen::MatrixXd::Zero(n_rows, n_cols);
2655  for (size_t iqn = 0; iqn < num_quads; iqn++)
2656  {
2657  double qr_weight = qr[iqn].w;
2658  U f_on_qr = f(qr[iqn].vector());
2659  for (size_t i = 0; i < n_rows; i++)
2660  {
2661  T f_B1 = f_on_qr * B1[i][iqn];
2662  size_t jcut = 0;
2663  if (sym == "sym")
2664  jcut = i;
2665  for (size_t j = 0; j < jcut; j++)
2666  {
2667  M(i, j) = M(j, i);
2668  }
2669  for (size_t j = jcut; j < n_cols; j++)
2670  {
2671  M(i, j) += qr_weight * scalar_product(f_B1, B2[j][iqn]);
2672  }
2673  }
2674  }
2675  return M;
2676  }
2677 
2679  template <typename T, typename U>
2681  const FType<U> &f,
2682  const BasisQuad<T> &B1,
2683  const BasisQuad<T> &B2,
2684  const QuadratureRule &qr,
2685  const std::string sym
2686  )
2687  {
2688  return compute_weighted_gram_matrix(f, B1, B2, qr, B1.shape()[0], B2.shape()[0], sym);
2689  }
2690 
2692  Eigen::MatrixXd compute_weighted_gram_matrix(
2693  const FType<VectorRd> &f,
2694  const BasisQuad<VectorRd> &B1,
2695  const BasisQuad<double> &B2,
2696  const QuadratureRule &qr,
2697  size_t n_rows = 0,
2698  size_t n_cols = 0
2699  );
2700 
2702  Eigen::MatrixXd compute_weighted_gram_matrix(
2703  const FType<VectorRd> &f,
2704  const BasisQuad<double> &B1,
2705  const BasisQuad<VectorRd> &B2,
2706  const QuadratureRule &qr,
2707  size_t n_rows = 0,
2708  size_t n_cols = 0
2709  );
2710 
2711  //------------------------------------------------------------------------------
2712  // L2 projection of a function
2713  //------------------------------------------------------------------------------
2714 
2716  template <typename BasisType>
2717  Eigen::VectorXd l2_projection(
2718  const std::function<typename BasisType::FunctionValue(const VectorRd &)> &f,
2719  const BasisType &basis,
2720  QuadratureRule &quad,
2721  const boost::multi_array<typename BasisType::FunctionValue, 2> &basis_quad,
2722  const Eigen::MatrixXd &mass_basis = Eigen::MatrixXd::Zero(1,1)
2723  )
2724  {
2725  Eigen::MatrixXd Mass = mass_basis;
2726  if (Mass.norm() < 1e-13){
2727  Mass = compute_gram_matrix(basis_quad, quad);
2728  }
2729  Eigen::LDLT<Eigen::MatrixXd> cholesky_mass(Mass);
2730  Eigen::VectorXd b = Eigen::VectorXd::Zero(basis.dimension());
2731  for (size_t i = 0; i < basis.dimension(); i++)
2732  {
2733  for (size_t iqn = 0; iqn < quad.size(); iqn++)
2734  {
2735  b(i) += quad[iqn].w * scalar_product(f(quad[iqn].vector()), basis_quad[i][iqn]);
2736  } // for iqn
2737  } // for i
2738  return cholesky_mass.solve(b);
2739  }
2740 
2741  //------------------------------------------------------------------------------
2742  // Decomposition on a polynomial basis
2743  //------------------------------------------------------------------------------
2744 
2746 
2751  template <typename BasisType>
2753  {
2755 
2761  const Face &F,
2762  const BasisType &basis
2763  ):
2764  m_dim(basis.dimension()),
2765  m_basis(basis),
2766  m_on_basis(basis, Eigen::MatrixXd::Identity(m_dim,m_dim)) // Need to initialise before we compute the real ON basis
2767  {
2768  /* The decomposition will be performed using an orthonormalised version of m_basis, for stability.
2769  The scalar product for which we orthonormalise is a minimal one (much less expensive than integrating
2770  over the face): \sum_i phi(x_i) psi(x_i) where (x_i)_i are nodes that are sufficient to determine
2771  entirely polynomials up to the considered degree.
2772  The nodes we build here correspond to P^k nodes on a triangle on a face (the triangle being centered
2773  at the face center) */
2774 
2775  // Create nodes
2776  std::vector<Eigen::Vector2i> indices = MonomialPowers<Face>::complete(basis.max_degree());
2777  VectorRd tF = F.edge(0)->tangent();
2778  VectorRd nF = F.edge_normal(0);
2779  VectorRd x0 = F.center_mass() - F.diam()*(tF+nF)/3.0;
2780 
2781  // Nodes
2782  m_nb_nodes = indices.size();
2783  m_nodes.reserve(m_nb_nodes);
2784  for (size_t i=0; i<m_nb_nodes; i++){
2785  VectorRd xi = x0 + F.diam()*(double(indices[i](0)) * tF + double(indices[i](1)) * nF)/std::max(1.,double(basis.max_degree()));
2786  m_nodes.emplace_back(xi.x(), xi.y(), xi.z(), 1.);
2787  }
2788 
2789  // We then orthonormalise Orthonormalise basis for simple scalar product
2790  m_on_basis_nodes.resize(boost::extents[m_dim][m_nb_nodes]);
2793  };
2794 
2797  const Cell &T,
2798  const BasisType &basis
2799  ):
2800  m_dim(basis.dimension()),
2801  m_basis(basis),
2802  m_on_basis(basis, Eigen::MatrixXd::Identity(m_dim,m_dim)) // Need to initialise before we compute the real ON basis
2803  {
2804  /* The decomposition will be performed using an orthonormalised version of m_basis, for stability.
2805  The scalar product for which we orthonormalise is a minimal one (much less expensive than integrating
2806  over the cell): \sum_i phi(x_i) psi(x_i) where (x_i)_i are nodes that are sufficient to determine
2807  entirely polynomials up to the considered degree.
2808  The nodes we build here correspond to P^k nodes on a tetrahedron */
2809 
2810  // Create nodes
2811  std::vector<Eigen::Vector3i> indices = MonomialPowers<Cell>::complete(basis.max_degree());
2812  VectorRd e0(1., 0., 0.);
2813  VectorRd e1(0., 1., 0.);
2814  VectorRd e2(0., 0., 1.);
2815  VectorRd xT = T.center_mass() - T.diam()*(e0+e1+e2)/3.0;
2816 
2817  // Nodes
2818  m_nb_nodes = indices.size();
2819  m_nodes.reserve(m_nb_nodes);
2820  for (size_t i=0; i<m_nb_nodes; i++){
2821  VectorRd xi = xT + T.diam()*(double(indices[i](0)) * e0 + double(indices[i](1)) * e1 + double(indices[i](2)) * e2)/std::max(1.,double(basis.max_degree()));
2822  m_nodes.emplace_back(xi.x(), xi.y(), xi.z(), 1.);
2823  }
2824 
2825  // We then orthonormalise Orthonormalise basis for simple scalar product
2826  m_on_basis_nodes.resize(boost::extents[m_dim][m_nb_nodes]);
2829  };
2830 
2832  inline QuadratureRule get_nodes() const
2833  {
2834  return m_nodes;
2835  };
2836 
2839  boost::multi_array<typename BasisType::FunctionValue, 2> &values
2840  )
2841  {
2842  // Gram matrix of the polynomials and the ON basis
2843  Eigen::MatrixXd Gram_P_onbasis = compute_gram_matrix(values, m_on_basis_nodes, m_nodes);
2844  // L=matrix of P as a family of the ON basis. In theory, Gram_onbasis is identity, but due to rounding errors it
2845  // can be a bit different. Computing L as if it's not the case improves stability
2846  Eigen::MatrixXd Gram_onbasis = compute_gram_matrix(m_on_basis_nodes, m_nodes);
2847  Eigen::MatrixXd L = Gram_onbasis.ldlt().solve(Gram_P_onbasis.transpose());
2848  return Family<BasisType>(m_basis, L.transpose() * m_on_basis.matrix());
2849  };
2850 
2851 
2852  // Member variables
2853  size_t m_dim; // dimension of basis
2854  BasisType m_basis; // Basis on which we decompose
2855  Family<BasisType> m_on_basis; // Orthonormalised basis (for simple scalar product)
2856  boost::multi_array<typename BasisType::FunctionValue, 2> m_on_basis_nodes; // Values of ON basis at the nodes
2857  size_t m_nb_nodes; // nb of nodes
2859 
2860  };
2861 
2862 
2863 
2865 
2866 } // end of namespace HArDCore3D
2867 
2868 #endif
Basis for the space of curls of polynomials.
Definition: basis.hpp:1290
Basis (or rather family) of divergence of an existing basis.
Definition: basis.hpp:1353
Family of functions expressed as linear combination of the functions of a given basis.
Definition: basis.hpp:388
Basis for the complement G^{c,k}(T) in P^k(T)^3 of the range of grad.
Definition: basis.hpp:1503
Basis for the complement G^{c,k}(F) in P^k(F)^2 of the range of the gradient on a face.
Definition: basis.hpp:1654
Basis for the space of gradients of polynomials.
Definition: basis.hpp:1228
Matrix family obtained from a scalar family.
Definition: basis.hpp:776
Scalar monomial basis on a cell.
Definition: basis.hpp:154
Scalar monomial basis on an edge.
Definition: basis.hpp:319
Scalar monomial basis on a face.
Definition: basis.hpp:225
Generate a basis restricted to the first "dimension" functions.
Definition: basis.hpp:1119
Basis for the complement R^{c,k}(T) in P^k(T)^3 of the range of curl.
Definition: basis.hpp:1432
Basis for the complement R^{c,k}(F) in P^k(F)^2 of the range of the vectorial rotational on a face.
Definition: basis.hpp:1580
Generate a basis where the function indices are shifted.
Definition: basis.hpp:1012
Vector family for polynomial functions that are tangent to a certain place (determined by the generat...
Definition: basis.hpp:920
Vector family obtained by tensorization of a scalar family.
Definition: basis.hpp:609
static boost::multi_array< typename detail::basis_evaluation_traits< MatrixFamily< BasisType, N >, BasisFunction >::ReturnValue, 2 > compute(const MatrixFamily< BasisType, N > &basis, const QuadratureRule &quad)
Evaluate a Matrix family at quadrature nodes (optimised compared the generic basis evaluation,...
Definition: basis.hpp:2265
Eigen::Matrix< double, dimspace, dimspace *dimspace > HessianValue
Definition: basis.hpp:1438
TensorizedVectorFamily< ScalarBasisType, N >::FunctionValue ReturnValue
Definition: basis.hpp:1952
void GradientValue
Definition: basis.hpp:1231
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition: basis.hpp:1201
double DivergenceValue
Definition: basis.hpp:1659
double DivergenceValue
Definition: basis.hpp:1508
VectorRd FunctionValue
Definition: basis.hpp:1434
Family< BasisType > l2_orthonormalize(const BasisType &basis, const QuadratureRule &qr, boost::multi_array< typename BasisType::FunctionValue, 2 > &basis_quad)
-orthonormalization: simply consists in using gram_schmidt() with the specific l2 inner product
Definition: basis.hpp:2403
const std::shared_ptr< RolyComplBasisFace > & rck() const
Return the Rck basis.
Definition: basis.hpp:1697
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:357
static const bool hasCurlCurl
Definition: basis.hpp:1307
VectorRd CurlValue
Definition: basis.hpp:1507
const Eigen::MatrixXd symmetriseOperator() const
Return the symmetrisation operator, the rN^2 square matrix that to a given vector of coefficients on ...
Definition: basis.hpp:881
Eigen::Matrix< double, dimspace, dimspace *dimspace > HessianValue
Definition: basis.hpp:1586
DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array< DivergenceValue, 2 > &ancestor_divergence_quad) const
Evaluate the divergence of the i-th function at a quadrature point iqn, knowing all the divergences o...
Definition: basis.hpp:519
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_hessian_quad)
Definition: basis.hpp:1911
static const bool hasGradient
Definition: basis.hpp:1241
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:930
static const bool hasHessian
Definition: basis.hpp:1519
size_t dimension() const
Return the dimension of the family.
Definition: basis.hpp:956
Eigen::Matrix< double, 2, dimspace > JacobianType
Definition: basis.hpp:1664
size_t dimension() const
Return the dimension of the basis.
Definition: basis.hpp:1045
static const bool hasCurl
Definition: basis.hpp:1446
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1442
double DivergenceValue
Definition: basis.hpp:159
const ScalarFamilyType & ancestor() const
Return the ancestor (family that has been tensorized)
Definition: basis.hpp:863
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:2023
VectorRd FunctionValue
Definition: basis.hpp:1582
constexpr const BasisType & ancestor() const
Return the ancestor.
Definition: basis.hpp:564
MatrixRd HessianValue
Definition: basis.hpp:160
VectorRd FunctionValue
Definition: basis.hpp:922
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, size_t iqn, const boost::multi_array< double, 2 > &ancestor_basis_quad)
Definition: basis.hpp:2133
static const bool hasHessian
Definition: basis.hpp:1028
TensorizedVectorFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition: basis.hpp:1984
static const bool hasDivergence
Definition: basis.hpp:1671
static const bool hasHessian
Definition: basis.hpp:1598
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1022
void CurlValue
Definition: basis.hpp:780
VectorRd CurlValue
Definition: basis.hpp:229
Eigen::Matrix< double, dimspace, dimspace *dimspace > HessianValue
Definition: basis.hpp:1660
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_basis_quad)
Definition: basis.hpp:2165
BasisType::FunctionValue FunctionValue
Definition: basis.hpp:1121
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the two-dimensional curl of the i-th basis function at point x.
Definition: basis.cpp:91
static boost::multi_array< typename detail::basis_evaluation_traits< BasisType, BasisFunction >::ReturnValue, 2 > compute(const BasisType &basis, const QuadratureRule &quad)
Generic basis evaluation.
Definition: basis.hpp:2189
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:1835
Face GeometricSupport
Definition: basis.hpp:928
static const bool hasHessian
Definition: basis.hpp:1448
static const bool hasGradient
Definition: basis.hpp:332
static const bool hasCurlCurl
Definition: basis.hpp:1136
size_t dimPkmo() const
Returns the dimension of P^{k-1}(R^3)
Definition: basis.hpp:1553
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, size_t iqn, const boost::multi_array< MatrixRd, 2 > &ancestor_basis_quad)
Definition: basis.hpp:2099
static boost::multi_array< typename detail::basis_evaluation_traits< TensorizedVectorFamily< BasisType, N >, BasisFunction >::ReturnValue, 2 > compute(const TensorizedVectorFamily< BasisType, N > &basis, const QuadratureRule &quad)
Evaluate a tensorized family at quadrature nodes (optimised compared the generic basis evaluation,...
Definition: basis.hpp:2240
BasisType::DivergenceValue ReturnValue
Definition: basis.hpp:1879
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition: basis.hpp:1077
size_t dimension() const
Return the dimension of the family.
Definition: basis.hpp:640
constexpr static const bool hasAncestor
Definition: basis.hpp:1239
boost::multi_array< T, 2 > BasisQuad
type for bases evaluated on quadrature nodes
Definition: basis.hpp:60
static const bool hasDivergence
Definition: basis.hpp:334
constexpr int dimspace
Dimension, and generic types for vector in correct dimension (makes it easier to translate a code bet...
Definition: basis.hpp:50
static std::vector< Eigen::Vector2i > homogeneous(const size_t L)
Definition: basis.hpp:118
static const bool hasGradient
Definition: basis.hpp:933
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition: basis.cpp:81
BasisType AncestorType
Definition: basis.hpp:1138
static std::function< Eigen::MatrixXd(const Eigen::MatrixXd &)> symmetrise_matrix
Function to symmetrise a matrix (useful together with transform_values_quad)
Definition: basis.hpp:1766
static const bool hasHessian
Definition: basis.hpp:1306
DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_gradient_quad) const
Evaluate the divergence of the i-th basis function at a quadrature point iqn, knowing all the gradien...
Definition: basis.hpp:854
const VectorRd & normal() const
Return the normal to the face used in the computation of the curl.
Definition: basis.hpp:277
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:1470
VectorRd CurlValue
Definition: basis.hpp:613
void GradientValue
Definition: basis.hpp:1356
Eigen::Matrix< double, dimspace, dimspace *dimspace > HessianValue
Definition: basis.hpp:1509
BasisType::FunctionValue FunctionValue
Definition: basis.hpp:390
CurlValue curlcurl(size_t i, size_t iqn, const boost::multi_array< typename ScalarFamilyType::HessianValue, 2 > &ancestor_hessian_quad) const
Evaluate the curl curl of the i-th basis function at a quadrature point iqn, knowing all the values o...
Definition: basis.hpp:734
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition: basis.hpp:686
static const bool hasDivergence
Definition: basis.hpp:1368
TensorizedVectorFamily(const ScalarFamilyType &scalar_family)
Definition: basis.hpp:632
static const bool hasFunction
Definition: basis.hpp:331
constexpr const ScalarFamilyType & ancestor() const
Return the ancestor (family that has been tensorized)
Definition: basis.hpp:747
const Eigen::MatrixXd transposeOperator() const
Return the transpose operator, the rN^2 square matrix that to a given vector of coefficients on the M...
Definition: basis.hpp:875
constexpr static const bool hasAncestor
Definition: basis.hpp:1301
static const bool hasDivergence
Definition: basis.hpp:169
double DivergenceValue
Definition: basis.hpp:230
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition: basis.hpp:1436
ScalarFamilyType AncestorType
Definition: basis.hpp:939
BasisType::GeometricSupport GeometricSupport
Definition: basis.hpp:1298
static const bool hasFunction
Definition: basis.hpp:1594
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition: basis.hpp:1335
double DivergenceValue
Definition: basis.hpp:614
static const bool hasCurlCurl
Definition: basis.hpp:171
VectorZd powers(size_t i) const
Returns the powers of the i-th basis function (its degree can be found using powers(i)....
Definition: basis.hpp:201
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:329
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1592
static const bool hasCurl
Definition: basis.hpp:333
static const bool hasDivergence
Definition: basis.hpp:1243
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:1529
BasisType::DivergenceValue FunctionValue
Definition: basis.hpp:1355
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1129
static const bool hasGradient
Definition: basis.hpp:401
size_t dimension() const
Dimension of the basis.
Definition: basis.hpp:253
static const bool hasGradient
Definition: basis.hpp:1303
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition: basis.hpp:1398
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1363
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition: basis.hpp:666
static const bool hasHessian
Definition: basis.hpp:1135
static const bool hasCurlCurl
Definition: basis.hpp:628
VectorRd GradientValue
Definition: basis.hpp:228
static const bool hasCurl
Definition: basis.hpp:1596
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:1063
Family< TensorizedVectorFamily< ScalarBasisType, N > > GenericTensorization(const ScalarBasisType &B, const std::vector< Eigen::VectorXd > &v)
From a scalar family B=(B_1..B_r) and vectors (v_1..v_k) in R^N, constructs a "Family" of "Tensorized...
Definition: basis.hpp:1739
constexpr static const bool hasAncestor
Definition: basis.hpp:330
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition: basis.hpp:829
DecomposePoly(const Face &F, const BasisType &basis)
Constructor for face.
Definition: basis.hpp:2760
double scalar_product(const double &x, const double &y)
Scalar product between two reals.
Definition: basis.cpp:308
DivergenceBasis< TangentFamily< ScalarFamilyType > > ScalarRotFamily(const TangentFamily< ScalarFamilyType > &tangent_family, const Face &F)
The following function creates the "scalar rot" basis of a TangentFamily on a face.
Definition: basis.hpp:1412
VectorRd GradientValue
Definition: basis.hpp:923
static const bool hasFunction
Definition: basis.hpp:1444
static const bool hasCurl
Definition: basis.hpp:168
CurlValue curlcurl(size_t i, const VectorRd &x) const
Evaluate the curl curl of the i-th basis function at point x.
Definition: basis.hpp:974
Face GeometricSupport
Definition: basis.hpp:233
RolyComplBasisFace(const Face &F, size_t degree)
Constructor.
Definition: basis.cpp:251
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1666
Eigen::Matrix< double, N, 1 > DivergenceValue
Definition: basis.hpp:781
VectorRd CurlValue
Definition: basis.hpp:158
std::function< T(const VectorRd &, const Cell *)> CellFType
type for function of point. T is the return type of the function
Definition: basis.hpp:57
static const bool hasHessian
Definition: basis.hpp:627
Eigen::MatrixXd gram_schmidt(boost::multi_array< T, 2 > &basis_eval, const std::function< double(size_t, size_t)> &inner_product)
Definition: basis.hpp:2303
BasisType::HessianValue ReturnValue
Definition: basis.hpp:1903
static const bool hasFunction
Definition: basis.hpp:1515
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition: basis.hpp:1294
VectorRd CurlValue
Definition: basis.hpp:323
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition: basis.hpp:1293
BasisType::CurlValue CurlValue
Definition: basis.hpp:1123
Eigen::Matrix< double, N, 1 > FunctionValue
Definition: basis.hpp:611
static const bool hasDivergence
Definition: basis.hpp:1305
static std::vector< VectorZd > complete(const size_t degree)
Definition: basis.hpp:99
std::function< T(const VectorRd &)> FType
type for function of point. T is the return type of the function
Definition: basis.hpp:54
MonomialScalarBasisEdge(const Edge &E, size_t degree)
Constructor.
Definition: basis.cpp:113
BasisType::HessianValue HessianValue
Definition: basis.hpp:1018
double DivergenceValue
Definition: basis.hpp:1295
BasisType::HessianValue HessianValue
Definition: basis.hpp:394
CurlValue curl(size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_gradient_quad) const
Evaluate the curl of the i-th basis function at a quadrature point iqn, knowing all the gradients of ...
Definition: basis.hpp:696
VectorZd powers(size_t i) const
Returns the powers of the i-th basis function (not including the vector part)
Definition: basis.hpp:1547
const JacobianType coordinates_system() const
Return the system of coordinates (basis in rows) on the face.
Definition: basis.hpp:289
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:2089
void DivergenceValue
Definition: basis.hpp:1358
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:753
Eigen::VectorXd l2_projection(const std::function< typename BasisType::FunctionValue(const VectorRd &)> &f, const BasisType &basis, QuadratureRule &quad, const boost::multi_array< typename BasisType::FunctionValue, 2 > &basis_quad, const Eigen::MatrixXd &mass_basis=Eigen::MatrixXd::Zero(1, 1))
Compute the L2-projection of a function.
Definition: basis.hpp:2717
MatrixFamily(const ScalarFamilyType &scalar_family)
Definition: basis.hpp:797
static const bool hasGradient
Definition: basis.hpp:1132
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition: basis.hpp:1093
double DivergenceValue
Definition: basis.hpp:1585
constexpr const ScalarFamilyType & ancestor() const
Return the ancestor (family used for the tangent)
Definition: basis.hpp:982
BasisType::GeometricSupport GeometricSupport
Definition: basis.hpp:1020
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition: basis.hpp:1193
Eigen::VectorXd integrate(const FType< T > &f, const BasisQuad< T > &B, const QuadratureRule &qr, size_t n_rows=0)
Computes the vector of integrals (f, phi_i)
Definition: basis.hpp:2591
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:619
static const bool hasCurl
Definition: basis.hpp:402
static const bool hasGradient
Definition: basis.hpp:1366
size_t dimension() const
Dimension of the basis.
Definition: basis.hpp:1682
boost::multi_array< typename BasisType::FunctionValue, 2 > m_on_basis_nodes
Definition: basis.hpp:2856
double DivergenceValue
Definition: basis.hpp:1437
constexpr static const bool hasAncestor
Definition: basis.hpp:238
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:1905
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:2123
VectorRd GradientValue
Definition: basis.hpp:322
static const bool hasGradient
Definition: basis.hpp:1445
VectorZd powers(size_t i) const
Returns the powers of the i-th basis function (not including the vector part)
Definition: basis.hpp:1476
static const bool hasCurlCurl
Definition: basis.hpp:405
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the Hessian of the i-th basis function at point x.
Definition: basis.cpp:96
double FunctionValue
Definition: basis.hpp:227
BasisType::GeometricSupport GeometricSupport
Definition: basis.hpp:1361
static const bool hasCurlCurl
Definition: basis.hpp:937
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition: basis.hpp:1583
ScalarFamilyType AncestorType
Definition: basis.hpp:630
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:237
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition: basis.hpp:1584
GradientValue gradient(size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_gradient_quad) const
Evaluate the gradient of the i-th basis function at a quadrature point iqn, knowing all the gradients...
Definition: basis.hpp:676
BasisType::HessianValue HessianValue
Definition: basis.hpp:1125
static const bool hasHessian
Definition: basis.hpp:1672
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition: basis.hpp:968
static const bool hasFunction
Definition: basis.hpp:788
BasisFunctionE
Definition: basis.hpp:1713
constexpr static const bool hasAncestor
Definition: basis.hpp:1364
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition: basis.hpp:706
constexpr static const bool hasAncestor
Definition: basis.hpp:1667
static const bool hasFunction
Definition: basis.hpp:1365
BasisType AncestorType
Definition: basis.hpp:1309
static const bool hasGradient
Definition: basis.hpp:1025
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:2155
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:1991
VectorRd FunctionValue
Definition: basis.hpp:1292
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th function at point x.
Definition: basis.hpp:454
double FunctionValue
Definition: basis.hpp:156
BasisType::GradientValue GradientValue
Definition: basis.hpp:1122
VectorRd FunctionValue
Definition: basis.hpp:1505
static const bool hasFunction
Definition: basis.hpp:239
BasisType m_basis
Definition: basis.hpp:2854
boost::multi_array< VectorRd, 2 > vector_product(const boost::multi_array< VectorRd, 2 > &basis_quad, const VectorRd &v)
Compute the vector (cross) product between the evaluation of a basis and a constant vector.
Definition: basis.cpp:324
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:1858
static const bool hasDivergence
Definition: basis.hpp:1447
static const bool hasCurlCurl
Definition: basis.hpp:1245
DivergenceBasis(const BasisType &basis)
Constructor.
Definition: basis.hpp:1375
TensorRankE
Definition: basis.hpp:63
static const bool hasCurlCurl
Definition: basis.hpp:1599
VectorRd CurlValue
Definition: basis.hpp:924
static const bool hasFunction
Definition: basis.hpp:1668
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1300
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition: basis.hpp:845
static const bool hasCurl
Definition: basis.hpp:1517
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition: basis.hpp:1273
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th function at point x.
Definition: basis.hpp:506
Eigen::Matrix< double, N, dimspace > GradientValue
Definition: basis.hpp:612
CurlValue curlcurl(size_t i, const VectorRd &x) const
Evaluate the curl curl of the i-th basis function at point x. We use the formula curl curl = - Laplac...
Definition: basis.hpp:722
MonomialScalarBasisCell(const Cell &T, size_t degree)
Constructor.
Definition: basis.cpp:12
void CurlValue
Definition: basis.hpp:1357
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_basis_quad)
Definition: basis.hpp:2001
CurlValue curl(size_t i, size_t iqn, const boost::multi_array< CurlValue, 2 > &ancestor_curl_quad) const
Evaluate the curl of the i-th function at a quadrature point iqn, knowing all the curls of ancestor b...
Definition: basis.hpp:493
double DivergenceValue
Definition: basis.hpp:324
BasisType::DivergenceValue DivergenceValue
Definition: basis.hpp:393
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:1929
Eigen::Matrix2d HessianValue
Definition: basis.hpp:926
BasisType::CurlValue ReturnValue
Definition: basis.hpp:1856
Family< BasisType > m_on_basis
Definition: basis.hpp:2855
const VectorRd & normal() const
Return the normal to the face used in the computation of the curl.
Definition: basis.hpp:1691
boost::multi_array< outValue, 2 > transform_values_quad(const boost::multi_array< inValue, 2 > &B_quad, const FunctionType &F)
Takes an array B_quad of values at quadrature nodes and applies the function F to all of them....
Definition: basis.hpp:1724
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:1458
constexpr static const bool hasAncestor
Definition: basis.hpp:1514
BasisType::GeometricSupport GeometricSupport
Definition: basis.hpp:1127
QuadratureRule get_nodes() const
Return the set of nodes (useful to compute value of polynomial to decompose via evaluate_quad)
Definition: basis.hpp:2832
RolyComplBasisCell(const Cell &T, size_t degree)
Constructor.
Definition: basis.cpp:137
static const bool hasCurlCurl
Definition: basis.hpp:1449
constexpr const BasisType & ancestor() const
Return the underlying complete basis.
Definition: basis.hpp:1160
static const bool hasCurl
Definition: basis.hpp:241
constexpr static const bool hasAncestor
Definition: basis.hpp:931
BasisType::CurlValue ReturnValue
Definition: basis.hpp:1927
void CurlValue
Definition: basis.hpp:1232
constexpr static const bool hasAncestor
Definition: basis.hpp:1130
static const bool hasFunction
Definition: basis.hpp:621
Eigen::Matrix< double, 2, dimspace > JacobianType
Definition: basis.hpp:1590
Eigen::Vector2i powers(size_t i) const
Returns the powers of the i-th basis function.
Definition: basis.hpp:1632
BasisType::GeometricSupport GeometricSupport
Definition: basis.hpp:396
size_t dimension() const
Dimension of the basis.
Definition: basis.hpp:345
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition: basis.cpp:229
double FunctionValue
Definition: basis.hpp:321
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_value_quad)
Definition: basis.hpp:1817
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_divergence_quad)
Definition: basis.hpp:1887
Family(const BasisType &basis, const Eigen::MatrixXd &matrix)
Constructor.
Definition: basis.hpp:410
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1513
static boost::multi_array< typename detail::basis_evaluation_traits< Family< BasisType >, BasisFunction >::ReturnValue, 2 > compute(const Family< BasisType > &basis, const QuadratureRule &quad)
Evaluate a 'Family' of functions at quadrature nodes (optimised compared the generic basis evaluation...
Definition: basis.hpp:2213
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition: basis.cpp:278
static const bool hasGradient
Definition: basis.hpp:1595
void DivergenceValue
Definition: basis.hpp:1233
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, size_t iqn, const boost::multi_array< double, 2 > &ancestor_basis_quad)
Definition: basis.hpp:1969
static const bool hasFunction
Definition: basis.hpp:1302
BasisType::GradientValue GradientValue
Definition: basis.hpp:391
void HessianValue
Definition: basis.hpp:1359
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:2056
size_t dimension() const
Dimension of the family. This is actually the number of functions in the family, not necessarily line...
Definition: basis.hpp:421
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:195
void HessianValue
Definition: basis.hpp:615
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:180
constexpr static const bool hasAncestor
Definition: basis.hpp:787
const JacobianType & jacobian() const
Return the Jacobian of the coordinate system transformation.
Definition: basis.hpp:283
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_gradient_quad)
Definition: basis.hpp:1841
const size_t matrixSize() const
Return the dimension of the matrices in the family.
Definition: basis.hpp:869
Family< BasisType > family(boost::multi_array< typename BasisType::FunctionValue, 2 > &values)
Returns the decomposed polynomials as a Family of the provided basis.
Definition: basis.hpp:2838
static const bool hasGradient
Definition: basis.hpp:167
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the hessian of the i-th basis function at point x.
Definition: basis.cpp:40
static const bool hasCurl
Definition: basis.hpp:791
static const bool hasDivergence
Definition: basis.hpp:1518
BasisType AncestorType
Definition: basis.hpp:1247
ScalarFamilyType::GeometricSupport GeometricSupport
Definition: basis.hpp:784
const JacobianType & jacobian() const
Return the Jacobian of the coordinate system transformation.
Definition: basis.hpp:1620
DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_gradient_quad) const
Evaluate the divergence of the i-th basis function at a quadrature point iqn, knowing all the gradien...
Definition: basis.hpp:714
static const bool hasFunction
Definition: basis.hpp:400
size_t m_dim
Definition: basis.hpp:2849
static const bool hasCurl
Definition: basis.hpp:1242
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:164
BasisType::DivergenceValue DivergenceValue
Definition: basis.hpp:1124
static const bool hasGradient
Definition: basis.hpp:789
Eigen::Matrix< double, 2, dimspace > generators() const
Returns the generators of the basis functions.
Definition: basis.hpp:994
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition: basis.hpp:1435
constexpr static const bool hasAncestor
Definition: basis.hpp:399
static const bool hasCurl
Definition: basis.hpp:1304
Eigen::Matrix3d MatrixRd
Definition: basis.hpp:51
static std::vector< Eigen::Vector2i > complete(size_t degree)
Definition: basis.hpp:130
BasisType::GradientValue FunctionValue
Definition: basis.hpp:1230
static const bool hasHessian
Definition: basis.hpp:170
static const bool hasDivergence
Definition: basis.hpp:1027
static const bool hasDivergence
Definition: basis.hpp:242
static const bool hasGradient
Definition: basis.hpp:1669
Eigen::Vector2i powers(size_t i) const
Returns the powers of the i-th basis function (its degree can be found using powers(i)....
Definition: basis.hpp:295
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:1261
static const bool hasHessian
Definition: basis.hpp:936
constexpr static const bool hasAncestor
Definition: basis.hpp:165
constexpr const BasisType & ancestor() const
Return the underlying complete basis.
Definition: basis.hpp:1057
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:271
static const bool hasCurl
Definition: basis.hpp:1133
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition: basis.hpp:646
static const bool hasFunction
Definition: basis.hpp:1024
size_t m_nb_nodes
Definition: basis.hpp:2857
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:1541
Family< MatrixFamily< ScalarBasisType, N > > IsotropicMatrixFamily(const ScalarBasisType &B)
From a scalar family B, constructs a "Family" of "MatrixFamily" (built on B, of size NxN) that repres...
Definition: basis.hpp:1775
void GradientValue
Definition: basis.hpp:779
static const bool hasCurl
Definition: basis.hpp:626
Edge GeometricSupport
Definition: basis.hpp:327
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_curlcurl_quad)
Definition: basis.hpp:1935
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition: basis.hpp:1506
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:570
TensorizedVectorFamily< ScalarBasisType, N >::DivergenceValue ReturnValue
Definition: basis.hpp:2049
VectorRd GradientValue
Definition: basis.hpp:157
static const bool hasFunction
Definition: basis.hpp:1131
static const bool hasFunction
Definition: basis.hpp:1240
ScalarFamilyType::GeometricSupport GeometricSupport
Definition: basis.hpp:617
size_t dimension() const
Dimension of the basis.
Definition: basis.hpp:1608
static const bool hasDivergence
Definition: basis.hpp:403
RestrictedBasis(const BasisType &basis, const size_t &dimension)
Constructor.
Definition: basis.hpp:1141
TensorizedVectorFamily< ScalarBasisType, N >::CurlValue ReturnValue
Definition: basis.hpp:2082
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the hessian of the i-th function at point x.
Definition: basis.hpp:532
static const bool hasFunction
Definition: basis.hpp:166
size_t shift() const
Return the shift.
Definition: basis.hpp:1051
Eigen::Matrix< double, dimspace, dimspace *dimspace > HessianValue
Definition: basis.hpp:1296
BasisType::DivergenceValue DivergenceValue
Definition: basis.hpp:1017
static const bool hasDivergence
Definition: basis.hpp:935
static const bool hasCurl
Definition: basis.hpp:1670
Eigen::MatrixXd compute_weighted_gram_matrix(const FType< VectorRd > &f, const BasisQuad< VectorRd > &B1, const BasisQuad< double > &B2, const QuadratureRule &qr, size_t n_rows, size_t n_cols)
Computes the Gram-like matrix of integrals (f dot phi_i, phi_j)
Definition: basis.cpp:477
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the hessian of the i-th basis function at point x.
Definition: basis.hpp:1101
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:1238
BasisType::GradientValue GradientValue
Definition: basis.hpp:1015
static const bool hasGradient
Definition: basis.hpp:240
static const bool hasCurl
Definition: basis.hpp:934
DecomposePoly(const Cell &T, const BasisType &basis)
Constructor for cell.
Definition: basis.hpp:2796
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:398
static const bool hasDivergence
Definition: basis.hpp:1597
static const bool hasFunction
Definition: basis.hpp:932
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_curl_quad)
Definition: basis.hpp:1864
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition: basis.hpp:1657
static const bool hasHessian
Definition: basis.hpp:404
static std::vector< VectorZd > homogeneous(const size_t L)
Definition: basis.hpp:84
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:988
static const bool hasHessian
Definition: basis.hpp:335
BasisType AncestorType
Definition: basis.hpp:407
MonomialScalarBasisFace(const Face &F, size_t degree)
Constructor.
Definition: basis.cpp:60
static const bool hasHessian
Definition: basis.hpp:792
static const bool hasGradient
Definition: basis.hpp:622
static const bool hasCurlCurl
Definition: basis.hpp:336
Face GeometricSupport
Definition: basis.hpp:1588
static const bool hasCurlCurl
Definition: basis.hpp:244
BasisType::FunctionValue ReturnValue
Definition: basis.hpp:1809
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_basis_quad)
Definition: basis.hpp:2033
constexpr static const bool hasAncestor
Definition: basis.hpp:620
BasisType::GeometricSupport GeometricSupport
Definition: basis.hpp:1236
constexpr static const TensorRankE tensorRank
Definition: basis.hpp:786
static const bool hasGradient
Definition: basis.hpp:1516
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition: basis.hpp:1085
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:1959
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:1386
TangentFamily(const ScalarFamilyType &scalar_family, const Eigen::Matrix< double, 2, dimspace > &generators)
Constructor.
Definition: basis.hpp:942
BasisType::FunctionValue FunctionValue
Definition: basis.hpp:1014
static const bool hasDivergence
Definition: basis.hpp:790
BasisType AncestorType
Definition: basis.hpp:1372
static const bool hasCurlCurl
Definition: basis.hpp:1029
void HessianValue
Definition: basis.hpp:782
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition: basis.cpp:127
BasisType AncestorType
Definition: basis.hpp:1031
GradientValue gradient(size_t i, size_t iqn, const boost::multi_array< GradientValue, 2 > &ancestor_gradient_quad) const
Evaluate the gradient of the i-th function at a quadrature point iqn, knowing all the gradients of an...
Definition: basis.hpp:467
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition: basis.hpp:1185
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the hessian of the i-th basis function at point x.
Definition: basis.hpp:1209
static const bool hasCurlCurl
Definition: basis.hpp:1673
MatrixFamily< ScalarBasisType, N >::FunctionValue ReturnValue
Definition: basis.hpp:2116
HessianValue hessian(size_t i, size_t iqn, const boost::multi_array< HessianValue, 2 > &ancestor_hessian_quad) const
Evaluate the hessian of the i-th function at a quadrature point iqn, knowing all the hessian of ances...
Definition: basis.hpp:545
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition: basis.hpp:1658
ScalarFamilyType AncestorType
Definition: basis.hpp:795
TensorizedVectorFamily< ScalarBasisType, N >::CurlValue ReturnValue
Definition: basis.hpp:2016
static const bool hasCurl
Definition: basis.hpp:1026
Eigen::Matrix< double, N, N > FunctionValue
Definition: basis.hpp:778
GolyComplBasisCell(const Cell &T, size_t degree)
Constructor.
Definition: basis.cpp:170
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition: basis.cpp:158
ShiftedBasis(const BasisType &basis, const int shift)
Constructor.
Definition: basis.hpp:1034
static const bool hasCurl
Definition: basis.hpp:1367
static const bool hasCurlCurl
Definition: basis.hpp:793
BasisType::CurlValue CurlValue
Definition: basis.hpp:392
BasisType::GradientValue ReturnValue
Definition: basis.hpp:1833
BasisType::CurlValue CurlValue
Definition: basis.hpp:1016
static std::function< Eigen::MatrixXd(const Eigen::MatrixXd &)> skew_symmetrise_matrix
Function to skew-symmetrise a matrix (useful together with transform_values_quad)
Definition: basis.hpp:1770
CurlBasis(const BasisType &basis)
Constructor.
Definition: basis.hpp:1312
static const bool hasHessian
Definition: basis.hpp:1369
const Eigen::MatrixXd & matrix() const
Return the coefficient matrix.
Definition: basis.hpp:558
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:1626
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_basis_quad)
Definition: basis.hpp:2066
Cell GeometricSupport
Definition: basis.hpp:162
size_t dimension() const
Return the dimension of the basis.
Definition: basis.hpp:1154
GradientBasis(const BasisType &basis)
Constructor.
Definition: basis.hpp:1250
constexpr static const bool hasAncestor
Definition: basis.hpp:1593
void HessianValue
Definition: basis.hpp:1234
constexpr static const bool hasAncestor
Definition: basis.hpp:1023
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:1323
static const bool hasHessian
Definition: basis.hpp:243
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th function at point x.
Definition: basis.hpp:480
static const bool hasDivergence
Definition: basis.hpp:1134
Eigen::MatrixXd compute_gram_matrix(const boost::multi_array< VectorRd, 2 > &B1, const boost::multi_array< double, 2 > &B2, const QuadratureRule &qr)
Compute the Gram-like matrix given a family of vector-valued and one of scalar-valued functions by te...
Definition: basis.cpp:339
Face GeometricSupport
Definition: basis.hpp:1662
Cell GeometricSupport
Definition: basis.hpp:1440
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:1811
static const bool hasDivergence
Definition: basis.hpp:625
QuadratureRule m_nodes
Nodes for the interpolation.
Definition: basis.hpp:2858
MatrixRd HessianValue
Definition: basis.hpp:231
static const bool hasCurlCurl
Definition: basis.hpp:1370
double DivergenceValue
Definition: basis.hpp:925
GolyComplBasisFace(const Face &F, size_t degree)
Constructor.
Definition: basis.cpp:290
double HessianValue
Definition: basis.hpp:325
static const bool hasHessian
Definition: basis.hpp:1244
size_t dimension() const
Return the dimension of the family.
Definition: basis.hpp:823
const Eigen::MatrixXd symmetricBasis() const
Returns the matrix that can be used, in a Family of this MatrixBasis, to create a basis of the subspa...
Definition: basis.hpp:887
VectorRd FunctionValue
Definition: basis.hpp:1656
Cell GeometricSupport
Definition: basis.hpp:1511
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition: basis.hpp:1881
static const bool hasCurlCurl
Definition: basis.hpp:1520
Eigen::Matrix< double, 2, dimspace > JacobianType
Definition: basis.hpp:235
constexpr static const bool hasAncestor
Definition: basis.hpp:1443
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition: basis.cpp:29
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:1166
MatrixFamily< ScalarBasisType, N >::DivergenceValue ReturnValue
Definition: basis.hpp:2148
@ CurlCurl
Definition: basis.hpp:1719
@ Function
Definition: basis.hpp:1714
@ Hessian
Definition: basis.hpp:1718
@ Gradient
Definition: basis.hpp:1715
@ Divergence
Definition: basis.hpp:1717
@ Curl
Definition: basis.hpp:1716
@ Matrix
Definition: basis.hpp:66
@ Vector
Definition: basis.hpp:65
@ Scalar
Definition: basis.hpp:64
size_t L
Definition: HHO_DiffAdvecReac.hpp:46
std::vector< QuadratureNode > QuadratureRule
Definition: quadraturerule.hpp:61
Definition: ddr-magnetostatics.hpp:40
MeshND::VectorZd< 2 > VectorZd
Definition: Mesh2D.hpp:15
MeshND::VectorRd< 2 > VectorRd
Definition: Mesh2D.hpp:14
MeshND::Edge< 2 > Edge
Definition: Mesh2D.hpp:11
MeshND::Face< 2 > Face
Definition: Mesh2D.hpp:12
MeshND::Cell< 2 > Cell
Definition: Mesh2D.hpp:13
Structure to decompose a set of polynomials on a basis on a face or a cell.
Definition: basis.hpp:2753
Compute vectors listing the powers of monomial basis functions (for a cell or face,...
Definition: basis.hpp:76
Basis dimensions for various polynomial spaces on edges/faces/elements (when relevant): Pk,...
Definition: polynomialspacedimension.hpp:54
Basis evaluation traits. Only specialization of 'BasisFunction' (=Function, Gradient,...
Definition: basis.hpp:1802
Evaluate a basis at quadrature nodes. 'BasisFunction' (=Function, Gradient, Curl, Divergence or Hessi...
Definition: basis.hpp:2185