HArD::Core2D
Hybrid Arbitrary Degree::Core 2D - Library to implement 2D schemes with edge and cell polynomials as unknowns
Loading...
Searching...
No Matches
basis.hpp
Go to the documentation of this file.
1// Core data structures and methods for 2D schemes based on polynomial unknowns in the elements and on the edges
2//
3// Provides:
4// - Full and partial polynomial spaces on the element and edges
5// - Generic routines to create quadrature nodes over cells and edges 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 *
13 * This library was developed around HHO methods, although some parts of it have a more
14 * general purpose. If you use this code or part of it in a scientific publication,
15 * please mention the following book as a reference for the underlying principles
16 * of HHO schemes:
17 *
18 * The Hybrid High-Order Method for Polytopal Meshes: Design, Analysis, and Applications.
19 * D. A. Di Pietro and J. Droniou. Modeling, Simulation and Applications, vol. 19.
20 * Springer International Publishing, 2020, xxxi + 525p. doi: 10.1007/978-3-030-37203-3.
21 * url: https://hal.archives-ouvertes.fr/hal-02151813.
22 *
23 */
24
25#ifndef BASIS_HPP
26#define BASIS_HPP
27
28#include <boost/multi_array.hpp>
29
30#include <mesh.hpp>
31//#include <edge.hpp>
32#include <iostream>
33
35
36#include <quadraturerule.hpp>
37
38namespace HArDCore2D
39{
40
53 constexpr int dimspace = 2;
54 typedef Eigen::Matrix2d MatrixRd;
55 typedef Eigen::Vector2d VectorRd;
56 typedef Eigen::Vector2i VectorZd;
57
58 static const std::vector<VectorRd> basisRd = { VectorRd(1., 0.), VectorRd(0., 1.) };
59
60 template <typename T>
61 using BasisQuad = boost::multi_array<T, 2>;
62
63 template <typename T>
64 using FType = std::function<T(const VectorRd &)>;
65
67 {
68 Scalar = 0,
69 Vector = 1,
70 Matrix = 2
71 };
72
73
74 //-----------------------------------------------------------------------------
75 // Powers of monomial basis
76 //-----------------------------------------------------------------------------
77
79 template<typename GeometricSupport>
81 {
82 // Only specializations are relevant
83 };
84
85 template<>
86 struct MonomialPowers<Cell>
87 {
88 static std::vector<VectorZd> complete(size_t degree)
89 {
90 std::vector<VectorZd> powers;
91 powers.reserve( PolynomialSpaceDimension<Cell>::Poly(degree) );
92 for (size_t l = 0; l <= degree; l++)
93 {
94 for (size_t i = 0; i <= l; i++)
95 {
96 powers.push_back(VectorZd(i, l - i));
97 } // for i
98 } // for l
99
100 return powers;
101 }
102 };
103
104 //----------------------------------------------------------------------
105 //----------------------------------------------------------------------
106 // STRUCTURE FOR GRADIENT OF MATRIX-VALUED FUNCTIONS
107 //----------------------------------------------------------------------
108 //----------------------------------------------------------------------
109
111 template<size_t N>
113 {
116 Eigen::Matrix<double, N, N> diff_x,
117 Eigen::Matrix<double, N, N> diff_y
118 ) : dx(diff_x),
119 dy(diff_y)
120 {
121 // do nothing
122 }
123
125 MatrixGradient() : dx(Eigen::Matrix<double, N, N>::Zero()),
126 dy(Eigen::Matrix<double, N, N>::Zero())
127 {
128 // do nothing
129 }
130
133 return MatrixGradient<N>(dx + G.dx, dy + G.dy);
134 }
135
138 this->dx += G.dx;
139 this->dy += G.dy;
140 return *this;
141 }
142
145 return MatrixGradient<N>(dx - G.dx, dy - G.dy);
146 }
147
148 // Directional derivatives
149 Eigen::Matrix<double, N, N> dx;
150 Eigen::Matrix<double, N, N> dy;
151
152 };
153
155 template <size_t N>
157 return MatrixGradient<N>(scalar * G.dx, scalar * G.dy);
158 };
159
160 //----------------------------------------------------------------------
161 //----------------------------------------------------------------------
162 // SCALAR MONOMIAL BASIS
163 //----------------------------------------------------------------------
164 //----------------------------------------------------------------------
165
168 {
169 public:
170 typedef double FunctionValue;
173 typedef void DivergenceValue;
174 typedef void RotorValue;
176
177 typedef Cell GeometricSupport;
178
179 constexpr static const TensorRankE tensorRank = Scalar;
180 constexpr static const bool hasAncestor = false;
181 static const bool hasFunction = true;
182 static const bool hasGradient = true;
183 static const bool hasCurl = true;
184 static const bool hasDivergence = false;
185 static const bool hasRotor = false;
186 static const bool hasHessian = true;
187
190 const Cell &T,
191 size_t degree
192 );
193
195 inline size_t dimension() const
196 {
197 return ( m_degree >= 0 ? (m_degree + 1) * (m_degree + 2) / 2 : 0);
198 }
199
201 FunctionValue function(size_t i, const VectorRd & x) const;
202
204 GradientValue gradient(size_t i, const VectorRd & x) const;
205
207 CurlValue curl(size_t i, const VectorRd & x) const;
208
210 HessianValue hessian(size_t i, const VectorRd & x) const;
211
213 inline size_t max_degree() const
214 {
215 return m_degree;
216 }
217
219 inline VectorZd powers(size_t i) const
220 {
221 return m_powers[i];
222 }
223
224 private:
226 inline VectorRd _coordinate_transform(const VectorRd& x) const
227 {
228 return (x - m_xT) / m_hT;
229 }
230
231 size_t m_degree;
232 VectorRd m_xT;
233 double m_hT;
234 std::vector<VectorZd> m_powers;
235 Eigen::Matrix2d m_rot; // rotation pi/2
236 };
237
238 //------------------------------------------------------------------------------
239
242 {
243 public:
244 typedef double FunctionValue;
247 typedef void DivergenceValue;
248 typedef void RotorValue;
249 typedef void HessianValue;
250
251 typedef Edge GeometricSupport;
252
253 constexpr static const TensorRankE tensorRank = Scalar;
254 constexpr static const bool hasAncestor = false;
255 static const bool hasFunction = true;
256 static const bool hasGradient = true;
257 static const bool hasCurl = false;
258 static const bool hasDivergence = false;
259 static const bool hasRotor = false;
260 static const bool hasHessian = false;
261
264 const Edge &E,
265 size_t degree
266 );
267
269 inline size_t dimension() const
270 {
271 return m_degree + 1;
272 }
273
275 FunctionValue function(size_t i, const VectorRd &x) const;
276
278 GradientValue gradient(size_t i, const VectorRd &x) const;
279
281 inline size_t max_degree() const
282 {
283 return m_degree;
284 }
285
286 private:
287 inline double _coordinate_transform(const VectorRd &x) const
288 {
289 return (x - m_xE).dot(m_tE) / m_hE;
290 }
291
292 size_t m_degree;
293 VectorRd m_xE;
294 double m_hE;
295 VectorRd m_tE;
296 };
297
298 //------------------------------------------------------------------------------
299 //------------------------------------------------------------------------------
300 // DERIVED BASIS
301 //------------------------------------------------------------------------------
302 //------------------------------------------------------------------------------
303
304 //----------------------------FAMILY------------------------------------------
305 //
311 template <typename BasisType>
312 class Family
313 {
314 public:
315 typedef typename BasisType::FunctionValue FunctionValue;
316 typedef typename BasisType::GradientValue GradientValue;
317 typedef typename BasisType::CurlValue CurlValue;
318 typedef typename BasisType::DivergenceValue DivergenceValue;
319 typedef typename BasisType::RotorValue RotorValue;
320 typedef typename BasisType::HessianValue HessianValue;
321
322 typedef typename BasisType::GeometricSupport GeometricSupport;
323
324 constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
325 constexpr static const bool hasAncestor = true;
326 static const bool hasFunction = BasisType::hasFunction;
327 static const bool hasGradient = BasisType::hasGradient;
328 static const bool hasCurl = BasisType::hasCurl;
329 static const bool hasDivergence = BasisType::hasDivergence;
330 static const bool hasRotor = BasisType::hasRotor;
331 static const bool hasHessian = BasisType::hasHessian;
332
333 typedef BasisType AncestorType;
334
337 const BasisType &basis,
338 const Eigen::MatrixXd &matrix
339 )
340 : m_basis(basis),
341 m_matrix(matrix)
342 {
343 assert((size_t)matrix.cols() == basis.dimension() || "Inconsistent family initialization");
344 }
345
347 inline size_t dimension() const
348 {
349 return m_matrix.rows();
350 }
351
353 FunctionValue function(size_t i, const VectorRd &x) const
354 {
355 static_assert(hasFunction, "Call to function() not available");
356
357 FunctionValue f = m_matrix(i, 0) * m_basis.function(0, x);
358 for (auto j = 1; j < m_matrix.cols(); j++)
359 {
360 f += m_matrix(i, j) * m_basis.function(j, x);
361 } // for j
362 return f;
363 }
364
366 FunctionValue function(size_t i, size_t iqn, const boost::multi_array<FunctionValue, 2> &ancestor_value_quad) const
367 {
368 static_assert(hasFunction, "Call to function() not available");
369
370 FunctionValue f = m_matrix(i, 0) * ancestor_value_quad[0][iqn];
371 for (auto j = 1; j < m_matrix.cols(); j++)
372 {
373 f += m_matrix(i, j) * ancestor_value_quad[j][iqn];
374 } // for j
375 return f;
376 }
377
378
380 GradientValue gradient(size_t i, const VectorRd &x) const
381 {
382 static_assert(hasGradient, "Call to gradient() not available");
383
384 GradientValue G = m_matrix(i, 0) * m_basis.gradient(0, x);
385 for (auto j = 1; j < m_matrix.cols(); j++)
386 {
387 G += m_matrix(i, j) * m_basis.gradient(j, x);
388 } // for j
389 return G;
390 }
391
393 GradientValue gradient(size_t i, size_t iqn, const boost::multi_array<GradientValue, 2> &ancestor_gradient_quad) const
394 {
395 static_assert(hasGradient, "Call to gradient() not available");
396
397 GradientValue G = m_matrix(i, 0) * ancestor_gradient_quad[0][iqn];
398 for (auto j = 1; j < m_matrix.cols(); j++)
399 {
400 G += m_matrix(i, j) * ancestor_gradient_quad[j][iqn];
401 } // for j
402 return G;
403 }
404
406 CurlValue curl(size_t i, const VectorRd &x) const
407 {
408 static_assert(hasCurl, "Call to curl() not available");
409
410 CurlValue C = m_matrix(i, 0) * m_basis.curl(0, x);
411 for (auto j = 1; j < m_matrix.cols(); j++)
412 {
413 C += m_matrix(i, j) * m_basis.curl(j, x);
414 } // for j
415 return C;
416 }
417
419 CurlValue curl(size_t i, size_t iqn, const boost::multi_array<CurlValue, 2> &ancestor_curl_quad) const
420 {
421 static_assert(hasCurl, "Call to curl() not available");
422
423 CurlValue C = m_matrix(i, 0) * ancestor_curl_quad[0][iqn];
424 for (auto j = 1; j < m_matrix.cols(); j++)
425 {
426 C += m_matrix(i, j) * ancestor_curl_quad[j][iqn];
427 } // for j
428 return C;
429 }
430
432 DivergenceValue divergence(size_t i, const VectorRd &x) const
433 {
434 static_assert(hasDivergence, "Call to divergence() not available");
435
436 DivergenceValue D = m_matrix(i, 0) * m_basis.divergence(0, x);
437 for (auto j = 1; j < m_matrix.cols(); j++)
438 {
439 D += m_matrix(i, j) * m_basis.divergence(j, x);
440 } // for j
441 return D;
442 }
443
445 DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<DivergenceValue, 2> &ancestor_divergence_quad) const
446 {
447 static_assert(hasDivergence, "Call to divergence() not available");
448
449 DivergenceValue D = m_matrix(i, 0) * ancestor_divergence_quad[0][iqn];
450 for (auto j = 1; j < m_matrix.cols(); j++)
451 {
452 D += m_matrix(i, j) * ancestor_divergence_quad[j][iqn];
453 } // for j
454 return D;
455 }
456
458 DivergenceValue rotor(size_t i, const VectorRd &x) const
459 {
460 static_assert(hasRotor, "Call to rotor() not available");
461
462 RotorValue R = m_matrix(i, 0) * m_basis.rotor(0, x);
463 for (auto j = 1; j < m_matrix.cols(); j++)
464 {
465 R += m_matrix(i, j) * m_basis.rotor(j, x);
466 } // for j
467 return R;
468 }
469
471 RotorValue rotor(size_t i, size_t iqn, const boost::multi_array<RotorValue, 2> &ancestor_rotor_quad) const
472 {
473 static_assert(hasRotor, "Call to rotor() not available");
474
475 RotorValue R = m_matrix(i, 0) * ancestor_rotor_quad[0][iqn];
476 for (auto j = 1; j < m_matrix.cols(); j++)
477 {
478 R += m_matrix(i, j) * ancestor_rotor_quad[j][iqn];
479 } // for j
480 return R;
481 }
482
484 inline HessianValue hessian(size_t i, const VectorRd & x) const
485 {
486 static_assert(hasHessian, "Call to hessian() not available");
487
488 HessianValue H = m_matrix(i, 0) * m_basis.hessian(0, x);
489 for (auto j = 1; j < m_matrix.cols(); j++)
490 {
491 H += m_matrix(i, j) * m_basis.hessian(j, x);
492 } // for j
493 return H;
494 }
495
497 HessianValue hessian(size_t i, size_t iqn, const boost::multi_array<HessianValue, 2> &ancestor_hessian_quad) const
498 {
499 static_assert(hasHessian, "Call to hessian() not available");
500
501 HessianValue H = m_matrix(i, 0) * ancestor_hessian_quad[0][iqn];
502 for (auto j = 1; j < m_matrix.cols(); j++)
503 {
504 H += m_matrix(i, j) * ancestor_hessian_quad[j][iqn];
505 } // for j
506 return H;
507 }
508
510 inline const Eigen::MatrixXd & matrix() const
511 {
512 return m_matrix;
513 }
514
516 constexpr inline const BasisType &ancestor() const
517 {
518 return m_basis;
519 }
520
522 inline size_t max_degree() const
523 {
524 return m_basis.max_degree();
525 }
526
527 private:
528 BasisType m_basis;
529 Eigen::MatrixXd m_matrix;
530 };
531
532 //----------------------TENSORIZED--------------------------------------------------------
533
535
559 template <typename ScalarFamilyType, size_t N>
561 {
562 public:
563 typedef typename Eigen::Matrix<double, N, 1> FunctionValue;
564 typedef typename Eigen::Matrix<double, N, dimspace> GradientValue;
566 typedef double DivergenceValue;
567 typedef double RotorValue;
568 typedef void HessianValue;
569
570 typedef typename ScalarFamilyType::GeometricSupport GeometricSupport;
571
572 constexpr static const TensorRankE tensorRank = Vector;
573 constexpr static const bool hasAncestor = true;
574 static const bool hasFunction = ScalarFamilyType::hasFunction;
575 static const bool hasGradient = ScalarFamilyType::hasGradient;
576 // We know how to compute the curl, scalar rotor, and divergence if gradient is available
577 static const bool hasDivergence = ( ScalarFamilyType::hasGradient && N==dimspace );
578 static const bool hasRotor = ( ScalarFamilyType::hasGradient && N==dimspace );
579 static const bool hasCurl = ( ScalarFamilyType::hasGradient && N==dimspace );
580 // In future versions, one could include the computation of second derivatives
581 // checking that BasisType has information on the Hessian
582 static const bool hasHessian = false;
583
584 typedef ScalarFamilyType AncestorType;
585
586 TensorizedVectorFamily(const ScalarFamilyType & scalar_family)
587 : m_scalar_family(scalar_family)
588 {
589 static_assert(ScalarFamilyType::tensorRank == Scalar,
590 "Vector family can only be constructed from scalar families");
591 m_rot.row(0) << 0., 1.;
592 m_rot.row(1) << -1., 0.;
593
594 }
595
597 inline size_t dimension() const
598 {
599 return m_scalar_family.dimension() * N;
600 }
601
603 FunctionValue function(size_t i, const VectorRd &x) const
604 {
605 static_assert(hasFunction, "Call to function() not available");
606
607 FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
608 ek(i / m_scalar_family.dimension()) = 1.;
609 return ek * m_scalar_family.function(i % m_scalar_family.dimension(), x);
610 }
611
613 FunctionValue function(size_t i, size_t iqn, const boost::multi_array<double, 2> &ancestor_value_quad) const
614 {
615 static_assert(hasFunction, "Call to function() not available");
616
617 FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
618 ek(i / m_scalar_family.dimension()) = 1.;
619 return ek * ancestor_value_quad[i % m_scalar_family.dimension()][iqn];
620 }
621
623 GradientValue gradient(size_t i, const VectorRd &x) const
624 {
625 static_assert(hasGradient, "Call to gradient() not available");
626
627 GradientValue G = Eigen::Matrix<double, N, dimspace>::Zero();
628 G.row(i / m_scalar_family.dimension()) = m_scalar_family.gradient(i % m_scalar_family.dimension(), x);
629 return G;
630 }
631
633 GradientValue gradient(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
634 {
635 static_assert(hasGradient, "Call to gradient() not available");
636
637 GradientValue G = Eigen::Matrix<double, N, dimspace>::Zero();
638 G.row(i / m_scalar_family.dimension()) = ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn];
639 return G;
640 }
641
643 CurlValue curl(size_t i, const VectorRd &x) const
644 {
645 static_assert(hasCurl, "Call to curl() not available");
646
647 return m_rot * gradient(i, x);
648 }
649
651 CurlValue curl(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
652 {
653 static_assert(hasCurl, "Call to curl() not available");
654
655 return m_rot * ancestor_gradient_quad[i][iqn];
656 }
657
659 DivergenceValue divergence(size_t i, const VectorRd &x) const
660 {
661 static_assert(hasDivergence, "Call to divergence() not available");
662
663 return m_scalar_family.gradient(i % m_scalar_family.dimension(), x)(i / m_scalar_family.dimension());
664 }
665
667 DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
668 {
669 static_assert(hasDivergence, "Call to divergence() not available");
670
671 return ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn](i / m_scalar_family.dimension());
672 }
673
675 RotorValue rotor(size_t i, const VectorRd &x) const
676 {
677 static_assert(hasRotor && hasCurl, "Call to rotor() not available");
678
679 return curl(i, x).trace();
680 }
681
683 RotorValue rotor(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
684 {
685 static_assert(hasRotor, "Call to rotor() not available");
686
687 return curl(i, iqn, ancestor_gradient_quad).trace();
688 }
689
691 constexpr inline const ScalarFamilyType &ancestor() const
692 {
693 return m_scalar_family;
694 }
695
697 inline size_t max_degree() const
698 {
699 return m_scalar_family.max_degree();
700 }
701
702 private:
703 ScalarFamilyType m_scalar_family;
704 Eigen::Matrix2d m_rot; // Rotation of pi/2
705 };
706
707 //----------------------MATRIX FAMILY--------------------------------------------------------
708
710
715 // Useful formulas to manipulate this basis (all indices starting from 0):
716 // the i-th element in the basis is f_{i%r} E_{i/r}
717 // the matrix E_m has 1 at position (m%N, m/N)
718 // the element f_aE_b is the i-th in the family with i = b*r + a
719 template<typename ScalarFamilyType, size_t N>
721 {
722 public:
723 typedef typename Eigen::Matrix<double, N, N> FunctionValue;
726 typedef typename Eigen::Matrix<double, N, 1> DivergenceValue;
727 typedef void RotorValue;
728 typedef void HessianValue;
729
730 typedef typename ScalarFamilyType::GeometricSupport GeometricSupport;
731
732 constexpr static const TensorRankE tensorRank = Matrix;
733 constexpr static const bool hasAncestor = true;
734 static const bool hasFunction = ScalarFamilyType::hasFunction;
735 static const bool hasGradient = true;
736 static const bool hasDivergence = ( ScalarFamilyType::hasGradient && N==dimspace );
737 static const bool hasRotor = false;
738 static const bool hasCurl = false;
739 static const bool hasHessian = false;
740
741 typedef ScalarFamilyType AncestorType;
742
743 MatrixFamily(const ScalarFamilyType & scalar_family)
744 : m_scalar_family(scalar_family),
745 m_E(N*N),
746 m_transposeOperator(Eigen::MatrixXd::Zero(scalar_family.dimension()*N*N, scalar_family.dimension()*N*N))
747 {
748 static_assert(ScalarFamilyType::tensorRank == Scalar,
749 "Vector family can only be constructed from scalar families");
750
751 // Construct the basis for NxN matrices
752 for (size_t j = 0; j < N; j++){
753 for (size_t i = 0; i < N; i++){
754 m_E[j*N + i] = Eigen::Matrix<double, N, N>::Zero();
755 m_E[j*N + i](i,j) = 1.;
756 }
757 }
758
759 // Construct the transpose operator
760 for (size_t i = 0; i < dimension(); i++){
761 // 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
762 size_t r = m_scalar_family.dimension();
763 size_t j = ( ( (i/r)%N )*N + (i/r)/N ) * r + (i%r);
764 m_transposeOperator(i,j) = 1.;
765 }
766 }
767
769 inline size_t dimension() const
770 {
771 return m_scalar_family.dimension() * N * N;
772 }
773
775 FunctionValue function(size_t i, const VectorRd & x) const
776 {
777 static_assert(hasFunction, "Call to function() not available");
778
779 return m_scalar_family.function(i % m_scalar_family.dimension(), x) * m_E[i / m_scalar_family.dimension()];
780 }
781
783 FunctionValue function(size_t i, size_t iqn, const boost::multi_array<double, 2> &ancestor_value_quad) const
784 {
785 static_assert(hasFunction, "Call to function() not available");
786
787 return ancestor_value_quad[i % m_scalar_family.dimension()][iqn] * m_E[i / m_scalar_family.dimension()];
788 }
789
791 DivergenceValue divergence(size_t i, const VectorRd & x) const
792 {
793 static_assert(hasDivergence, "Call to divergence() not available");
794
795 Eigen::Matrix<double, N, 1> V = m_E[i/m_scalar_family.dimension()].col( (i/m_scalar_family.dimension()) /N);
796 return m_scalar_family.gradient(i % m_scalar_family.dimension(), x)( (i / m_scalar_family.dimension()) / N) * V;
797 }
798
800 DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
801 {
802 static_assert(hasDivergence, "Call to divergence() not available");
803
804 Eigen::Matrix<double, N, 1> V = m_E[i/m_scalar_family.dimension()].col( (i/m_scalar_family.dimension()) /N);
805 return ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn]( (i / m_scalar_family.dimension()) / N) * V;
806 }
807
809 GradientValue gradient(size_t i, const VectorRd & x) const
810 {
811 static_assert(hasGradient, "Call to gradient() not available");
812
813 const VectorRd gradient_scalar_function = m_scalar_family.gradient(i % m_scalar_family.dimension(), x);
814 const Eigen::Matrix<double, N, N> matrix_basis = m_E[i / m_scalar_family.dimension()];
815 return GradientValue(gradient_scalar_function.x() * matrix_basis, gradient_scalar_function.y() * matrix_basis);
816 }
817
819 GradientValue gradient(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
820 {
821 static_assert(hasGradient, "Call to gradient() not available");
822
823 const VectorRd gradient_scalar_function = ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn];
824 const Eigen::Matrix<double, N, N> matrix_basis = m_E[i / m_scalar_family.dimension()];
825 return GradientValue(gradient_scalar_function.x() * matrix_basis, gradient_scalar_function.y() * matrix_basis);
826 }
827
829 inline const ScalarFamilyType &ancestor() const
830 {
831 return m_scalar_family;
832 }
833
835 inline const size_t matrixSize() const
836 {
837 return N;
838 }
839
841 inline const Eigen::MatrixXd transposeOperator() const
842 {
843 return m_transposeOperator;
844 }
845
847 inline const Eigen::MatrixXd symmetriseOperator() const
848 {
849 return (Eigen::MatrixXd::Identity(dimension(), dimension()) + m_transposeOperator)/2;
850 }
851
853 const Eigen::MatrixXd symmetricBasis() const
854 {
855 size_t dim_scalar = m_scalar_family.dimension();
856 Eigen::MatrixXd symOpe = symmetriseOperator();
857
858 Eigen::MatrixXd SB = Eigen::MatrixXd::Zero(dim_scalar * N*(N+1)/2, dimension());
859
860 // The matrix consists in selecting certain rows of symmetriseOperator, corresponding to the lower triangular part
861 // To select these rows, we loop over the columns of the underlying matrices, and get the rows in symmetriseOperator()
862 // corresponding to the lower triangular part of each column
863 size_t position = 0;
864 for (size_t i = 0; i<N; i++){
865 // Skip the first i*dim_scalar elements in the column (upper triangle) in symOpe, take the remaining (N-i)*dim_scalar
866 SB.middleRows(position, (N-i)*dim_scalar) = symOpe.middleRows(i*(N+1)*dim_scalar, (N-i)*dim_scalar);
867 // update current position
868 position += (N-i)*dim_scalar;
869 }
870
871 return SB;
872 }
873
875
878 inline const Eigen::MatrixXd traceOperator() const
879 {
880 size_t r = m_scalar_family.dimension();
881
882 Eigen::MatrixXd Tr = Eigen::MatrixXd::Zero(r, dimension());
883
884 /* According to the formulas described at the start of this class, the l-th element of the
885 matrix family is f_{l%r} E_{l/r}.
886 Given the construction of E_m=E_{l/r}, the trace is either 0, or 1 if m%N=m/N, that is,
887 (l/r)%N = (l/r)/N.
888 So Tr_{kl}=1 only if k=l%r and (l/r)%N = (l/r)/N
889 */
890 for (size_t l=0; l < dimension(); l++){
891 if ( size_t(l/r)%N == size_t(size_t(l/r)/N) ){
892 size_t k = l%r;
893 Tr(k,l) = 1.;
894 }
895 }
896
897 return Tr;
898 }
899
900 private:
901 ScalarFamilyType m_scalar_family;
902 std::vector<Eigen::Matrix<double, N, N>> m_E;
903 Eigen::MatrixXd m_transposeOperator;
904 };
905
906
907 //----------------------TANGENT FAMILY--------------------------------------------------------
908
910 template <typename ScalarFamilyType>
912 {
913 public:
917 typedef void DivergenceValue;
918 typedef void RotorValue;
919 typedef void HessianValue;
920
921 typedef Edge GeometricSupport;
922
923 constexpr static const TensorRankE tensorRank = Vector;
924 constexpr static const bool hasAncestor = true;
925 static const bool hasFunction = true;
926 static const bool hasGradient = false;
927 static const bool hasCurl = false;
928 static const bool hasDivergence = false;
929 static const bool hasRotor = false;
930 static const bool hasHessian = false;
931
932 typedef ScalarFamilyType AncestorType;
933
936 const ScalarFamilyType &scalar_family,
937 const VectorRd &generator
938 )
939 : m_scalar_family(scalar_family),
940 m_generator(generator)
941 {
942 static_assert(ScalarFamilyType::hasFunction, "Call to function() not available");
943 static_assert(std::is_same<typename ScalarFamilyType::GeometricSupport, Edge>::value,
944 "Tangent families can only be defined on edges");
945 }
946
948 inline size_t dimension() const
949 {
950 return m_scalar_family.dimension();
951 }
952
954 inline FunctionValue function(size_t i, const VectorRd &x) const
955 {
956 return m_scalar_family.function(i, x) * m_generator;
957 }
958
960 constexpr inline const ScalarFamilyType &ancestor() const
961 {
962 return m_scalar_family;
963 }
964
966 inline size_t max_degree() const
967 {
968 return m_scalar_family.max_degree();
969 }
970
972 inline VectorRd generator() const
973 {
974 return m_generator;
975 }
976
977 private:
978 ScalarFamilyType m_scalar_family;
979 VectorRd m_generator;
980 };
981
982
983 //--------------------SHIFTED BASIS----------------------------------------------------------
984
986
987 template <typename BasisType>
989 {
990 public:
991 typedef typename BasisType::FunctionValue FunctionValue;
992 typedef typename BasisType::GradientValue GradientValue;
993 typedef typename BasisType::CurlValue CurlValue;
994 typedef typename BasisType::DivergenceValue DivergenceValue;
995 typedef typename BasisType::RotorValue RotorValue;
996 typedef typename BasisType::HessianValue HessianValue;
997
998 typedef typename BasisType::GeometricSupport GeometricSupport;
999
1000 constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
1001 constexpr static const bool hasAncestor = true;
1002 static const bool hasFunction = BasisType::hasFunction;
1003 static const bool hasGradient = BasisType::hasGradient;
1004 static const bool hasCurl = BasisType::hasCurl;
1005 static const bool hasDivergence = BasisType::hasDivergence;
1006 static const bool hasRotor = BasisType::hasRotor;
1007 static const bool hasHessian = BasisType::hasHessian;
1008
1009 typedef BasisType AncestorType;
1010
1013 const BasisType &basis,
1014 const int shift
1015 )
1016 : m_basis(basis),
1017 m_shift(shift)
1018 {
1019 // Do nothing
1020 }
1021
1023 inline size_t dimension() const
1024 {
1025 return m_basis.dimension() - m_shift;
1026 }
1027
1029 constexpr inline const BasisType &ancestor() const
1030 {
1031 return m_basis;
1032 }
1033
1035 inline size_t max_degree() const
1036 {
1037 return m_basis.max_degree();
1038 }
1039
1041 inline FunctionValue function(size_t i, const VectorRd &x) const
1042 {
1043 static_assert(hasFunction, "Call to function() not available");
1044
1045 return m_basis.function(i + m_shift, x);
1046 }
1047
1049 inline GradientValue gradient(size_t i, const VectorRd &x) const
1050 {
1051 static_assert(hasGradient, "Call to gradient() not available");
1052
1053 return m_basis.gradient(i + m_shift, x);
1054 }
1055
1057 inline CurlValue curl(size_t i, const VectorRd &x) const
1058 {
1059 static_assert(hasCurl, "Call to curl() not available");
1060
1061 return m_basis.curl(i + m_shift, x);
1062 }
1063
1065 inline DivergenceValue divergence(size_t i, const VectorRd &x) const
1066 {
1067 static_assert(hasDivergence, "Call to divergence() not available");
1068
1069 return m_basis.divergence(i + m_shift, x);
1070 }
1071
1073 inline RotorValue rotor(size_t i, const VectorRd &x) const
1074 {
1075 static_assert(hasRotor, "Call to rotor() not available");
1076
1077 return m_basis.rotor(i + m_shift, x);
1078 }
1079
1081 inline HessianValue hessian(size_t i, const VectorRd & x) const
1082 {
1083 static_assert(hasHessian, "Call to hessian() not available");
1084
1085 return m_basis.hessian(i + m_shift, x);
1086 }
1087
1088 private:
1089 BasisType m_basis;
1090 int m_shift;
1091 };
1092
1093 //-----------------------RESTRICTED BASIS-------------------------------------------------------
1094
1096
1097 template <typename BasisType>
1099 {
1100 public:
1101 typedef typename BasisType::FunctionValue FunctionValue;
1102 typedef typename BasisType::GradientValue GradientValue;
1103 typedef typename BasisType::CurlValue CurlValue;
1104 typedef typename BasisType::DivergenceValue DivergenceValue;
1105 typedef typename BasisType::RotorValue RotorValue;
1106 typedef typename BasisType::HessianValue HessianValue;
1107
1108 typedef typename BasisType::GeometricSupport GeometricSupport;
1109
1110 constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
1111 constexpr static const bool hasAncestor = true;
1112 static const bool hasFunction = BasisType::hasFunction;
1113 static const bool hasGradient = BasisType::hasGradient;
1114 static const bool hasCurl = BasisType::hasCurl;
1115 static const bool hasDivergence = BasisType::hasDivergence;
1116 static const bool hasRotor = BasisType::hasRotor;
1117 static const bool hasHessian = BasisType::hasHessian;
1118
1119 typedef BasisType AncestorType;
1120
1123 const BasisType &basis,
1124 const size_t &dimension
1125 )
1126 : m_basis(basis),
1127 m_dimension(dimension)
1128 {
1129 // Make sure that the provided dimension is smaller than the one
1130 // of the provided basis
1131 assert(dimension <= basis.dimension());
1132 }
1133
1135 inline size_t dimension() const
1136 {
1137 return m_dimension;
1138 }
1139
1141 constexpr inline const BasisType &ancestor() const
1142 {
1143 return m_basis;
1144 }
1145
1147 inline size_t max_degree() const
1148 {
1149 // We need to find the degree based on the dimension, assumes the basis is hierarchical
1150 size_t deg = 0;
1151 while (PolynomialSpaceDimension<GeometricSupport>::Poly(deg) < m_dimension){
1152 deg++;
1153 }
1154 return deg;
1155 }
1156
1158 inline FunctionValue function(size_t i, const VectorRd &x) const
1159 {
1160 static_assert(hasFunction, "Call to function() not available");
1161
1162 return m_basis.function(i, x);
1163 }
1164
1166 GradientValue gradient(size_t i, const VectorRd &x) const
1167 {
1168 static_assert(hasGradient, "Call to gradient() not available");
1169
1170 return m_basis.gradient(i, x);
1171 }
1172
1174 CurlValue curl(size_t i, const VectorRd &x) const
1175 {
1176 static_assert(hasCurl, "Call to curl() not available");
1177
1178 return m_basis.curl(i, x);
1179 }
1180
1182 DivergenceValue divergence(size_t i, const VectorRd &x) const
1183 {
1184 static_assert(hasDivergence, "Call to divergence() not available");
1185
1186 return m_basis.divergence(i, x);
1187 }
1188
1190 RotorValue rotor(size_t i, const VectorRd &x) const
1191 {
1192 static_assert(hasRotor, "Call to rotor() not available");
1193
1194 return m_basis.rotor(i, x);
1195 }
1196
1197 private:
1198 BasisType m_basis;
1199 size_t m_dimension;
1200 };
1201
1202 //--------------------GRADIENT BASIS----------------------------------------------------------
1203
1205
1207 template <typename BasisType>
1209 {
1210 public:
1211 typedef typename BasisType::GradientValue FunctionValue;
1212 typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1214 typedef void DivergenceValue;
1215 typedef void RotorValue;
1216 typedef void HessianValue;
1217
1218 typedef typename BasisType::GeometricSupport GeometricSupport;
1219
1220 constexpr static const TensorRankE tensorRank = Vector;
1221 constexpr static const bool hasAncestor = true;
1222 static const bool hasFunction = true;
1223 // In future versions, one could include the computation of derivatives
1224 // checking that BasisType has information on the Hessian
1225 static const bool hasGradient = false;
1226 static const bool hasCurl = false;
1227 static const bool hasDivergence = false;
1228 static const bool hasRotor = false;
1229 static const bool hasHessian = false;
1230
1231 typedef BasisType AncestorType;
1232
1234 GradientBasis(const BasisType &basis)
1235 : m_scalar_basis(basis)
1236 {
1237 static_assert(BasisType::hasGradient,
1238 "Gradient basis requires gradient() for the original basis to be available");
1239 // Do nothing
1240 }
1241
1243 inline size_t dimension() const
1244 {
1245 return m_scalar_basis.dimension();
1246 }
1247
1249 inline FunctionValue function(size_t i, const VectorRd &x) const
1250 {
1251 return m_scalar_basis.gradient(i, x);
1252 }
1253
1255 constexpr inline const BasisType &ancestor() const
1256 {
1257 return m_scalar_basis;
1258 }
1259
1260
1261 private:
1262 BasisType m_scalar_basis;
1263 };
1264
1265 //-------------------CURL BASIS-----------------------------------------------------------
1266
1268
1269 template <typename BasisType>
1271 {
1272 public:
1274 typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1275 typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1276 typedef void DivergenceValue;
1277 typedef void RotorValue;
1278 typedef void HessianValue;
1279
1280 typedef typename BasisType::GeometricSupport GeometricSupport;
1281
1282 constexpr static const TensorRankE tensorRank = Vector;
1283 constexpr static const bool hasAncestor = true;
1284 static const bool hasFunction = true;
1285 static const bool hasGradient = false;
1286 static const bool hasCurl = false;
1287 static const bool hasDivergence = false;
1288 static const bool hasRotor = false;
1289 static const bool hasHessian = false;
1290
1291 typedef BasisType AncestorType;
1292
1294 CurlBasis(const BasisType &basis)
1295 : m_basis(basis)
1296 {
1297 static_assert(BasisType::tensorRank == Scalar && std::is_same<typename BasisType::GeometricSupport, Cell>::value,
1298 "Curl basis can only be constructed starting from scalar bases on elements");
1299 static_assert(BasisType::hasCurl,
1300 "Curl basis requires curl() for the original basis to be available");
1301 }
1302
1304 inline size_t dimension() const
1305 {
1306 return m_basis.dimension();
1307 }
1308
1310 inline FunctionValue function(size_t i, const VectorRd &x) const
1311 {
1312 return m_basis.curl(i, x);
1313 }
1314
1316 constexpr inline const BasisType &ancestor() const
1317 {
1318 return m_basis;
1319 }
1320
1321
1322 private:
1323 size_t m_degree;
1324 BasisType m_basis;
1325 };
1326
1327
1328 //--------------------DIVERGENCE BASIS----------------------------------------------------------
1329
1331
1332 template <typename BasisType>
1334 {
1335 public:
1336 typedef double FunctionValue;
1339 typedef double DivergenceValue;
1340 typedef void HessianValue;
1341
1342 typedef typename BasisType::GeometricSupport GeometricSupport;
1343
1344 constexpr static const TensorRankE tensorRank = Scalar;
1345 constexpr static const bool hasAncestor = true;
1346 static const bool hasFunction = true;
1347 static const bool hasGradient = false;
1348 static const bool hasCurl = false;
1349 static const bool hasDivergence = false;
1350 static const bool hasHessian = false;
1351
1352 typedef BasisType AncestorType;
1353
1355 DivergenceBasis(const BasisType &basis)
1356 : m_vector_basis(basis)
1357 {
1358 static_assert(BasisType::tensorRank == Vector || BasisType::tensorRank == Matrix,
1359 "Divergence basis can only be constructed starting from vector bases");
1360 static_assert(BasisType::hasDivergence,
1361 "Divergence basis requires divergence() for the original basis to be available");
1362 // Do nothing
1363 }
1364
1366 inline size_t dimension() const
1367 {
1368 return m_vector_basis.dimension();
1369 }
1370
1372 inline FunctionValue function(size_t i, const VectorRd &x) const
1373 {
1374 return m_vector_basis.divergence(i, x);
1375 }
1376
1378 constexpr inline const BasisType &ancestor() const
1379 {
1380 return m_vector_basis;
1381 }
1382
1383 private:
1384 BasisType m_vector_basis;
1385 };
1386
1387
1388 //--------------------ROTOR BASIS----------------------------------------------------------
1389
1391
1392 template <typename BasisType>
1394 {
1395 public:
1396 typedef double FunctionValue;
1399 typedef void DivergenceValue;
1400 typedef void RotorValue;
1401 typedef void HessianValue;
1402
1403 typedef typename BasisType::GeometricSupport GeometricSupport;
1404
1405 constexpr static const TensorRankE tensorRank = Scalar;
1406 constexpr static const bool hasAncestor = true;
1407 static const bool hasFunction = true;
1408 static const bool hasGradient = false;
1409 static const bool hasCurl = false;
1410 static const bool hasDivergence = false;
1411 static const bool hasRotor = false;
1412 static const bool hasHessian = false;
1413
1414 typedef BasisType AncestorType;
1415
1417 RotorBasis(const BasisType &basis)
1418 : m_vector_basis(basis)
1419 {
1420 static_assert(BasisType::tensorRank == Vector,
1421 "Rotor basis can only be constructed starting from vector bases");
1422 static_assert(BasisType::hasRotor,
1423 "Rotor basis requires rotor() for the original basis to be available");
1424 // Do nothing
1425 }
1426
1428 inline size_t dimension() const
1429 {
1430 return m_vector_basis.dimension();
1431 }
1432
1434 inline FunctionValue function(size_t i, const VectorRd &x) const
1435 {
1436 return m_vector_basis.rotor(i, x);
1437 }
1438
1440 constexpr inline const BasisType &ancestor() const
1441 {
1442 return m_vector_basis;
1443 }
1444
1445 private:
1446 BasisType m_vector_basis;
1447 };
1448
1449
1450 //--------------------HESSIAN BASIS----------------------------------------------------------
1451
1453
1455 template <typename BasisType>
1457 {
1458 public:
1460 // The following types do not make sense in this context and are set to void
1461 typedef void GradientValue;
1462 typedef void CurlValue;
1463 typedef void DivergenceValue;
1464 typedef void RotorValue;
1465 typedef void HessianValue;
1466
1467 typedef typename BasisType::GeometricSupport GeometricSupport;
1468
1469 constexpr static const TensorRankE tensorRank = Matrix;
1470 constexpr static const bool hasAncestor = true;
1471 static const bool hasFunction = true;
1472 // In future versions, one could include the computation of derivatives
1473 // checking that BasisType has information on the Hessian
1474 static const bool hasGradient = false;
1475 static const bool hasCurl = false;
1476 static const bool hasDivergence = false;
1477 static const bool hasRotor = false;
1478 static const bool hasHessian = false;
1479
1480 typedef BasisType AncestorType;
1481
1483 HessianBasis(const BasisType &basis)
1484 : m_scalar_basis(basis)
1485 {
1486 static_assert(BasisType::tensorRank == Scalar,
1487 "Hessian basis can only be constructed starting from scalar bases");
1488 static_assert(BasisType::hasHessian,
1489 "Hessian basis requires hessian() for the original basis to be available");
1490 // Do nothing
1491 }
1492
1494 inline size_t dimension() const
1495 {
1496 return m_scalar_basis.dimension();
1497 }
1498
1500 inline FunctionValue function(size_t i, const VectorRd &x) const
1501 {
1502 return m_scalar_basis.hessian(i, x);
1503 }
1504
1506 constexpr inline const BasisType &ancestor() const
1507 {
1508 return m_scalar_basis;
1509 }
1510
1511
1512 private:
1513 BasisType m_scalar_basis;
1514 };
1515
1516 //---------------------------------------------------------------------
1517 // BASES FOR THE KOSZUL COMPLEMENTS OF G^k, R^k, H^k
1518 //---------------------------------------------------------------------
1521 {
1522 public:
1524 typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1525 typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1526 typedef double DivergenceValue;
1527 typedef void RotorValue;
1528 typedef void HessianValue;
1529
1530 typedef Cell GeometricSupport;
1531
1532 constexpr static const TensorRankE tensorRank = Vector;
1533 constexpr static const bool hasAncestor = false;
1534 static const bool hasFunction = true;
1535 static const bool hasGradient = false;
1536 static const bool hasCurl = false;
1537 static const bool hasDivergence = true;
1538 static const bool hasRotor = false;
1539 static const bool hasHessian = false;
1540
1543 const Cell &T,
1544 size_t degree
1545 );
1546
1548 inline size_t dimension() const
1549 {
1551 }
1552
1554 FunctionValue function(size_t i, const VectorRd &x) const;
1555
1557 DivergenceValue divergence(size_t i, const VectorRd &x) const;
1558
1560 inline size_t max_degree() const
1561 {
1562 return m_degree;
1563 }
1564
1566 inline VectorZd powers(size_t i) const
1567 {
1568 return m_powers[i];
1569 }
1570
1571 private:
1573 inline VectorRd _coordinate_transform(const VectorRd &x) const
1574 {
1575 return (x - m_xT) / m_hT;
1576 }
1577
1578 size_t m_degree;
1579 VectorRd m_xT;
1580 double m_hT;
1581 std::vector<VectorZd> m_powers;
1582 };
1583
1584
1587 {
1588 public:
1590 typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1591 typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1592 typedef void DivergenceValue;
1593 typedef double RotorValue;
1594 typedef void HessianValue;
1595
1596 typedef Cell GeometricSupport;
1597
1598 constexpr static const TensorRankE tensorRank = Vector;
1599 constexpr static const bool hasAncestor = false;
1600 static const bool hasFunction = true;
1601 static const bool hasGradient = false;
1602 static const bool hasCurl = false;
1603 static const bool hasDivergence = false;
1604 static const bool hasRotor = true;
1605 static const bool hasHessian = false;
1606
1609 const Cell &T,
1610 size_t degree
1611 );
1612
1614 inline size_t dimension() const
1615 {
1617 }
1618
1620 FunctionValue function(size_t i, const VectorRd &x) const;
1621
1623 RotorValue rotor(size_t i, const VectorRd &x) const;
1624
1626 inline const std::shared_ptr<RolyComplBasisCell> &rck() const
1627 {
1628 return m_Rck_basis;
1629 }
1630
1631 private:
1632 size_t m_degree;
1633 Eigen::Matrix2d m_rot; // Rotation of pi/2: the basis of Gck is the rotated basis of Rck
1634 std::shared_ptr<RolyComplBasisCell> m_Rck_basis; // A basis of Rck, whose rotation gives a basis of Gck
1635 };
1636
1639 {
1640 public:
1642 // The following types do not make sense in this context and are set to void
1643 typedef void GradientValue;
1644 typedef void CurlValue;
1645 typedef void DivergenceValue;
1646 typedef void RotorValue;
1647 typedef void HessianValue;
1648
1649 typedef Cell GeometricSupport;
1650
1651 constexpr static const TensorRankE tensorRank = Matrix;
1652 constexpr static const bool hasAncestor = false;
1653 static const bool hasFunction = true;
1654 static const bool hasGradient = false;
1655 static const bool hasCurl = false;
1656 static const bool hasDivergence = true;
1657 static const bool hasRotor = false;
1658 static const bool hasHessian = false;
1659
1662 const Cell &T,
1663 size_t degree
1664 );
1665
1667 inline size_t dimension() const
1668 {
1670 }
1671
1673 FunctionValue function(size_t i, const VectorRd &x) const;
1674
1676 inline size_t max_degree() const
1677 {
1678 return m_degree;
1679 }
1680
1681 private:
1683 inline VectorRd _coordinate_transform(const VectorRd &x) const
1684 {
1685 return (x - m_xT) / m_hT;
1686 }
1687
1688 size_t m_degree;
1689 VectorRd m_xT;
1690 double m_hT;
1691 Eigen::Matrix2d m_rot;
1692 TensorizedVectorFamily<MonomialScalarBasisCell, dimspace> m_Pkmo;
1693 };
1694
1695 //------------------------------------------------------------------------------
1696 // Free functions
1697 //------------------------------------------------------------------------------
1698
1710
1712 template <typename outValue, typename inValue, typename FunctionType>
1713 boost::multi_array<outValue, 2> transform_values_quad(
1714 const boost::multi_array<inValue, 2> &B_quad,
1715 const FunctionType &F
1716 )
1717 {
1718 boost::multi_array<outValue, 2> transformed_B_quad( boost::extents[B_quad.shape()[0]][B_quad.shape()[1]] );
1719
1720 std::transform( B_quad.origin(), B_quad.origin() + B_quad.num_elements(), transformed_B_quad.origin(), F);
1721
1722 return transformed_B_quad;
1723 };
1724
1726
1727 template <typename ScalarBasisType, size_t N>
1729 const ScalarBasisType & B,
1730 const std::vector<Eigen::VectorXd> & v
1731 )
1732 {
1733 size_t r = B.dimension();
1734 size_t k = v.size();
1735
1736 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(r*k, r*N);
1737
1738 for (size_t i=0; i < k; i++){
1739 // Check the dimension of vector v[i]
1740 assert(v[i].size() == N);
1741
1742 // Fill in M
1743 for (size_t j=0; j < N; j++){
1744 M.block(i*r, j*r, r, r) = v[i](j) * Eigen::MatrixXd::Identity(r,r);
1745 }
1746 }
1747
1750 }
1751
1753
1756 Eigen::MatrixXd PermuteTensorization( const size_t a,
1757 const size_t b
1758 );
1759
1761 inline static std::function<Eigen::MatrixXd(const Eigen::MatrixXd &)>
1762 symmetrise_matrix = [](const Eigen::MatrixXd & x)->Eigen::MatrixXd { return 0.5*(x+x.transpose());};
1763
1765 inline static std::function<Eigen::MatrixXd(const Eigen::MatrixXd &)>
1766 skew_symmetrise_matrix = [](const Eigen::MatrixXd & x)->Eigen::MatrixXd { return 0.5*(x-x.transpose());};
1767
1769
1770 template <typename ScalarBasisType, size_t N>
1772 const ScalarBasisType & B
1773 )
1774 {
1775 size_t r = B.dimension();
1776 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(r, r*N*N);
1777
1778 for (size_t k=0; k < N; k++){
1779 M.block(0, k*r*(N+1), r, r) = Eigen::MatrixXd::Identity(r, r);
1780 }
1781
1783 return Family<MatrixFamily<ScalarBasisType, N>>(matbasis, M);
1784 }
1785 //------------------------------------------------------------------------------
1786 // BASIS EVALUATION
1787 //------------------------------------------------------------------------------
1788
1789 namespace detail {
1791
1792 template<typename BasisType, BasisFunctionE BasisFunction>
1794
1795 //---------- GENERIC EVALUATION TRAITS -----------------------------------------
1796 // Evaluate the function value at x
1797 template<typename BasisType>
1799 {
1800 static_assert(BasisType::hasFunction, "Call to function not available");
1801 typedef typename BasisType::FunctionValue ReturnValue;
1802 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1803 {
1804 return basis.function(i, x);
1805 }
1806
1807 // Computes function value at quadrature node iqn, knowing values of ancestor basis at quadrature nodes
1808 static inline ReturnValue evaluate(
1809 const BasisType &basis,
1810 size_t i,
1811 size_t iqn,
1812 const boost::multi_array<ReturnValue, 2> &ancestor_value_quad
1813 )
1814 {
1815 return basis.function(i, iqn, ancestor_value_quad);
1816 }
1817
1818 };
1819
1820 // Evaluate the gradient value at x
1821 template<typename BasisType>
1823 {
1824 static_assert(BasisType::hasGradient, "Call to gradient not available");
1825 typedef typename BasisType::GradientValue ReturnValue;
1826 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1827 {
1828 return basis.gradient(i, x);
1829 }
1830
1831 // Computes gradient value at quadrature node iqn, knowing gradients of ancestor basis at quadrature nodes
1832 static inline ReturnValue evaluate(
1833 const BasisType &basis,
1834 size_t i,
1835 size_t iqn,
1836 const boost::multi_array<ReturnValue, 2> &ancestor_gradient_quad
1837 )
1838 {
1839 return basis.gradient(i, iqn, ancestor_gradient_quad);
1840 }
1841 };
1842
1843 // AC - it's supposed to be used only in case of vector variables (vhhospace)
1844 // Evaluate the symmetric part of gradient at x
1845 template<typename BasisType>
1847 {
1848 static_assert(BasisType::hasGradient, "Call to gradient not available");
1849 typedef typename BasisType::GradientValue ReturnValue;
1850 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1851 {
1852 return 0.5 * (basis.gradient(i, x) + basis.gradient(i, x).transpose());
1853 }
1854
1855 // Computes gradient value at quadrature node iqn, knowing gradients of ancestor basis at quadrature nodes
1856 static inline ReturnValue evaluate(
1857 const BasisType &basis,
1858 size_t i,
1859 size_t iqn,
1860 const boost::multi_array<ReturnValue, 2> &ancestor_gradient_quad
1861 )
1862 {
1863 return 0.5 * (basis.gradient(i, iqn, ancestor_gradient_quad) + basis.gradient(i, iqn, ancestor_gradient_quad).transpose());
1864 }
1865 };
1866
1867 // AC - it's supposed to be used only in case of vector variables (vhhospace)
1868 // Evaluate the symmetric part of gradient at x
1869 template<typename BasisType>
1871 {
1872 static_assert(BasisType::hasGradient, "Call to gradient not available");
1873 typedef typename BasisType::GradientValue ReturnValue;
1874 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1875 {
1876 return 0.5 * (basis.gradient(i, x) - basis.gradient(i, x).transpose());
1877 }
1878
1879 // Computes gradient value at quadrature node iqn, knowing gradients of ancestor basis at quadrature nodes
1880 static inline ReturnValue evaluate(
1881 const BasisType &basis,
1882 size_t i,
1883 size_t iqn,
1884 const boost::multi_array<ReturnValue, 2> &ancestor_gradient_quad
1885 )
1886 {
1887 return 0.5 * (basis.gradient(i, iqn, ancestor_gradient_quad) - basis.gradient(i, iqn, ancestor_gradient_quad).transpose());
1888 }
1889 };
1890
1891 // Evaluate the curl value at x
1892 template<typename BasisType>
1894 {
1895 static_assert(BasisType::hasCurl, "Call to curl not available");
1896 typedef typename BasisType::CurlValue ReturnValue;
1897 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1898 {
1899 return basis.curl(i, x);
1900 }
1901
1902 // Computes curl value at quadrature node iqn, knowing curls of ancestor basis at quadrature nodes
1903 static inline ReturnValue evaluate(
1904 const BasisType &basis,
1905 size_t i,
1906 size_t iqn,
1907 const boost::multi_array<ReturnValue, 2> &ancestor_curl_quad
1908 )
1909 {
1910 return basis.curl(i, iqn, ancestor_curl_quad);
1911 }
1912 };
1913
1914 // Evaluate the divergence value at x
1915 template<typename BasisType>
1917 {
1918 static_assert(BasisType::hasDivergence, "Call to divergence not available");
1919 typedef typename BasisType::DivergenceValue ReturnValue;
1920 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1921 {
1922 return basis.divergence(i, x);
1923 }
1924
1925 // Computes divergence value at quadrature node iqn, knowing divergences of ancestor basis at quadrature nodes
1926 static inline ReturnValue evaluate(
1927 const BasisType &basis,
1928 size_t i,
1929 size_t iqn,
1930 const boost::multi_array<ReturnValue, 2> &ancestor_divergence_quad
1931 )
1932 {
1933 return basis.divergence(i, iqn, ancestor_divergence_quad);
1934 }
1935 };
1936
1937 // Evaluate the rotor value at x
1938 template<typename BasisType>
1940 {
1941 static_assert(BasisType::hasRotor, "Call to rotor not available");
1942 typedef typename BasisType::RotorValue ReturnValue;
1943 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1944 {
1945 return basis.rotor(i, x);
1946 }
1947
1948 // Computes rotor value at quadrature node iqn, knowing rotors of ancestor basis at quadrature nodes
1949 static inline ReturnValue evaluate(
1950 const BasisType &basis,
1951 size_t i,
1952 size_t iqn,
1953 const boost::multi_array<ReturnValue, 2> &ancestor_rotor_quad
1954 )
1955 {
1956 return basis.rotor(i, iqn, ancestor_rotor_quad);
1957 }
1958 };
1959
1960 // Evaluate the Hessian value at x
1961 template<typename BasisType>
1963 {
1964 static_assert(BasisType::hasHessian, "Call to Hessian not available");
1965 typedef typename BasisType::HessianValue ReturnValue;
1966 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1967 {
1968 return basis.hessian(i, x);
1969 }
1970
1971 // Computes Hessian value at quadrature node iqn, knowing Hessians of ancestor basis at quadrature nodes
1972 static inline ReturnValue evaluate(
1973 const BasisType &basis,
1974 size_t i,
1975 size_t iqn,
1976 const boost::multi_array<ReturnValue, 2> &ancestor_hessian_quad
1977 )
1978 {
1979 return basis.hessian(i, iqn, ancestor_hessian_quad);
1980 }
1981 };
1982
1983 //---------- TENSORIZED FAMILY EVALUATION TRAITS -----------------------------------------
1984 // Evaluate the value at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
1985 template <typename ScalarBasisType, size_t N>
1987 {
1988 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasFunction, "Call to function not available");
1989
1991 static const BasisFunctionE AncestorBasisFunction = Function; // Type of values needed from ancestor basis
1993
1994 // Computes function values at x
1995 static inline ReturnValue evaluate(
1997 size_t i,
1998 const VectorRd &x
1999 )
2000 {
2001 return basis.function(i, x);
2002 }
2003
2004 // Computes function value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2005 static inline ReturnValue evaluate(
2007 size_t i,
2008 size_t iqn,
2009 const boost::multi_array<double, 2> &ancestor_basis_quad
2010 )
2011 {
2012 return basis.function(i, iqn, ancestor_basis_quad);
2013 }
2014 };
2015
2016 // Evaluate the gradient at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2017 template <typename ScalarBasisType, size_t N>
2019 {
2020 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasGradient, "Call to gradient not available");
2021
2023 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2025
2026 // Computes gradient value at x
2027 static inline ReturnValue evaluate(
2029 size_t i,
2030 const VectorRd &x
2031 )
2032 {
2033 return basis.gradient(i, x);
2034 }
2035
2036 // Computes gradient value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2037 static inline ReturnValue evaluate(
2039 size_t i,
2040 size_t iqn,
2041 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2042 )
2043 {
2044 return basis.gradient(i, iqn, ancestor_basis_quad);
2045 }
2046 };
2047
2048 // AC - supposed to be used only in case of vector variables (vhhospace)
2049 // Evaluate the symmetric gradient at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2050 template <typename ScalarBasisType, size_t N>
2052 {
2053 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasGradient, "Call to gradient not available");
2054
2056 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2058
2059 // Computes gradient value at x
2060 static inline ReturnValue evaluate(
2062 size_t i,
2063 const VectorRd &x
2064 )
2065 {
2066 return 0.5 * (basis.gradient(i, x) + basis.gradient(i, x).transpose()) ;
2067 }
2068
2069 // Computes gradient value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2070 static inline ReturnValue evaluate(
2072 size_t i,
2073 size_t iqn,
2074 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2075 )
2076 {
2077 return 0.5 * (basis.gradient(i, iqn, ancestor_basis_quad) + basis.gradient(i, iqn, ancestor_basis_quad).transpose());
2078 }
2079 };
2080
2081 // AC - supposed to be used only in case of vector variables (so gradient is a matrix)
2082 // Evaluate the symmetric gradient at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2083 template <typename ScalarBasisType, size_t N>
2085 {
2086 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasGradient, "Call to gradient not available");
2087
2089 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2091
2092 // Computes gradient value at x
2093 static inline ReturnValue evaluate(
2095 size_t i,
2096 const VectorRd &x
2097 )
2098 {
2099 return 0.5 * (basis.gradient(i, x) - basis.gradient(i, x).transpose()) ;
2100 }
2101
2102 // Computes gradient value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2103 static inline ReturnValue evaluate(
2105 size_t i,
2106 size_t iqn,
2107 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2108 )
2109 {
2110 return 0.5 * (basis.gradient(i, iqn, ancestor_basis_quad) - basis.gradient(i, iqn, ancestor_basis_quad).transpose());
2111 }
2112 };
2113
2114 // Evaluate the curl at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2115 template <typename ScalarBasisType, size_t N>
2117 {
2118 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasCurl, "Call to curl not available");
2119
2121 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2123
2124 // Computes curl values at x
2125 static inline ReturnValue evaluate(
2127 size_t i,
2128 const VectorRd &x
2129 )
2130 {
2131 return basis.curl(i, x);
2132 }
2133
2134 // Computes curl values at quadrature node iqn, knowing ancestor basis at quadrature nodes
2135 static inline ReturnValue evaluate(
2137 size_t i,
2138 size_t iqn,
2139 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2140 )
2141 {
2142 return basis.curl(i, iqn, ancestor_basis_quad);
2143 }
2144
2145 };
2146
2147 // Evaluate the divergence at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2148 template <typename ScalarBasisType, size_t N>
2150 {
2151 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasDivergence, "Call to divergence not available");
2152
2154 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2156
2157 // Computes divergence value at x
2158 static inline ReturnValue evaluate(
2160 size_t i,
2161 const VectorRd &x
2162 )
2163 {
2164 return basis.divergence(i, x);
2165 }
2166
2167 // Computes divergence value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2168 static inline ReturnValue evaluate(
2170 size_t i,
2171 size_t iqn,
2172 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2173 )
2174 {
2175 return basis.divergence(i, iqn, ancestor_basis_quad);
2176 }
2177
2178 };
2179
2180 // Evaluate the rotor at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2181 template <typename ScalarBasisType, size_t N>
2183 {
2184 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasRotor, "Call to rotor not available");
2185
2187 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2189
2190 // Computes divergence value at x
2191 static inline ReturnValue evaluate(
2193 size_t i,
2194 const VectorRd &x
2195 )
2196 {
2197 return basis.rotor(i, x);
2198 }
2199
2200 // Computes rotor value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2201 static inline ReturnValue evaluate(
2203 size_t i,
2204 size_t iqn,
2205 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2206 )
2207 {
2208 return basis.rotor(i, iqn, ancestor_basis_quad);
2209 }
2210
2211 };
2212
2213 //---------- MATRIX FAMILY EVALUATION TRAITS -----------------------------------------
2214 // Evaluate the value at x of a MatrixFamily (includes information on the ancestor basis, to optimise eval_quad for matrix families)
2215 template <typename ScalarBasisType, size_t N>
2216 struct basis_evaluation_traits<MatrixFamily<ScalarBasisType, N>, Function>
2217 {
2218 static_assert(MatrixFamily<ScalarBasisType, N>::hasFunction, "Call to function not available");
2219
2221 static const BasisFunctionE AncestorBasisFunction = Function; // Type of values needed from ancestor basis
2223
2224 // Computes function values at x
2225 static inline ReturnValue evaluate(
2227 size_t i,
2228 const VectorRd &x
2229 )
2230 {
2231 return basis.function(i, x);
2232 }
2233
2234 // Computes function value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2235 static inline ReturnValue evaluate(
2237 size_t i,
2238 size_t iqn,
2239 const boost::multi_array<double, 2> &ancestor_basis_quad
2240 )
2241 {
2242 return basis.function(i, iqn, ancestor_basis_quad);
2243 }
2244 };
2245
2246 // Evaluate the divergence at x of a MatrixFamily (includes information on the ancestor basis, to optimise eval_quad for matrix families)
2247 template <typename ScalarBasisType, size_t N>
2249 {
2250 static_assert(MatrixFamily<ScalarBasisType, N>::hasDivergence, "Call to divergence not available");
2251
2253 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2255
2256 // Computes divergence value at x
2257 static inline ReturnValue evaluate(
2259 size_t i,
2260 const VectorRd &x
2261 )
2262 {
2263 return basis.divergence(i, x);
2264 }
2265
2266 // Computes divergence value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2267 static inline ReturnValue evaluate(
2269 size_t i,
2270 size_t iqn,
2271 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2272 )
2273 {
2274 return basis.divergence(i, iqn, ancestor_basis_quad);
2275 }
2276
2277 };
2278
2279
2280 // Evaluate the gradient at x of a MatrixFamily (includes information on the ancestor basis, to optimise eval_quad for matrix families)
2281 template <typename ScalarBasisType, size_t N>
2282 struct basis_evaluation_traits<MatrixFamily<ScalarBasisType, N>, Gradient>
2283 {
2284 static_assert(MatrixFamily<ScalarBasisType, N>::hasGradient, "Call to gradient not available");
2285
2287 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2289
2290 // Computes gradient value at x
2291 static inline ReturnValue evaluate(
2293 size_t i,
2294 const VectorRd &x
2295 )
2296 {
2297 return basis.gradient(i, x);
2298 }
2299
2300 // Computes gradient value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2301 static inline ReturnValue evaluate(
2303 size_t i,
2304 size_t iqn,
2305 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2306 )
2307 {
2308 return basis.gradient(i, iqn, ancestor_basis_quad);
2309 }
2310
2311 };
2312
2313 } // end of namespace detail
2314
2315
2316 //-----------------------------------EVALUATE_QUAD--------------------------------------
2317
2319 template<BasisFunctionE BasisFunction>
2322 template<typename BasisType>
2323 static boost::multi_array<typename detail::basis_evaluation_traits<BasisType, BasisFunction>::ReturnValue, 2>
2325 const BasisType & basis,
2326 const QuadratureRule & quad
2327 )
2328 {
2330
2331 boost::multi_array<typename traits::ReturnValue, 2>
2332 basis_quad( boost::extents[basis.dimension()][quad.size()] );
2333
2334 for (size_t i = 0; i < basis.dimension(); i++) {
2335 for (size_t iqn = 0; iqn < quad.size(); iqn++) {
2336 basis_quad[i][iqn] = traits::evaluate(basis, i, quad[iqn].vector());
2337 } // for iqn
2338 } // for i
2339
2340 return basis_quad;
2341 }
2342
2344 template<typename BasisType>
2345 static boost::multi_array<typename detail::basis_evaluation_traits<Family<BasisType>, BasisFunction>::ReturnValue, 2>
2347 const Family<BasisType> & basis,
2348 const QuadratureRule & quad
2349 )
2350 {
2351 typedef detail::basis_evaluation_traits<Family<BasisType>, BasisFunction> traits;
2352
2353 boost::multi_array<typename traits::ReturnValue, 2>
2354 basis_quad( boost::extents[basis.dimension()][quad.size()] );
2355
2356 // Compute values at quadrature note on ancestor basis, and then do a transformation
2357 const auto & ancestor_basis = basis.ancestor();
2358 boost::multi_array<typename traits::ReturnValue, 2>
2359 ancestor_basis_quad = evaluate_quad<BasisFunction>::compute(ancestor_basis, quad);
2360
2361 Eigen::MatrixXd M = basis.matrix();
2362 for (size_t i = 0; i < size_t(M.rows()); i++) {
2363 for (size_t iqn = 0; iqn < quad.size(); iqn++) {
2364 basis_quad[i][iqn] = M(i,0) * ancestor_basis_quad[0][iqn];
2365 }
2366 for (size_t j = 1; j < size_t(M.cols()); j++) {
2367 for (size_t iqn = 0; iqn < quad.size(); iqn++) {
2368 basis_quad[i][iqn] += M(i,j) * ancestor_basis_quad[j][iqn];
2369 }
2370 } // for j
2371 } // for i
2372
2373 return basis_quad;
2374 }
2375
2377 template <typename BasisType, size_t N>
2378 static boost::multi_array<typename detail::basis_evaluation_traits<TensorizedVectorFamily<BasisType, N>, BasisFunction>::ReturnValue, 2>
2381 const QuadratureRule &quad
2382 )
2383 {
2385
2386 boost::multi_array<typename traits::ReturnValue, 2>
2387 basis_quad(boost::extents[basis.dimension()][quad.size()]);
2388
2389 const auto &ancestor_basis = basis.ancestor();
2390 const boost::multi_array<typename traits::AncestorBasisFunctionValue, 2> ancestor_basis_quad
2392
2393 for (size_t i = 0; i < basis.dimension(); i++){
2394 for (size_t iqn = 0; iqn < quad.size(); iqn++){
2395 basis_quad[i][iqn] = traits::evaluate(basis, i, iqn, ancestor_basis_quad);
2396 }
2397 }
2398 return basis_quad;
2399 }
2400
2402 template <typename BasisType, size_t N>
2403 static boost::multi_array<typename detail::basis_evaluation_traits<MatrixFamily<BasisType, N>, BasisFunction>::ReturnValue, 2>
2405 const MatrixFamily<BasisType, N> &basis,
2406 const QuadratureRule &quad
2407 )
2408 {
2410
2411 boost::multi_array<typename traits::ReturnValue, 2>
2412 basis_quad(boost::extents[basis.dimension()][quad.size()]);
2413
2414 const auto &ancestor_basis = basis.ancestor();
2415 const boost::multi_array<typename traits::AncestorBasisFunctionValue, 2> ancestor_basis_quad
2417
2418 for (size_t i = 0; i < basis.dimension(); i++){
2419 for (size_t iqn = 0; iqn < quad.size(); iqn++){
2420 basis_quad[i][iqn] = traits::evaluate(basis, i, iqn, ancestor_basis_quad);
2421 }
2422 }
2423 return basis_quad;
2424 }
2425 };
2426
2427 //------------------------------------------------------------------------------
2428 // ORTHONORMALISATION
2429 //------------------------------------------------------------------------------
2430
2439 template<typename T>
2440 Eigen::MatrixXd gram_schmidt(
2441 boost::multi_array<T, 2> & basis_eval,
2442 const std::function<double(size_t, size_t)> & inner_product
2443 )
2444 {
2445 auto induced_norm = [inner_product](size_t i)->double
2446 {
2447 return std::sqrt( inner_product(i, i) );
2448 };
2449
2450 // Number of basis functions
2451 size_t Nb = basis_eval.shape()[0];
2452 // Number of quadrature nodes
2453 size_t Nqn = basis_eval.shape()[1];
2454
2455 Eigen::MatrixXd B = Eigen::MatrixXd::Zero(Nb, Nb);
2456
2457 // Normalise the first element
2458 double norm = induced_norm(0);
2459 for (size_t iqn = 0; iqn < Nqn; iqn++) {
2460 basis_eval[0][iqn] /= norm;
2461 } // for iqn
2462 B(0,0) = 1./norm;
2463
2464 for (size_t ib = 1; ib < Nb; ib++) {
2465 // 'coeffs' represents the coefficients of the ib-th orthogonal function on the ON basis functions 0 to ib-1
2466 Eigen::RowVectorXd coeffs = Eigen::RowVectorXd::Zero(ib);
2467 for (size_t pb = 0; pb < ib; pb++) {
2468 coeffs(pb) = - inner_product(ib, pb);
2469 } // for pb
2470
2471 // store the values of the orthogonalised ib-th basis function
2472 for (size_t pb = 0; pb < ib; pb++) {
2473 for (size_t iqn = 0; iqn < Nqn; iqn++) {
2474 basis_eval[ib][iqn] += coeffs(pb) * basis_eval[pb][iqn];
2475 } // for iqn
2476 } // for pb
2477
2478 // normalise ib-th basis function
2479 double norm = induced_norm(ib);
2480 for (size_t iqn = 0; iqn < Nqn; iqn++) {
2481 basis_eval[ib][iqn] /= norm;
2482 } // for iqn
2483 coeffs /= norm;
2484 // Compute ib-th row of B.
2485 // B.topLeftCorner(ib, ib) contains the rows that represent the ON basis functions 0 to ib-1 on
2486 // the original basis. Multiplying on the left by coeffs gives the coefficients of the ON basis
2487 // functions on the original basis functions from 0 to ib-1.
2488 B.block(ib, 0, 1, ib) = coeffs * B.topLeftCorner(ib, ib);
2489 B(ib, ib) = 1./norm;
2490 }
2491 return B;
2492 }
2493
2494 //------------------------------------------------------------------------------
2495
2497 double scalar_product(const double & x, const double & y);
2498
2500 double scalar_product(const VectorRd & x, const VectorRd & y);
2501
2503 template<int N>
2504 double scalar_product(const Eigen::Matrix<double, N, N> & x, const Eigen::Matrix<double, N, N> & y)
2505 {
2506 return (x.transpose() * y).trace();
2507 }
2508
2510 template <typename Value>
2511 boost::multi_array<double, 2> scalar_product(
2512 const boost::multi_array<Value, 2> &basis_quad,
2513 const Value &v
2514 )
2515 {
2516 boost::multi_array<double, 2> basis_dot_v_quad(boost::extents[basis_quad.shape()[0]][basis_quad.shape()[1]]);
2517 std::transform(basis_quad.origin(), basis_quad.origin() + basis_quad.num_elements(),
2518 basis_dot_v_quad.origin(), [&v](const Value &x) -> double { return scalar_product(x,v); });
2519 return basis_dot_v_quad;
2520 }
2521
2523 template <typename Value>
2524 boost::multi_array<double, 2> scalar_product(
2525 const boost::multi_array<Value, 2> & basis_quad,
2526 const std::vector<Value> & v
2527 )
2528 {
2529 boost::multi_array<double, 2> basis_dot_v_quad(boost::extents[basis_quad.shape()[0]][basis_quad.shape()[1]]);
2530 for (std::size_t i = 0; i < basis_quad.shape()[0]; i++) {
2531 for (std::size_t iqn = 0; iqn < basis_quad.shape()[1]; iqn++) {
2532 basis_dot_v_quad[i][iqn] = scalar_product(basis_quad[i][iqn], v[iqn]);
2533 } // for iqn
2534 } // for i
2535 return basis_dot_v_quad;
2536 }
2537
2539 boost::multi_array<VectorRd, 2> matrix_vector_product(
2540 const boost::multi_array<MatrixRd, 2> & basis_quad,
2541 const std::vector<VectorRd> & v_quad
2542 );
2543
2545 boost::multi_array<VectorRd, 2> matrix_vector_product(
2546 const std::vector<MatrixRd> & m_quad,
2547 const boost::multi_array<VectorRd, 2> & basis_quad
2548 );
2549
2551 boost::multi_array<VectorRd, 2> vector_matrix_product(
2552 const std::vector<VectorRd> & v_quad,
2553 const boost::multi_array<MatrixRd, 2> & basis_quad
2554 );
2555
2557 template<typename BasisType>
2559 const BasisType & basis,
2560 const QuadratureRule & qr,
2561 boost::multi_array<typename BasisType::FunctionValue, 2> & basis_quad
2562 )
2563 {
2564 // Check that the basis evaluation and quadrature rule are coherent
2565 assert ( basis.dimension() == basis_quad.shape()[0] && qr.size() == basis_quad.shape()[1] );
2566
2567 // The inner product between the i-th and j-th basis vectors
2568 std::function<double(size_t, size_t)> inner_product
2569 = [&basis_quad, &qr](size_t i, size_t j)->double
2570 {
2571 double r = 0.;
2572 for(size_t iqn = 0; iqn < qr.size(); iqn++) {
2573 r += qr[iqn].w * scalar_product(basis_quad[i][iqn], basis_quad[j][iqn]);
2574 } // for iqn
2575 return r;
2576 };
2577
2578 Eigen::MatrixXd B = gram_schmidt(basis_quad, inner_product);
2579
2580 return Family<BasisType>(basis, B);
2581 }
2582
2584 /* This method is more robust that the previous one based on values at quadrature nodes */
2585 template <typename BasisType>
2587 const BasisType &basis,
2588 const Eigen::MatrixXd & GM
2589 )
2590 {
2591 // Check that the basis and Gram matrix are coherent
2592 assert(basis.dimension() == size_t(GM.rows()) && GM.rows() == GM.cols());
2593
2594 Eigen::MatrixXd L = GM.llt().matrixL();
2595
2596 return Family<BasisType>(basis, L.inverse());
2597 }
2598
2599
2600 //------------------------------------------------------------------------------
2601 // GRAM MATRICES
2602 //------------------------------------------------------------------------------
2603
2605 template<typename FunctionValue>
2606 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> & B1,
2607 const boost::multi_array<FunctionValue, 2> & B2,
2608 const QuadratureRule & qr,
2609 const size_t nrows,
2610 const size_t ncols,
2611 const std::string sym = "nonsym"
2612 )
2613 {
2614 // Check that the basis evaluation and quadrature rule are coherent
2615 assert ( qr.size() == B1.shape()[1] && qr.size() == B2.shape()[1] );
2616 // Check that we don't ask for more members of family than available
2617 assert ( nrows <= B1.shape()[0] && ncols <= B2.shape()[0] );
2618
2619 // Re-cast quadrature weights into ArrayXd to make computations faster
2620 Eigen::ArrayXd qr_weights = Eigen::ArrayXd::Zero(qr.size());
2621 for (size_t iqn = 0; iqn < qr.size(); iqn++){
2622 qr_weights(iqn) = qr[iqn].w;
2623 }
2624
2625 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(nrows, ncols);
2626 for (size_t i = 0; i < nrows; i++) {
2627 size_t jcut = 0;
2628 if ( sym=="sym" ) jcut = i;
2629 for (size_t j = 0; j < jcut; j++){
2630 M(i, j) = M(j, i);
2631 }
2632 for(size_t j = jcut; j < ncols; j++) {
2633 std::vector<double> tmp(B1.shape()[1]);
2634 // Extract values at quadrature nodes for elements i of B1 and j of B2
2635 auto B1i = B1[ boost::indices[i][boost::multi_array_types::index_range(0, B1.shape()[1])] ];
2636 auto B2j = B2[ boost::indices[j][boost::multi_array_types::index_range(0, B1.shape()[1])] ];
2637 // Compute scalar product of B1i and B2j, and recast it as ArrayXd
2638 std::transform(B1i.begin(), B1i.end(), B2j.begin(), tmp.begin(), [](FunctionValue a, FunctionValue b)->double { return scalar_product(a,b);});
2639 Eigen::ArrayXd tmp_array = Eigen::Map<Eigen::ArrayXd, Eigen::Unaligned>(tmp.data(), tmp.size());
2640 // Multiply by quadrature weights and sum (using .sum() of ArrayXd makes this step faster than a loop)
2641 M(i,j) = (qr_weights * tmp_array).sum();
2642
2643
2644 // Simple version with loop (replaces everything above after the for on j)
2645 /*
2646 for (size_t iqn = 0; iqn < qr.size(); iqn++) {
2647 M(i,j) += qr[iqn].w * scalar_product(B1[i][iqn], B2[j][iqn]);
2648 } // for iqn
2649 */
2650
2651 } // for j
2652 } // for i
2653 return M;
2654 }
2655
2657 template<typename FunctionValue>
2658 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> & B1,
2659 const boost::multi_array<FunctionValue, 2> & B2,
2660 const QuadratureRule & qr,
2661 const std::string sym = "nonsym"
2662 )
2663 {
2664 return compute_gram_matrix<FunctionValue>(B1, B2, qr, B1.shape()[0], B2.shape()[0], sym);
2665 }
2666
2668 template<typename FunctionValue>
2669 inline Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> & B,
2670 const QuadratureRule & qr
2671 )
2672 {
2673 return compute_gram_matrix<FunctionValue>(B, B, qr, "sym");
2674 }
2675
2677 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> & B1,
2678 const boost::multi_array<double, 2> & B2,
2679 const QuadratureRule & qr
2680 );
2681
2683 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<double, 2> & B1,
2684 const boost::multi_array<double, 2> & B2,
2685 const QuadratureRule & qr,
2686 const size_t nrows,
2687 const size_t ncols,
2688 const std::string sym = "nonsym"
2689 );
2690
2692 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<double, 2> & B1,
2693 const boost::multi_array<double, 2> & B2,
2694 const QuadratureRule & qr,
2695 const std::string sym = "nonsym"
2696 );
2697
2699 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> & B1,
2700 const boost::multi_array<VectorRd, 2> & B2,
2701 const QuadratureRule & qr,
2702 const size_t nrows,
2703 const size_t ncols,
2704 const std::string sym = "nonsym"
2705 );
2706
2708 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> & B1,
2709 const boost::multi_array<VectorRd, 2> & B2,
2710 const QuadratureRule & qr,
2711 const std::string sym = "nonsym"
2712 );
2713
2715 template<typename ScalarFamilyType, size_t N>
2717 const boost::multi_array<double, 2> & scalar_family_quad,
2718 const QuadratureRule & qr
2719 )
2720 {
2721 Eigen::MatrixXd Gram = Eigen::MatrixXd::Zero(MatFam.dimension(), MatFam.dimension());
2722
2723 // Gram matrix of the scalar family
2724 Eigen::MatrixXd scalarGram = compute_gram_matrix<double>(scalar_family_quad, qr);
2725 for (size_t i = 0; i < MatFam.dimension(); i = i+scalarGram.rows()){
2726 Gram.block(i, i, scalarGram.rows(), scalarGram.cols()) = scalarGram;
2727 }
2728
2729 return Gram;
2730 }
2731
2732
2734
2735 template <typename T>
2736 Eigen::VectorXd integrate(
2737 const FType<T> &f,
2738 const BasisQuad<T> &B,
2739 const QuadratureRule &qr,
2740 size_t n_rows = 0
2741 )
2742 {
2743 // If default, set n_rows to size of family
2744 if (n_rows == 0)
2745 {
2746 n_rows = B.shape()[0];
2747 }
2748
2749 // Number of quadrature nodes
2750 const size_t num_quads = qr.size();
2751
2752 // Check number of quadrature nodes is compatible with B
2753 assert(num_quads == B.shape()[1]);
2754
2755 // Check that we don't ask for more members of family than available
2756 assert(n_rows <= B.shape()[0]);
2757
2758 Eigen::VectorXd V = Eigen::VectorXd::Zero(n_rows);
2759
2760 for (size_t iqn = 0; iqn < num_quads; iqn++)
2761 {
2762 double qr_weight = qr[iqn].w;
2763 T f_on_qr = f(qr[iqn].vector());
2764 for (size_t i = 0; i < n_rows; i++)
2765 {
2766 V(i) += qr_weight * scalar_product(B[i][iqn], f_on_qr);
2767 }
2768 }
2769
2770 return V;
2771 }
2772
2774 template <typename T, typename U>
2776 const FType<U> &f,
2777 const BasisQuad<T> &B1,
2778 const BasisQuad<T> &B2,
2779 const QuadratureRule &qr,
2780 size_t n_rows = 0,
2781 size_t n_cols = 0,
2782 const std::string sym = "nonsym"
2783 )
2784 {
2785 // If default, set n_rows and n_cols to size of families
2786 if (n_rows == 0 && n_cols == 0)
2787 {
2788 n_rows = B1.shape()[0];
2789 n_cols = B2.shape()[0];
2790 }
2791
2792 // Number of quadrature nodes
2793 const size_t num_quads = qr.size();
2794 // Check number of quadrature nodes is compatible with B1 and B2
2795 assert(num_quads == B1.shape()[1] && num_quads == B2.shape()[1]);
2796 // Check that we don't ask for more members of family than available
2797 assert(n_rows <= B1.shape()[0] && n_cols <= B2.shape()[0]);
2798
2799 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(n_rows, n_cols);
2800 for (size_t iqn = 0; iqn < num_quads; iqn++)
2801 {
2802 double qr_weight = qr[iqn].w;
2803 U f_on_qr = f(qr[iqn].vector());
2804 for (size_t i = 0; i < n_rows; i++)
2805 {
2806 T f_B1 = f_on_qr * B1[i][iqn];
2807 size_t jcut = 0;
2808 if (sym == "sym")
2809 jcut = i;
2810 for (size_t j = 0; j < jcut; j++)
2811 {
2812 M(i, j) = M(j, i);
2813 }
2814 for (size_t j = jcut; j < n_cols; j++)
2815 {
2816 M(i, j) += qr_weight * scalar_product(f_B1, B2[j][iqn]);
2817 }
2818 }
2819 }
2820 return M;
2821 }
2822
2824 template <typename T, typename U>
2826 const FType<U> &f,
2827 const BasisQuad<T> &B1,
2828 const BasisQuad<T> &B2,
2829 const QuadratureRule &qr,
2830 const std::string sym
2831 )
2832 {
2833 return compute_weighted_gram_matrix(f, B1, B2, qr, B1.shape()[0], B2.shape()[0], sym);
2834 }
2835
2837 Eigen::MatrixXd compute_weighted_gram_matrix(
2838 const FType<VectorRd> &f,
2839 const BasisQuad<VectorRd> &B1,
2840 const BasisQuad<double> &B2,
2841 const QuadratureRule &qr,
2842 size_t n_rows = 0,
2843 size_t n_cols = 0
2844 );
2845
2846
2848 Eigen::MatrixXd compute_weighted_gram_matrix(
2849 const FType<VectorRd> &f,
2850 const BasisQuad<double> &B1,
2851 const BasisQuad<VectorRd> &B2,
2852 const QuadratureRule &qr,
2853 size_t n_rows = 0,
2854 size_t n_cols = 0
2855 );
2856
2858 template <typename Value>
2859 Eigen::MatrixXd compute_closure_matrix(
2860 const boost::multi_array<Value, 2> & f_quad,
2861 const boost::multi_array<Value, 2> & g_quad,
2862 const QuadratureRule & qr_f,
2863 const QuadratureRule & qr_g
2864 )
2865 {
2866 const size_t dimf = f_quad.shape()[0];
2867 const size_t dimg = g_quad.shape()[0];
2868 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(dimf, dimg);
2869
2870 std::vector<Value> int_f(dimf);
2871 for (size_t i = 0; i < dimf; i++){
2872 int_f[i] = qr_f[0].w * f_quad[i][0];
2873 for (size_t iqn = 1; iqn < qr_f.size(); iqn++){
2874 int_f[i] += qr_f[iqn].w * f_quad[i][iqn];
2875 }
2876 }
2877 std::vector<Value> int_g(dimg);
2878 for (size_t j = 0; j < dimg; j++){
2879 int_g[j] = qr_g[0].w * g_quad[j][0];
2880 for (size_t iqn = 1; iqn < qr_g.size(); iqn++){
2881 int_g[j] += qr_g[iqn].w * g_quad[j][iqn];
2882 }
2883 }
2884
2885 // Compute (int w_i) and create dot product with (int w_j) for j<=i, then fill in M by symmetry
2886 for (size_t i = 0; i < dimf; i++){
2887 for (size_t j = 0; j < dimg; j++){
2888 M(i,j) = scalar_product(int_f[i], int_g[j]);
2889 }
2890 }
2891
2892 return M;
2893 }
2894
2896 template <typename Value>
2897 Eigen::MatrixXd compute_closure_matrix(
2898 const boost::multi_array<Value, 2> & f_quad,
2899 const boost::multi_array<Value, 2> & g_quad,
2900 const QuadratureRule & qr
2901 )
2902 {
2903 return compute_closure_matrix(f_quad, g_quad, qr, qr);
2904 }
2905
2907 template <typename Value>
2908 Eigen::MatrixXd compute_closure_matrix(
2909 const boost::multi_array<Value, 2> & f_quad,
2910 const QuadratureRule & qr
2911 )
2912 {
2913 return compute_closure_matrix(f_quad, f_quad, qr, qr);
2914 }
2915
2916 //------------------------------------------------------------------------------
2917 // L2 projection of a function
2918 //------------------------------------------------------------------------------
2919
2921 template<typename BasisType>
2922 Eigen::VectorXd l2_projection(
2923 const std::function<typename BasisType::FunctionValue(const VectorRd &)> & f,
2924 const BasisType & basis,
2925 QuadratureRule & quad,
2926 const boost::multi_array<typename BasisType::FunctionValue, 2> & basis_quad,
2927 const Eigen::MatrixXd &mass_basis = Eigen::MatrixXd::Zero(1,1)
2928 )
2929 {
2930 Eigen::MatrixXd Mass = mass_basis;
2931 if (Mass.norm() < 1e-13){
2932 Mass = compute_gram_matrix(basis_quad, quad);
2933 }
2934
2935 Eigen::LDLT<Eigen::MatrixXd> cholesky_mass(Mass);
2936 Eigen::VectorXd b = Eigen::VectorXd::Zero(basis.dimension());
2937 for (size_t i = 0; i < basis.dimension(); i++) {
2938 for (size_t iqn = 0; iqn < quad.size(); iqn++) {
2939 b(i) += quad[iqn].w * scalar_product(f(quad[iqn].vector()), basis_quad[i][iqn]);
2940 } // for iqn
2941 } // for i
2942
2943 return cholesky_mass.solve(b);
2944 }
2945
2946 //------------------------------------------------------------------------------
2947 // Decomposition on a polynomial basis
2948 //------------------------------------------------------------------------------
2949
2951
2956 template <typename BasisType>
2958 {
2960
2966 const Edge &E,
2967 const BasisType &basis
2968 ):
2969 m_dim(basis.dimension()),
2970 m_basis(basis),
2971 m_on_basis(basis, Eigen::MatrixXd::Identity(m_dim,m_dim)) // Need to initialise before we compute the real ON basis
2972 {
2973 /* The decomposition will be performed using an orthonormalised version of m_basis, for stability.
2974 The scalar product for which we orthonormalise is a minimal one (much less expensive than integrating
2975 over the edge): \sum_i phi(x_i) psi(x_i) where (x_i)_i are nodes that are sufficient to determine
2976 entirely polynomials up to the considered degree.
2977 The nodes we build here correspond to equidistant P^k nodes on the edge */
2978
2979 // Nodes
2980 m_nb_nodes = basis.max_degree() + 1;
2981 m_nodes.reserve(m_nb_nodes);
2982 double h = 1./std::max(1., double(basis.max_degree()));
2983 for (size_t i=0; i<m_nb_nodes; i++){
2984 VectorRd xi = E.vertex(0)->coords() + double(i) * h * (E.vertex(1)->coords() - E.vertex(0)->coords());
2985 m_nodes.emplace_back(xi.x(), xi.y(), 1.);
2986 }
2987
2988 // We then orthonormalise Orthonormalise basis for simple scalar product
2989 m_on_basis_nodes.resize(boost::extents[m_dim][m_nb_nodes]);
2992 };
2993
2996 const Cell &T,
2997 const BasisType &basis
2998 ):
2999 m_dim(basis.dimension()),
3000 m_basis(basis),
3001 m_on_basis(basis, Eigen::MatrixXd::Identity(m_dim,m_dim)) // Need to initialise before we compute the real ON basis
3002 {
3003 /* The decomposition will be performed using an orthonormalised version of m_basis, for stability.
3004 The scalar product for which we orthonormalise is a minimal one (much less expensive than integrating
3005 over the cell): \sum_i phi(x_i) psi(x_i) where (x_i)_i are nodes that are sufficient to determine
3006 entirely polynomials up to the considered degree.
3007 The nodes we build here correspond to P^k nodes on a tetrahedron */
3008
3009 // Create nodes
3010 std::vector<Eigen::Vector2i> indices = MonomialPowers<Cell>::complete(basis.max_degree());
3011 VectorRd e1 = VectorRd(1., 0.);
3012 VectorRd e2 = VectorRd(0., 1.);
3013 VectorRd x0 = T.center_mass() - T.diam()*VectorRd(1., 1.)/2.0;
3014
3015 // Nodes
3016 m_nb_nodes = indices.size();
3017 m_nodes.reserve(m_nb_nodes);
3018 for (size_t i=0; i<m_nb_nodes; i++){
3019 VectorRd xi = x0 + T.diam()*(double(indices[i](0)) * e1 + double(indices[i](1)) * e2)/std::max(1.,double(basis.max_degree()));
3020 m_nodes.emplace_back(xi.x(), xi.y(), 1.);
3021 }
3022
3023 // We then orthonormalise Orthonormalise basis for simple scalar product
3024 m_on_basis_nodes.resize(boost::extents[m_dim][m_nb_nodes]);
3027 };
3028
3031 {
3032 return m_nodes;
3033 };
3034
3037 boost::multi_array<typename BasisType::FunctionValue, 2> &values
3038 )
3039 {
3040 // Gram matrix of the polynomials and the ON basis
3041 Eigen::MatrixXd Gram_P_onbasis = compute_gram_matrix(values, m_on_basis_nodes, m_nodes);
3042 // L=matrix of P as a family of the ON basis. In theory, Gram_onbasis is identity, but due to rounding errors it
3043 // can be a bit different. Computing L as if it's not the case improves stability
3044 Eigen::MatrixXd Gram_onbasis = compute_gram_matrix(m_on_basis_nodes, m_nodes);
3045 Eigen::MatrixXd L = Gram_onbasis.ldlt().solve(Gram_P_onbasis.transpose());
3046 return Family<BasisType>(m_basis, L.transpose() * m_on_basis.matrix());
3047 };
3048
3049
3050 // Member variables
3051 size_t m_dim; // dimension of basis
3052 BasisType m_basis; // Basis on which we decompose
3053 Family<BasisType> m_on_basis; // Orthonormalised basis (for simple scalar product)
3054 boost::multi_array<typename BasisType::FunctionValue, 2> m_on_basis_nodes; // Values of ON basis at the nodes
3055 size_t m_nb_nodes; // nb of nodes
3057
3058 };
3059
3060
3062
3063} // end of namespace HArDCore2D
3064
3065#endif
Basis for the space of curls (vectorial rot) of polynomials.
Definition basis.hpp:1271
Basis (or rather family) of divergence of an existing basis.
Definition basis.hpp:1334
Definition basis.hpp:313
Basis for the complement G^{c,k}(T) in P^k(F)^2 of the range of the gradient on a face.
Definition basis.hpp:1587
Basis for the space of gradients of polynomials.
Definition basis.hpp:1209
Basis for the space of Hessians of polynomials.
Definition basis.hpp:1457
Basis for the complement H^{c,k}(T) in P^k(T)^{2x2} of the range of the Hessian on a face.
Definition basis.hpp:1639
Matrix family obtained from a scalar family.
Definition basis.hpp:721
Scalar monomial basis on a cell.
Definition basis.hpp:168
Scalar monomial basis on an edge.
Definition basis.hpp:242
Generate a basis restricted to the first "dimension" functions.
Definition basis.hpp:1099
Basis for the complement R^{c,k}(T) in P^k(T)^2 of the range of the vectorial rotational on a face.
Definition basis.hpp:1521
Basis (or rather family) of scalar rotor of an existing basis.
Definition basis.hpp:1394
Generate a basis where the function indices are shifted.
Definition basis.hpp:989
Vector family for polynomial functions that are tangent to an edge (determined by the generator)
Definition basis.hpp:912
Vector family obtained by tensorization of a scalar family.
Definition basis.hpp:561
Compute max and min eigenvalues of all matrices for i
Definition compute_eigs.m:5
function[maxeig, mineig, cond, mat]
Definition compute_eigs.m:1
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2027
void RotorValue
Definition basis.hpp:1464
static constexpr const TensorRankE tensorRank
Definition basis.hpp:572
VectorRd CurlValue
Definition basis.hpp:1398
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1598
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1243
TensorizedVectorFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition basis.hpp:2055
static const bool hasRotor
Definition basis.hpp:1538
Eigen::Matrix< double, N, dimspace > GradientValue
Definition basis.hpp:564
static const bool hasGradient
Definition basis.hpp:1535
MatrixGradient(Eigen::Matrix< double, N, N > diff_x, Eigen::Matrix< double, N, N > diff_y)
Constructor.
Definition basis.hpp:115
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th function at point x.
Definition basis.hpp:380
BasisType::GradientValue GradientValue
Definition basis.hpp:316
Cell GeometricSupport
Definition basis.hpp:1649
static const bool hasFunction
Definition basis.hpp:255
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:281
BasisType AncestorType
Definition basis.hpp:1414
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:2379
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:2070
static const bool hasDivergence
Definition basis.hpp:1115
MatrixFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition basis.hpp:2286
VectorRd FunctionValue
Definition basis.hpp:1523
static const bool hasFunction
Definition basis.hpp:1002
static constexpr const bool hasAncestor
Definition basis.hpp:1652
size_t dimension() const
Return the dimension of the family.
Definition basis.hpp:948
double DivergenceValue
Definition basis.hpp:1339
VectorRd CurlValue
Definition basis.hpp:246
BasisType::RotorValue ReturnValue
Definition basis.hpp:1942
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the Hessian of the i-th basis function at point x.
Definition basis.hpp:484
static const bool hasGradient
Definition basis.hpp:575
static const bool hasFunction
Definition basis.hpp:574
const size_t matrixSize() const
Return the dimension of the matrices in the family.
Definition basis.hpp:835
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:667
BasisType m_basis
Definition basis.hpp:3052
static constexpr const bool hasAncestor
Definition basis.hpp:924
BasisType::FunctionValue FunctionValue
Definition basis.hpp:315
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1532
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1494
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th function at point x.
Definition basis.hpp:353
static std::vector< VectorZd > complete(size_t degree)
Definition basis.hpp:88
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2257
BasisType::FunctionValue ReturnValue
Definition basis.hpp:1801
static constexpr const bool hasAncestor
Definition basis.hpp:733
static const bool hasHessian
Definition basis.hpp:1539
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition basis.hpp:643
static const bool hasDivergence
Definition basis.hpp:184
size_t dimension() const
Return the dimension of the family.
Definition basis.hpp:769
void RotorValue
Definition basis.hpp:1527
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1280
Eigen::MatrixXd compute_closure_matrix(const boost::multi_array< Value, 2 > &f_quad, const boost::multi_array< Value, 2 > &g_quad, const QuadratureRule &qr_f, const QuadratureRule &qr_g)
Computes closure equation matrices, from evaluations at quadrature nodes. For two families of functio...
Definition basis.hpp:2859
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1158
CurlBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1294
void HessianValue
Definition basis.hpp:568
BasisType::HessianValue HessianValue
Definition basis.hpp:320
MatrixGradient()
Default constructor.
Definition basis.hpp:125
VectorRd CurlValue
Definition basis.hpp:1338
BasisFunctionE
Definition basis.hpp:1700
double FunctionValue
Definition basis.hpp:1336
void RotorValue
Definition basis.hpp:174
static const bool hasHessian
Definition basis.hpp:1658
static const bool hasCurl
Definition basis.hpp:1475
static const bool hasFunction
Definition basis.hpp:1346
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_hessian_quad)
Definition basis.hpp:1972
static const bool hasDivergence
Definition basis.hpp:928
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:322
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_gradient_quad)
Definition basis.hpp:1880
static const bool hasRotor
Definition basis.hpp:1477
static constexpr const TensorRankE tensorRank
Definition basis.hpp:923
DivergenceBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1355
static constexpr const bool hasAncestor
Definition basis.hpp:1406
static constexpr const bool hasAncestor
Definition basis.hpp:1111
VectorRd CurlValue
Definition basis.hpp:916
static const bool hasGradient
Definition basis.hpp:1285
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_divergence_quad)
Definition basis.hpp:1926
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1405
void HessianValue
Definition basis.hpp:919
Eigen::Vector2d VectorRd
Definition basis.hpp:55
Eigen::Vector2i VectorZd
Definition basis.hpp:56
BasisType::RotorValue RotorValue
Definition basis.hpp:995
void DivergenceValue
Definition basis.hpp:1592
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1403
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition basis.hpp:1275
static const bool hasHessian
Definition basis.hpp:930
static const bool hasGradient
Definition basis.hpp:926
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition basis.hpp:1274
boost::multi_array< VectorRd, 2 > matrix_vector_product(const boost::multi_array< MatrixRd, 2 > &basis_quad, const std::vector< VectorRd > &v_quad)
Take the product of a matrix-valued basis with a vector.
Definition basis.cpp:175
BasisType::DivergenceValue DivergenceValue
Definition basis.hpp:318
Family(const BasisType &basis, const Eigen::MatrixXd &matrix)
Constructor.
Definition basis.hpp:336
TensorizedVectorFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition basis.hpp:2022
BasisType::GradientValue GradientValue
Definition basis.hpp:1102
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2291
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1874
static const bool hasRotor
Definition basis.hpp:1116
static const bool hasRotor
Definition basis.hpp:737
BasisType AncestorType
Definition basis.hpp:1480
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:2346
void GradientValue
Definition basis.hpp:1643
static const bool hasFunction
Definition basis.hpp:1653
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_curl_quad)
Definition basis.hpp:1903
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.cpp:31
constexpr const ScalarFamilyType & ancestor() const
Return the ancestor (family that has been tensorized)
Definition basis.hpp:691
static const bool hasRotor
Definition basis.hpp:1288
BasisType AncestorType
Definition basis.hpp:333
static const bool hasDivergence
Definition basis.hpp:258
static const bool hasCurl
Definition basis.hpp:257
void HessianValue
Definition basis.hpp:1216
static const bool hasCurl
Definition basis.hpp:927
size_t dimension() const
Dimension of the family. This is actually the number of functions in the family, not necessarily line...
Definition basis.hpp:347
static const bool hasDivergence
Definition basis.hpp:1476
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1255
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:2235
static const bool hasCurl
Definition basis.hpp:1602
void GradientValue
Definition basis.hpp:1461
RotorValue rotor(size_t i, size_t iqn, const boost::multi_array< VectorRd, 2 > &ancestor_gradient_quad) const
Evaluate the scalar rotor of the i-th basis function at a quadrature point iqn, knowing all the gradi...
Definition basis.hpp:683
void HessianValue
Definition basis.hpp:249
RestrictedBasis(const BasisType &basis, const size_t &dimension)
Constructor.
Definition basis.hpp:1122
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2191
BasisType::CurlValue CurlValue
Definition basis.hpp:993
static const bool hasFunction
Definition basis.hpp:1222
BasisType::HessianValue HessianValue
Definition basis.hpp:1106
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1310
Edge GeometricSupport
Definition basis.hpp:921
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2060
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:847
GradientBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1234
boost::multi_array< T, 2 > BasisQuad
type for a family of basis functions evaluated on quadrature nodes
Definition basis.hpp:61
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:800
VectorRd generator() const
Returns the generator of the basis functions.
Definition basis.hpp:972
static const bool hasCurl
Definition basis.hpp:579
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1282
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.hpp:623
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.cpp:76
static const bool hasDivergence
Definition basis.hpp:329
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1428
TensorizedVectorFamily< ScalarBasisType, N >::FunctionValue ReturnValue
Definition basis.hpp:1990
void DivergenceValue
Definition basis.hpp:247
static const bool hasHessian
Definition basis.hpp:1350
VectorRd FunctionValue
Definition basis.hpp:1589
static const bool hasHessian
Definition basis.hpp:1229
Cell GeometricSupport
Definition basis.hpp:1596
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:841
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.hpp:809
MatrixGradient & operator+=(const MatrixGradient &G)
Increment.
Definition basis.hpp:137
void RotorValue
Definition basis.hpp:918
RotorBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1417
VectorRd GradientValue
Definition basis.hpp:1397
ScalarFamilyType AncestorType
Definition basis.hpp:741
size_t dimension() const
Return the dimension of the basis.
Definition basis.hpp:1135
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:633
Cell GeometricSupport
Definition basis.hpp:177
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:393
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:603
MatrixGradient< N > GradientValue
Definition basis.hpp:724
double scalar_product(const double &x, const double &y)
Scalar product between two reals.
Definition basis.cpp:163
void HessianValue
Definition basis.hpp:1465
size_t dimension() const
Dimension of the basis.
Definition basis.hpp:1614
Eigen::Matrix< double, N, 1 > FunctionValue
Definition basis.hpp:563
void DivergenceValue
Definition basis.hpp:1645
FunctionValue function(size_t i, size_t iqn, const boost::multi_array< double, 2 > &ancestor_value_quad) const
Evaluate the i-th basis function at a quadrature point iqn, knowing all the values of ancestor basis ...
Definition basis.hpp:613
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:239
void DivergenceValue
Definition basis.hpp:173
BasisType::FunctionValue FunctionValue
Definition basis.hpp:1101
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1467
static constexpr const bool hasAncestor
Definition basis.hpp:1221
QuadratureRule m_nodes
Nodes for the interpolation.
Definition basis.hpp:3056
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:1771
BasisType AncestorType
Definition basis.hpp:1119
BasisType::GradientValue ReturnValue
Definition basis.hpp:1825
TensorizedVectorFamily< ScalarBasisType, N >::CurlValue ReturnValue
Definition basis.hpp:2120
static constexpr const bool hasAncestor
Definition basis.hpp:573
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1000
MatrixRd HessianValue
Definition basis.hpp:175
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1249
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition basis.hpp:1212
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:2168
BasisType::RotorValue RotorValue
Definition basis.hpp:319
static const bool hasGradient
Definition basis.hpp:1113
BasisType::DivergenceValue ReturnValue
Definition basis.hpp:1919
static const bool hasCurl
Definition basis.hpp:738
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:697
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_gradient_quad)
Definition basis.hpp:1856
static const bool hasHessian
Definition basis.hpp:331
static const std::vector< VectorRd > basisRd
Definition basis.hpp:58
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:998
static const bool hasDivergence
Definition basis.hpp:577
static const bool hasDivergence
Definition basis.hpp:1410
static const bool hasHessian
Definition basis.hpp:739
static constexpr const bool hasAncestor
Definition basis.hpp:1470
void HessianValue
Definition basis.hpp:1278
static const bool hasHessian
Definition basis.hpp:1289
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1110
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:497
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:1147
TangentFamily(const ScalarFamilyType &scalar_family, const VectorRd &generator)
Constructor.
Definition basis.hpp:935
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:954
RotorValue rotor(size_t i, const VectorRd &x) const
Evaluate the scalar rotor of the i-th basis function at point x.
Definition basis.hpp:675
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1667
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition basis.hpp:659
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1548
MatrixFamily< ScalarBasisType, N >::DivergenceValue ReturnValue
Definition basis.hpp:2252
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:2037
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:368
BasisType::FunctionValue FunctionValue
Definition basis.hpp:991
void HessianValue
Definition basis.hpp:1528
static const bool hasHessian
Definition basis.hpp:1605
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1220
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1041
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2225
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:1713
static const bool hasDivergence
Definition basis.hpp:1349
static constexpr const TensorRankE tensorRank
Definition basis.hpp:253
size_t dimension() const
Return the dimension of the basis.
Definition basis.hpp:1023
VectorRd FunctionValue
Definition basis.hpp:914
static const bool hasHessian
Definition basis.hpp:260
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:2404
static const bool hasFunction
Definition basis.hpp:925
RotorValue rotor(size_t i, const VectorRd &x) const
Evaluate the scalar rotor of the i-th basis function at point x.
Definition basis.hpp:1073
static const bool hasFunction
Definition basis.hpp:734
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:195
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:1035
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1651
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.hpp:1049
ScalarFamilyType::GeometricSupport GeometricSupport
Definition basis.hpp:730
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition basis.hpp:1057
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:2301
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1500
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:775
boost::multi_array< typename BasisType::FunctionValue, 2 > m_on_basis_nodes
Definition basis.hpp:3054
double RotorValue
Definition basis.hpp:1593
void RotorValue
Definition basis.hpp:1277
Eigen::Matrix2d MatrixRd
Definition basis.hpp:54
BasisType::DivergenceValue DivergenceValue
Definition basis.hpp:994
GradientValue CurlValue
Definition basis.hpp:565
BasisType::CurlValue ReturnValue
Definition basis.hpp:1896
RotorValue rotor(size_t i, size_t iqn, const boost::multi_array< RotorValue, 2 > &ancestor_rotor_quad) const
Evaluate the scalar rotor of the i-th function at a quadrature point iqn, knowing all the scalar roto...
Definition basis.hpp:471
static const bool hasDivergence
Definition basis.hpp:736
TensorizedVectorFamily< ScalarBasisType, N >::RotorValue ReturnValue
Definition basis.hpp:2186
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:2135
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition basis.hpp:1174
static const bool hasRotor
Definition basis.hpp:1228
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2093
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1995
void RotorValue
Definition basis.hpp:1646
static std::function< Eigen::MatrixXd(const Eigen::MatrixXd &)> symmetrise_matrix
Function to symmetrise a matrix (useful together with transform_values_quad)
Definition basis.hpp:1762
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition basis.hpp:1065
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:219
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th function at point x.
Definition basis.hpp:432
static constexpr const bool hasAncestor
Definition basis.hpp:1001
BasisType::GradientValue FunctionValue
Definition basis.hpp:1211
static const bool hasGradient
Definition basis.hpp:1601
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition basis.hpp:1591
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:213
VectorRd FunctionValue
Definition basis.hpp:1273
void DivergenceValue
Definition basis.hpp:1214
void DivergenceValue
Definition basis.hpp:917
constexpr const BasisType & ancestor() const
Return the underlying complete basis.
Definition basis.hpp:1029
BasisType::GradientValue GradientValue
Definition basis.hpp:992
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:2103
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.hpp:1166
static const bool hasHessian
Definition basis.hpp:1412
double DivergenceValue
Definition basis.hpp:1526
static constexpr const bool hasAncestor
Definition basis.hpp:180
DivergenceValue rotor(size_t i, const VectorRd &x) const
Evaluate the scalar rotor of the i-th function at point x.
Definition basis.hpp:458
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:2201
VectorRd GradientValue
Definition basis.hpp:915
constexpr const BasisType & ancestor() const
Return the underlying complete basis.
Definition basis.hpp:1141
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:2922
void CurlValue
Definition basis.hpp:1644
BasisType AncestorType
Definition basis.hpp:1291
static const bool hasCurl
Definition basis.hpp:1114
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1469
static const bool hasCurl
Definition basis.hpp:1226
static const bool hasFunction
Definition basis.hpp:1534
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl (vector rot) of the i-th basis function at point x.
Definition basis.cpp:41
static const bool hasRotor
Definition basis.hpp:1411
void DivergenceValue
Definition basis.hpp:1463
FunctionValue function(size_t i, size_t iqn, const boost::multi_array< double, 2 > &ancestor_value_quad) const
Evaluate the i-th basis function at a quadrature point iqn, knowing all the values of ancestor basis ...
Definition basis.hpp:783
static const bool hasGradient
Definition basis.hpp:256
Eigen::MatrixXd PermuteTensorization(const size_t a, const size_t b)
Returns the matrix giving the permutation of the tensorization of a family of size a with a family of...
Definition basis.cpp:224
Cell GeometricSupport
Definition basis.hpp:1530
MatrixFamily(const ScalarFamilyType &scalar_family)
Definition basis.hpp:743
constexpr int dimspace
Dimension, and generic types for vector in correct dimension (makes it easier to translate a code bet...
Definition basis.hpp:53
TensorRankE
Definition basis.hpp:67
MatrixGradient< N > operator*(double scalar, MatrixGradient< N > const &G)
Multiplication of a MatrixGradient from the left (non-member function to be able to multiply from the...
Definition basis.hpp:156
RotorValue rotor(size_t i, const VectorRd &x) const
Evaluate the rotor of the i-th basis function at point x.
Definition basis.cpp:131
double FunctionValue
Definition basis.hpp:170
const Eigen::MatrixXd traceOperator() const
Returns the matrix corresponding to the trace, expressed as a linear operator between that MatrixFami...
Definition basis.hpp:878
Eigen::MatrixXd gram_schmidt(boost::multi_array< T, 2 > &basis_eval, const std::function< double(size_t, size_t)> &inner_product)
Definition basis.hpp:2440
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th function at point x.
Definition basis.hpp:406
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2125
VectorRd CurlValue
Definition basis.hpp:725
static const bool hasRotor
Definition basis.hpp:185
BasisType::GradientValue ReturnValue
Definition basis.hpp:1849
static constexpr const bool hasAncestor
Definition basis.hpp:1599
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition basis.hpp:1182
void RotorValue
Definition basis.hpp:1215
MatrixGradient operator+(const MatrixGradient &G)
Addition.
Definition basis.hpp:132
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1316
static const bool hasCurl
Definition basis.hpp:328
BasisType::CurlValue CurlValue
Definition basis.hpp:317
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1897
static const bool hasGradient
Definition basis.hpp:1225
MatrixRd FunctionValue
Definition basis.hpp:1641
static const bool hasGradient
Definition basis.hpp:1347
Family< BasisType > m_on_basis
Definition basis.hpp:3053
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:1766
static const bool hasCurl
Definition basis.hpp:1536
void RotorValue
Definition basis.hpp:727
static constexpr const bool hasAncestor
Definition basis.hpp:254
BasisType::HessianValue HessianValue
Definition basis.hpp:996
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2158
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:445
double DivergenceValue
Definition basis.hpp:566
std::function< T(const VectorRd &)> FType
type for function of point. T is the type of value of the function
Definition basis.hpp:64
BasisType AncestorType
Definition basis.hpp:1231
static const bool hasHessian
Definition basis.hpp:186
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition basis.hpp:791
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1378
RotorValue rotor(size_t i, const VectorRd &x) const
Evaluate the rotor of the i-th basis function at point x.
Definition basis.hpp:1190
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:419
static constexpr const TensorRankE tensorRank
Definition basis.hpp:732
static const bool hasRotor
Definition basis.hpp:578
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition basis.hpp:1524
Eigen::Matrix< double, N, N > dx
Definition basis.hpp:149
static const bool hasGradient
Definition basis.hpp:1408
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:2558
static const bool hasDivergence
Definition basis.hpp:1656
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1342
static constexpr const TensorRankE tensorRank
Definition basis.hpp:179
constexpr const BasisType & ancestor() const
Return the ancestor.
Definition basis.hpp:516
static const bool hasDivergence
Definition basis.hpp:1287
static const bool hasCurl
Definition basis.hpp:1004
Eigen::Matrix< double, N, N > FunctionValue
Definition basis.hpp:723
VectorRd GradientValue
Definition basis.hpp:1337
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:1728
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1943
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:3036
static const bool hasRotor
Definition basis.hpp:330
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1304
static const bool hasFunction
Definition basis.hpp:1284
ScalarFamilyType AncestorType
Definition basis.hpp:932
size_t dimension() const
Return the dimension of the family.
Definition basis.hpp:597
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1966
static const bool hasCurl
Definition basis.hpp:1286
const ScalarFamilyType & ancestor() const
Return the ancestor (family that has been tensorized)
Definition basis.hpp:829
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1366
static const bool hasGradient
Definition basis.hpp:1474
static const bool hasFunction
Definition basis.hpp:181
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition basis.cpp:106
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_rotor_quad)
Definition basis.hpp:1949
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1108
VectorRd CurlValue
Definition basis.hpp:1213
BasisType AncestorType
Definition basis.hpp:1009
void HessianValue
Definition basis.hpp:1340
FunctionValue function(size_t i, size_t iqn, const boost::multi_array< FunctionValue, 2 > &ancestor_value_quad) const
Evaluate the i-th function at a quadrature point iqn, knowing all the values of ancestor basis functi...
Definition basis.hpp:366
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:819
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:1560
MatrixRd FunctionValue
Definition basis.hpp:1459
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition basis.hpp:1590
VectorRd GradientValue
Definition basis.hpp:245
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:1676
DecomposePoly(const Cell &T, const BasisType &basis)
Constructor for cell.
Definition basis.hpp:2995
static const bool hasGradient
Definition basis.hpp:735
static const bool hasRotor
Definition basis.hpp:259
static const bool hasCurl
Definition basis.hpp:1409
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1920
static const bool hasRotor
Definition basis.hpp:1657
void RotorValue
Definition basis.hpp:1400
TensorizedVectorFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition basis.hpp:2088
static const bool hasDivergence
Definition basis.hpp:1227
static const bool hasHessian
Definition basis.hpp:1007
void HessianValue
Definition basis.hpp:1594
static const bool hasFunction
Definition basis.hpp:1112
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_gradient_quad)
Definition basis.hpp:1832
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:853
static const bool hasRotor
Definition basis.hpp:1604
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:966
VectorRd GradientValue
Definition basis.hpp:171
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the Hessian of the i-th basis function at point x.
Definition basis.cpp:46
double RotorValue
Definition basis.hpp:567
BasisType::DivergenceValue DivergenceValue
Definition basis.hpp:1104
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1802
ScalarFamilyType::GeometricSupport GeometricSupport
Definition basis.hpp:570
Eigen::VectorXd integrate(const FType< T > &f, const BasisQuad< T > &B, const QuadratureRule &qr, size_t n_rows=0)
Compute the integral of a given function against all functions from a family.
Definition basis.hpp:2736
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_value_quad)
Definition basis.hpp:1808
VectorZd powers(size_t i) const
Returns the powers of the i-th basis function (not including the vector part)
Definition basis.hpp:1566
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1434
static const bool hasHessian
Definition basis.hpp:582
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:522
HessianBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1483
static const bool hasRotor
Definition basis.hpp:929
void HessianValue
Definition basis.hpp:728
Eigen::Matrix< double, N, N > dy
Definition basis.hpp:150
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1218
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1850
static const bool hasFunction
Definition basis.hpp:326
static const bool hasGradient
Definition basis.hpp:182
ShiftedBasis(const BasisType &basis, const int shift)
Constructor.
Definition basis.hpp:1012
static constexpr const bool hasAncestor
Definition basis.hpp:1533
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1372
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the Hessian of the i-th basis function at point x.
Definition basis.hpp:1081
ScalarFamilyType AncestorType
Definition basis.hpp:584
void HessianValue
Definition basis.hpp:1647
const std::shared_ptr< RolyComplBasisCell > & rck() const
Return the Rck basis.
Definition basis.hpp:1626
void CurlValue
Definition basis.hpp:1462
static const bool hasHessian
Definition basis.hpp:1478
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:651
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1440
static const bool hasGradient
Definition basis.hpp:327
static constexpr const TensorRankE tensorRank
Definition basis.hpp:324
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1344
size_t dimension() const
Dimension of the basis.
Definition basis.hpp:269
static constexpr const bool hasAncestor
Definition basis.hpp:1283
void DivergenceValue
Definition basis.hpp:1276
static const bool hasFunction
Definition basis.hpp:1471
BasisType AncestorType
Definition basis.hpp:1352
static const bool hasDivergence
Definition basis.hpp:1537
QuadratureRule get_nodes() const
Return the set of nodes (useful to compute value of polynomial to decompose via evaluate_quad)
Definition basis.hpp:3030
static const bool hasFunction
Definition basis.hpp:1600
DecomposePoly(const Edge &E, const BasisType &basis)
Constructor for edge.
Definition basis.hpp:2965
void HessianValue
Definition basis.hpp:1401
size_t m_dim
Definition basis.hpp:3051
static const bool hasCurl
Definition basis.hpp:1655
static const bool hasCurl
Definition basis.hpp:183
Edge GeometricSupport
Definition basis.hpp:251
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:2005
boost::multi_array< VectorRd, 2 > vector_matrix_product(const std::vector< VectorRd > &v_quad, const boost::multi_array< MatrixRd, 2 > &basis_quad)
Take the product of (the transposed of) a vector with a matrix-valued basis.
Definition basis.cpp:205
constexpr const ScalarFamilyType & ancestor() const
Return the ancestor (family used for the tangent)
Definition basis.hpp:960
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:2324
double FunctionValue
Definition basis.hpp:1396
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:2267
BasisType::HessianValue ReturnValue
Definition basis.hpp:1965
Eigen::Matrix< double, N, 1 > DivergenceValue
Definition basis.hpp:726
static const bool hasDivergence
Definition basis.hpp:1005
const Eigen::MatrixXd & matrix() const
Return the coefficient matrix.
Definition basis.hpp:510
size_t m_nb_nodes
Definition basis.hpp:3055
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1506
static const bool hasDivergence
Definition basis.hpp:1603
static const bool hasRotor
Definition basis.hpp:1006
static const bool hasGradient
Definition basis.hpp:1003
MatrixGradient operator-(const MatrixGradient &G)
Subtraction.
Definition basis.hpp:144
MatrixFamily< ScalarBasisType, N >::FunctionValue ReturnValue
Definition basis.hpp:2220
double FunctionValue
Definition basis.hpp:244
static const bool hasCurl
Definition basis.hpp:1348
static constexpr const bool hasAncestor
Definition basis.hpp:325
static constexpr const bool hasAncestor
Definition basis.hpp:1345
static const bool hasHessian
Definition basis.hpp:1117
static const bool hasGradient
Definition basis.hpp:1654
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1826
TensorizedVectorFamily< ScalarBasisType, N >::DivergenceValue ReturnValue
Definition basis.hpp:2153
TensorizedVectorFamily(const ScalarFamilyType &scalar_family)
Definition basis.hpp:586
static const bool hasFunction
Definition basis.hpp:1407
BasisType::CurlValue CurlValue
Definition basis.hpp:1103
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition basis.hpp:1525
void RotorValue
Definition basis.hpp:248
void DivergenceValue
Definition basis.hpp:1399
BasisType::RotorValue RotorValue
Definition basis.hpp:1105
VectorRd CurlValue
Definition basis.hpp:172
@ Curl
Definition basis.hpp:1705
@ Function
Definition basis.hpp:1701
@ Gradient
Definition basis.hpp:1702
@ SkewsymmetricGradient
Definition basis.hpp:1704
@ Rotor
Definition basis.hpp:1707
@ Divergence
Definition basis.hpp:1706
@ SymmetricGradient
Definition basis.hpp:1703
@ Hessian
Definition basis.hpp:1708
@ Scalar
Definition basis.hpp:68
@ Vector
Definition basis.hpp:69
@ Matrix
Definition basis.hpp:70
size_t L
Definition HHO_DiffAdvecReac.hpp:46
std::vector< QuadratureNode > QuadratureRule
Definition quadraturerule.hpp:55
if(strcmp(field, 'real')) % real valued entries T
Definition mmread.m:93
for j
Definition mmread.m:174
Definition PastixInterface.hpp:16
Definition ddr-klplate.hpp:27
static auto v
Definition ddrcore-test.hpp:32
Structure to decompose a set of polynomials on a basis on an edge or a cell.
Definition basis.hpp:2958
Structure to store the gradient of a matrix-valued function.
Definition basis.hpp:113
Compute vectors listing the powers of monomial basis functions (for a cell, only this specialization ...
Definition basis.hpp:81
Basis dimensions for various polynomial spaces on edges/faces/elements (when relevant): Pk,...
Definition polynomialspacedimension.hpp:55
Basis evaluation traits. Only specialization of 'BasisFunction' (=Function, Gradient,...
Definition basis.hpp:1793
Evaluate a basis at quadrature nodes. 'BasisFunction' (=Function, Gradient, Curl, Divergence,...
Definition basis.hpp:2320