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 static const bool hasCurlCurl = false;
188
191 const Cell &T,
192 size_t degree
193 );
194
196 inline size_t dimension() const
197 {
198 return ( m_degree >= 0 ? (m_degree + 1) * (m_degree + 2) / 2 : 0);
199 }
200
202 FunctionValue function(size_t i, const VectorRd & x) const;
203
205 GradientValue gradient(size_t i, const VectorRd & x) const;
206
208 CurlValue curl(size_t i, const VectorRd & x) const;
209
211 HessianValue hessian(size_t i, const VectorRd & x) const;
212
214 inline size_t max_degree() const
215 {
216 return m_degree;
217 }
218
220 inline VectorZd powers(size_t i) const
221 {
222 return m_powers[i];
223 }
224
225 private:
227 inline VectorRd _coordinate_transform(const VectorRd& x) const
228 {
229 return (x - m_xT) / m_hT;
230 }
231
232 size_t m_degree;
233 VectorRd m_xT;
234 double m_hT;
235 std::vector<VectorZd> m_powers;
236 Eigen::Matrix2d m_rot; // rotation pi/2
237 };
238
239 //------------------------------------------------------------------------------
240
243 {
244 public:
245 typedef double FunctionValue;
248 typedef void DivergenceValue;
249 typedef void RotorValue;
250 typedef void HessianValue;
251
252 typedef Edge GeometricSupport;
253
254 constexpr static const TensorRankE tensorRank = Scalar;
255 constexpr static const bool hasAncestor = false;
256 static const bool hasFunction = true;
257 static const bool hasGradient = true;
258 static const bool hasCurl = false;
259 static const bool hasDivergence = false;
260 static const bool hasRotor = false;
261 static const bool hasHessian = false;
262 static const bool hasCurlCurl = false;
263
266 const Edge &E,
267 size_t degree
268 );
269
271 inline size_t dimension() const
272 {
273 return m_degree + 1;
274 }
275
277 FunctionValue function(size_t i, const VectorRd &x) const;
278
280 GradientValue gradient(size_t i, const VectorRd &x) const;
281
283 inline size_t max_degree() const
284 {
285 return m_degree;
286 }
287
288 private:
289 inline double _coordinate_transform(const VectorRd &x) const
290 {
291 return (x - m_xE).dot(m_tE) / m_hE;
292 }
293
294 size_t m_degree;
295 VectorRd m_xE;
296 double m_hE;
297 VectorRd m_tE;
298 };
299
300 //------------------------------------------------------------------------------
301 //------------------------------------------------------------------------------
302 // DERIVED BASIS
303 //------------------------------------------------------------------------------
304 //------------------------------------------------------------------------------
305
306 //----------------------------FAMILY------------------------------------------
307 //
313 template <typename BasisType>
314 class Family
315 {
316 public:
317 typedef typename BasisType::FunctionValue FunctionValue;
318 typedef typename BasisType::GradientValue GradientValue;
319 typedef typename BasisType::CurlValue CurlValue;
320 typedef typename BasisType::DivergenceValue DivergenceValue;
321 typedef typename BasisType::RotorValue RotorValue;
322 typedef typename BasisType::HessianValue HessianValue;
323
324 typedef typename BasisType::GeometricSupport GeometricSupport;
325
326 constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
327 constexpr static const bool hasAncestor = true;
328 static const bool hasFunction = BasisType::hasFunction;
329 static const bool hasGradient = BasisType::hasGradient;
330 static const bool hasCurl = BasisType::hasCurl;
331 static const bool hasDivergence = BasisType::hasDivergence;
332 static const bool hasRotor = BasisType::hasRotor;
333 static const bool hasHessian = BasisType::hasHessian;
334 static const bool hasCurlCurl = BasisType::hasCurlCurl;
335
336 typedef BasisType AncestorType;
337
340 const BasisType &basis,
341 const Eigen::MatrixXd &matrix
342 )
343 : m_basis(basis),
344 m_matrix(matrix)
345 {
346 assert((size_t)matrix.cols() == basis.dimension() || "Inconsistent family initialization");
347 }
348
350 inline size_t dimension() const
351 {
352 return m_matrix.rows();
353 }
354
356 FunctionValue function(size_t i, const VectorRd &x) const
357 {
358 static_assert(hasFunction, "Call to function() not available");
359
360 FunctionValue f = m_matrix(i, 0) * m_basis.function(0, x);
361 for (auto j = 1; j < m_matrix.cols(); j++)
362 {
363 f += m_matrix(i, j) * m_basis.function(j, x);
364 } // for j
365 return f;
366 }
367
369 FunctionValue function(size_t i, size_t iqn, const boost::multi_array<FunctionValue, 2> &ancestor_value_quad) const
370 {
371 static_assert(hasFunction, "Call to function() not available");
372
373 FunctionValue f = m_matrix(i, 0) * ancestor_value_quad[0][iqn];
374 for (auto j = 1; j < m_matrix.cols(); j++)
375 {
376 f += m_matrix(i, j) * ancestor_value_quad[j][iqn];
377 } // for j
378 return f;
379 }
380
381
383 GradientValue gradient(size_t i, const VectorRd &x) const
384 {
385 static_assert(hasGradient, "Call to gradient() not available");
386
387 GradientValue G = m_matrix(i, 0) * m_basis.gradient(0, x);
388 for (auto j = 1; j < m_matrix.cols(); j++)
389 {
390 G += m_matrix(i, j) * m_basis.gradient(j, x);
391 } // for j
392 return G;
393 }
394
396 GradientValue gradient(size_t i, size_t iqn, const boost::multi_array<GradientValue, 2> &ancestor_gradient_quad) const
397 {
398 static_assert(hasGradient, "Call to gradient() not available");
399
400 GradientValue G = m_matrix(i, 0) * ancestor_gradient_quad[0][iqn];
401 for (auto j = 1; j < m_matrix.cols(); j++)
402 {
403 G += m_matrix(i, j) * ancestor_gradient_quad[j][iqn];
404 } // for j
405 return G;
406 }
407
409 CurlValue curl(size_t i, const VectorRd &x) const
410 {
411 static_assert(hasCurl, "Call to curl() not available");
412
413 CurlValue C = m_matrix(i, 0) * m_basis.curl(0, x);
414 for (auto j = 1; j < m_matrix.cols(); j++)
415 {
416 C += m_matrix(i, j) * m_basis.curl(j, x);
417 } // for j
418 return C;
419 }
420
422 CurlValue curl(size_t i, size_t iqn, const boost::multi_array<CurlValue, 2> &ancestor_curl_quad) const
423 {
424 static_assert(hasCurl, "Call to curl() not available");
425
426 CurlValue C = m_matrix(i, 0) * ancestor_curl_quad[0][iqn];
427 for (auto j = 1; j < m_matrix.cols(); j++)
428 {
429 C += m_matrix(i, j) * ancestor_curl_quad[j][iqn];
430 } // for j
431 return C;
432 }
433
435 DivergenceValue divergence(size_t i, const VectorRd &x) const
436 {
437 static_assert(hasDivergence, "Call to divergence() not available");
438
439 DivergenceValue D = m_matrix(i, 0) * m_basis.divergence(0, x);
440 for (auto j = 1; j < m_matrix.cols(); j++)
441 {
442 D += m_matrix(i, j) * m_basis.divergence(j, x);
443 } // for j
444 return D;
445 }
446
448 DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<DivergenceValue, 2> &ancestor_divergence_quad) const
449 {
450 static_assert(hasDivergence, "Call to divergence() not available");
451
452 DivergenceValue D = m_matrix(i, 0) * ancestor_divergence_quad[0][iqn];
453 for (auto j = 1; j < m_matrix.cols(); j++)
454 {
455 D += m_matrix(i, j) * ancestor_divergence_quad[j][iqn];
456 } // for j
457 return D;
458 }
459
461 DivergenceValue rotor(size_t i, const VectorRd &x) const
462 {
463 static_assert(hasRotor, "Call to rotor() not available");
464
465 RotorValue R = m_matrix(i, 0) * m_basis.rotor(0, x);
466 for (auto j = 1; j < m_matrix.cols(); j++)
467 {
468 R += m_matrix(i, j) * m_basis.rotor(j, x);
469 } // for j
470 return R;
471 }
472
474 RotorValue rotor(size_t i, size_t iqn, const boost::multi_array<RotorValue, 2> &ancestor_rotor_quad) const
475 {
476 static_assert(hasRotor, "Call to rotor() not available");
477
478 RotorValue R = m_matrix(i, 0) * ancestor_rotor_quad[0][iqn];
479 for (auto j = 1; j < m_matrix.cols(); j++)
480 {
481 R += m_matrix(i, j) * ancestor_rotor_quad[j][iqn];
482 } // for j
483 return R;
484 }
485
487 inline HessianValue hessian(size_t i, const VectorRd & x) const
488 {
489 static_assert(hasHessian, "Call to hessian() not available");
490
491 HessianValue H = m_matrix(i, 0) * m_basis.hessian(0, x);
492 for (auto j = 1; j < m_matrix.cols(); j++)
493 {
494 H += m_matrix(i, j) * m_basis.hessian(j, x);
495 } // for j
496 return H;
497 }
498
500 HessianValue hessian(size_t i, size_t iqn, const boost::multi_array<HessianValue, 2> &ancestor_hessian_quad) const
501 {
502 static_assert(hasHessian, "Call to hessian() not available");
503
504 HessianValue H = m_matrix(i, 0) * ancestor_hessian_quad[0][iqn];
505 for (auto j = 1; j < m_matrix.cols(); j++)
506 {
507 H += m_matrix(i, j) * ancestor_hessian_quad[j][iqn];
508 } // for j
509 return H;
510 }
511
513 inline const Eigen::MatrixXd & matrix() const
514 {
515 return m_matrix;
516 }
517
519 constexpr inline const BasisType &ancestor() const
520 {
521 return m_basis;
522 }
523
525 inline size_t max_degree() const
526 {
527 return m_basis.max_degree();
528 }
529
530 private:
531 BasisType m_basis;
532 Eigen::MatrixXd m_matrix;
533 };
534
535 //----------------------TENSORIZED--------------------------------------------------------
536
538
562 template <typename ScalarFamilyType, size_t N>
564 {
565 public:
566 typedef typename Eigen::Matrix<double, N, 1> FunctionValue;
567 typedef typename Eigen::Matrix<double, N, dimspace> GradientValue;
570 typedef double DivergenceValue;
571 typedef double RotorValue;
572 typedef void HessianValue;
573
574 typedef typename ScalarFamilyType::GeometricSupport GeometricSupport;
575
576 constexpr static const TensorRankE tensorRank = Vector;
577 constexpr static const bool hasAncestor = true;
578 static const bool hasFunction = ScalarFamilyType::hasFunction;
579 static const bool hasGradient = ScalarFamilyType::hasGradient;
580 // We know how to compute the curl, scalar rotor, and divergence if gradient is available
581 static const bool hasDivergence = ( ScalarFamilyType::hasGradient && N==dimspace );
582 static const bool hasRotor = ( ScalarFamilyType::hasGradient && N==dimspace );
583 static const bool hasCurl = ( ScalarFamilyType::hasGradient && N==dimspace );
584 // In future versions, one could include the computation of second derivatives
585 // checking that BasisType has information on the Hessian
586 static const bool hasHessian = false;
587 static const bool hasCurlCurl = (ScalarFamilyType::hasHessian && N == dimspace);
588
589 typedef ScalarFamilyType AncestorType;
590
591 TensorizedVectorFamily(const ScalarFamilyType & scalar_family)
592 : m_scalar_family(scalar_family)
593 {
594 static_assert(ScalarFamilyType::tensorRank == Scalar,
595 "Vector family can only be constructed from scalar families");
596 m_rot.row(0) << 0., 1.;
597 m_rot.row(1) << -1., 0.;
598
599 }
600
602 inline size_t dimension() const
603 {
604 return m_scalar_family.dimension() * N;
605 }
606
608 FunctionValue function(size_t i, const VectorRd &x) const
609 {
610 static_assert(hasFunction, "Call to function() not available");
611
612 FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
613 ek(i / m_scalar_family.dimension()) = 1.;
614 return ek * m_scalar_family.function(i % m_scalar_family.dimension(), x);
615 }
616
618 FunctionValue function(size_t i, size_t iqn, const boost::multi_array<double, 2> &ancestor_value_quad) const
619 {
620 static_assert(hasFunction, "Call to function() not available");
621
622 FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
623 ek(i / m_scalar_family.dimension()) = 1.;
624 return ek * ancestor_value_quad[i % m_scalar_family.dimension()][iqn];
625 }
626
628 GradientValue gradient(size_t i, const VectorRd &x) const
629 {
630 static_assert(hasGradient, "Call to gradient() not available");
631
632 GradientValue G = Eigen::Matrix<double, N, dimspace>::Zero();
633 G.row(i / m_scalar_family.dimension()) = m_scalar_family.gradient(i % m_scalar_family.dimension(), x);
634 return G;
635 }
636
638 GradientValue gradient(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
639 {
640 static_assert(hasGradient, "Call to gradient() not available");
641
642 GradientValue G = Eigen::Matrix<double, N, dimspace>::Zero();
643 G.row(i / m_scalar_family.dimension()) = ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn];
644 return G;
645 }
646
648 CurlValue curl(size_t i, const VectorRd &x) const
649 {
650 static_assert(hasCurl, "Call to curl() not available");
651
652 return m_rot * gradient(i, x);
653 }
654
656 CurlValue curl(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
657 {
658 static_assert(hasCurl, "Call to curl() not available");
659
660 return m_rot * ancestor_gradient_quad[i][iqn];
661 }
662
664 DivergenceValue divergence(size_t i, const VectorRd &x) const
665 {
666 static_assert(hasDivergence, "Call to divergence() not available");
667
668 return m_scalar_family.gradient(i % m_scalar_family.dimension(), x)(i / m_scalar_family.dimension());
669 }
670
672 DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
673 {
674 static_assert(hasDivergence, "Call to divergence() not available");
675
676 return ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn](i / m_scalar_family.dimension());
677 }
678
680 RotorValue rotor(size_t i, const VectorRd &x) const
681 {
682 static_assert(hasRotor && hasCurl, "Call to rotor() not available");
683
684 return curl(i, x).trace();
685 }
686
688 RotorValue rotor(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
689 {
690 static_assert(hasRotor, "Call to rotor() not available");
691
692 return curl(i, iqn, ancestor_gradient_quad).trace();
693 }
694
696 CurlCurlValue curlcurl(size_t i, const VectorRd &x) const
697 {
698 static_assert(hasCurlCurl, "Call to curlcurl() not available");
699
700 FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
701 int p = i / m_scalar_family.dimension();
702 ek(p) = 1.;
703 typename ScalarFamilyType::HessianValue hess = m_scalar_family.hessian(i % m_scalar_family.dimension(), x);
704 return - hess.trace() * ek + hess.col(p);
705 }
706
708 CurlCurlValue curlcurl(size_t i, size_t iqn, const boost::multi_array<typename ScalarFamilyType::HessianValue, 2> &ancestor_hessian_quad) const
709 {
710 static_assert(hasCurlCurl, "Call to curlcurl() not available");
711
712 FunctionValue ek = Eigen::Matrix<double, N, 1>::Zero();
713 int p = i / m_scalar_family.dimension();
714 ek(p) = 1.;
715 typename ScalarFamilyType::HessianValue hess = ancestor_hessian_quad[i % m_scalar_family.dimension()][iqn];
716 return - hess.trace() * ek + hess.col(p);
717 }
718
720 constexpr inline const ScalarFamilyType &ancestor() const
721 {
722 return m_scalar_family;
723 }
724
726 inline size_t max_degree() const
727 {
728 return m_scalar_family.max_degree();
729 }
730
731 private:
732 ScalarFamilyType m_scalar_family;
733 Eigen::Matrix2d m_rot; // Rotation of pi/2
734 };
735
736 //----------------------MATRIX FAMILY--------------------------------------------------------
737
739
744 // Useful formulas to manipulate this basis (all indices starting from 0):
745 // the i-th element in the basis is f_{i%r} E_{i/r}
746 // the matrix E_m has 1 at position (m%N, m/N)
747 // the element f_aE_b is the i-th in the family with i = b*r + a
748 template<typename ScalarFamilyType, size_t N>
750 {
751 public:
752 typedef typename Eigen::Matrix<double, N, N> FunctionValue;
755 typedef typename Eigen::Matrix<double, N, 1> DivergenceValue;
756 typedef void RotorValue;
757 typedef void HessianValue;
758
759 typedef typename ScalarFamilyType::GeometricSupport GeometricSupport;
760
761 constexpr static const TensorRankE tensorRank = Matrix;
762 constexpr static const bool hasAncestor = true;
763 static const bool hasFunction = ScalarFamilyType::hasFunction;
764 static const bool hasGradient = true;
765 static const bool hasDivergence = ( ScalarFamilyType::hasGradient && N==dimspace );
766 static const bool hasRotor = false;
767 static const bool hasCurl = false;
768 static const bool hasHessian = false;
769 static const bool hasCurlCurl = false;
770
771 typedef ScalarFamilyType AncestorType;
772
773 MatrixFamily(const ScalarFamilyType & scalar_family)
774 : m_scalar_family(scalar_family),
775 m_E(N*N),
776 m_transposeOperator(Eigen::MatrixXd::Zero(scalar_family.dimension()*N*N, scalar_family.dimension()*N*N))
777 {
778 static_assert(ScalarFamilyType::tensorRank == Scalar,
779 "Vector family can only be constructed from scalar families");
780
781 // Construct the basis for NxN matrices
782 for (size_t j = 0; j < N; j++){
783 for (size_t i = 0; i < N; i++){
784 m_E[j*N + i] = Eigen::Matrix<double, N, N>::Zero();
785 m_E[j*N + i](i,j) = 1.;
786 }
787 }
788
789 // Construct the transpose operator
790 for (size_t i = 0; i < dimension(); i++){
791 // 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
792 size_t r = m_scalar_family.dimension();
793 size_t j = ( ( (i/r)%N )*N + (i/r)/N ) * r + (i%r);
794 m_transposeOperator(i,j) = 1.;
795 }
796 }
797
799 inline size_t dimension() const
800 {
801 return m_scalar_family.dimension() * N * N;
802 }
803
805 FunctionValue function(size_t i, const VectorRd & x) const
806 {
807 static_assert(hasFunction, "Call to function() not available");
808
809 return m_scalar_family.function(i % m_scalar_family.dimension(), x) * m_E[i / m_scalar_family.dimension()];
810 }
811
813 FunctionValue function(size_t i, size_t iqn, const boost::multi_array<double, 2> &ancestor_value_quad) const
814 {
815 static_assert(hasFunction, "Call to function() not available");
816
817 return ancestor_value_quad[i % m_scalar_family.dimension()][iqn] * m_E[i / m_scalar_family.dimension()];
818 }
819
821 DivergenceValue divergence(size_t i, const VectorRd & x) const
822 {
823 static_assert(hasDivergence, "Call to divergence() not available");
824
825 Eigen::Matrix<double, N, 1> V = m_E[i/m_scalar_family.dimension()].col( (i/m_scalar_family.dimension()) /N);
826 return m_scalar_family.gradient(i % m_scalar_family.dimension(), x)( (i / m_scalar_family.dimension()) / N) * V;
827 }
828
830 DivergenceValue divergence(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
831 {
832 static_assert(hasDivergence, "Call to divergence() not available");
833
834 Eigen::Matrix<double, N, 1> V = m_E[i/m_scalar_family.dimension()].col( (i/m_scalar_family.dimension()) /N);
835 return ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn]( (i / m_scalar_family.dimension()) / N) * V;
836 }
837
839 GradientValue gradient(size_t i, const VectorRd & x) const
840 {
841 static_assert(hasGradient, "Call to gradient() not available");
842
843 const VectorRd gradient_scalar_function = m_scalar_family.gradient(i % m_scalar_family.dimension(), x);
844 const Eigen::Matrix<double, N, N> matrix_basis = m_E[i / m_scalar_family.dimension()];
845 return GradientValue(gradient_scalar_function.x() * matrix_basis, gradient_scalar_function.y() * matrix_basis);
846 }
847
849 GradientValue gradient(size_t i, size_t iqn, const boost::multi_array<VectorRd, 2> &ancestor_gradient_quad) const
850 {
851 static_assert(hasGradient, "Call to gradient() not available");
852
853 const VectorRd gradient_scalar_function = ancestor_gradient_quad[i % m_scalar_family.dimension()][iqn];
854 const Eigen::Matrix<double, N, N> matrix_basis = m_E[i / m_scalar_family.dimension()];
855 return GradientValue(gradient_scalar_function.x() * matrix_basis, gradient_scalar_function.y() * matrix_basis);
856 }
857
859 inline const ScalarFamilyType &ancestor() const
860 {
861 return m_scalar_family;
862 }
863
865 inline const size_t matrixSize() const
866 {
867 return N;
868 }
869
871 inline const Eigen::MatrixXd transposeOperator() const
872 {
873 return m_transposeOperator;
874 }
875
877 inline const Eigen::MatrixXd symmetriseOperator() const
878 {
879 return (Eigen::MatrixXd::Identity(dimension(), dimension()) + m_transposeOperator)/2;
880 }
881
883 const Eigen::MatrixXd symmetricBasis() const
884 {
885 size_t dim_scalar = m_scalar_family.dimension();
886 Eigen::MatrixXd symOpe = symmetriseOperator();
887
888 Eigen::MatrixXd SB = Eigen::MatrixXd::Zero(dim_scalar * N*(N+1)/2, dimension());
889
890 // The matrix consists in selecting certain rows of symmetriseOperator, corresponding to the lower triangular part
891 // To select these rows, we loop over the columns of the underlying matrices, and get the rows in symmetriseOperator()
892 // corresponding to the lower triangular part of each column
893 size_t position = 0;
894 for (size_t i = 0; i<N; i++){
895 // Skip the first i*dim_scalar elements in the column (upper triangle) in symOpe, take the remaining (N-i)*dim_scalar
896 SB.middleRows(position, (N-i)*dim_scalar) = symOpe.middleRows(i*(N+1)*dim_scalar, (N-i)*dim_scalar);
897 // update current position
898 position += (N-i)*dim_scalar;
899 }
900
901 return SB;
902 }
903
905
908 inline const Eigen::MatrixXd traceOperator() const
909 {
910 size_t r = m_scalar_family.dimension();
911
912 Eigen::MatrixXd Tr = Eigen::MatrixXd::Zero(r, dimension());
913
914 /* According to the formulas described at the start of this class, the l-th element of the
915 matrix family is f_{l%r} E_{l/r}.
916 Given the construction of E_m=E_{l/r}, the trace is either 0, or 1 if m%N=m/N, that is,
917 (l/r)%N = (l/r)/N.
918 So Tr_{kl}=1 only if k=l%r and (l/r)%N = (l/r)/N
919 */
920 for (size_t l=0; l < dimension(); l++){
921 if ( size_t(l/r)%N == size_t(size_t(l/r)/N) ){
922 size_t k = l%r;
923 Tr(k,l) = 1.;
924 }
925 }
926
927 return Tr;
928 }
929
930 private:
931 ScalarFamilyType m_scalar_family;
932 std::vector<Eigen::Matrix<double, N, N>> m_E;
933 Eigen::MatrixXd m_transposeOperator;
934 };
935
936
937 //----------------------TANGENT FAMILY--------------------------------------------------------
938
940 template <typename ScalarFamilyType>
942 {
943 public:
947 typedef void DivergenceValue;
948 typedef void RotorValue;
949 typedef void HessianValue;
950
951 typedef Edge GeometricSupport;
952
953 constexpr static const TensorRankE tensorRank = Vector;
954 constexpr static const bool hasAncestor = true;
955 static const bool hasFunction = true;
956 static const bool hasGradient = false;
957 static const bool hasCurl = false;
958 static const bool hasDivergence = false;
959 static const bool hasRotor = false;
960 static const bool hasHessian = false;
961 static const bool hasCurlCurl = ScalarFamilyType::hasHessian;
962
963 typedef ScalarFamilyType AncestorType;
964
967 const ScalarFamilyType &scalar_family,
968 const VectorRd &generator
969 )
970 : m_scalar_family(scalar_family),
971 m_generator(generator)
972 {
973 static_assert(ScalarFamilyType::hasFunction, "Call to function() not available");
974 static_assert(std::is_same<typename ScalarFamilyType::GeometricSupport, Edge>::value,
975 "Tangent families can only be defined on edges");
976 }
977
979 inline size_t dimension() const
980 {
981 return m_scalar_family.dimension();
982 }
983
985 inline FunctionValue function(size_t i, const VectorRd &x) const
986 {
987 return m_scalar_family.function(i, x) * m_generator;
988 }
989
991 constexpr inline const ScalarFamilyType &ancestor() const
992 {
993 return m_scalar_family;
994 }
995
997 inline size_t max_degree() const
998 {
999 return m_scalar_family.max_degree();
1000 }
1001
1003 inline VectorRd generator() const
1004 {
1005 return m_generator;
1006 }
1007
1008 private:
1009 ScalarFamilyType m_scalar_family;
1010 VectorRd m_generator;
1011 };
1012
1013
1014 //--------------------SHIFTED BASIS----------------------------------------------------------
1015
1017
1018 template <typename BasisType>
1020 {
1021 public:
1022 typedef typename BasisType::FunctionValue FunctionValue;
1023 typedef typename BasisType::GradientValue GradientValue;
1024 typedef typename BasisType::CurlValue CurlValue;
1025 typedef typename BasisType::DivergenceValue DivergenceValue;
1026 typedef typename BasisType::RotorValue RotorValue;
1027 typedef typename BasisType::HessianValue HessianValue;
1028
1029 typedef typename BasisType::GeometricSupport GeometricSupport;
1030
1031 constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
1032 constexpr static const bool hasAncestor = true;
1033 static const bool hasFunction = BasisType::hasFunction;
1034 static const bool hasGradient = BasisType::hasGradient;
1035 static const bool hasCurl = BasisType::hasCurl;
1036 static const bool hasDivergence = BasisType::hasDivergence;
1037 static const bool hasRotor = BasisType::hasRotor;
1038 static const bool hasHessian = BasisType::hasHessian;
1039 static const bool hasCurlCurl = BasisType::hasCurlCurl;
1040
1041 typedef BasisType AncestorType;
1042
1045 const BasisType &basis,
1046 const int shift
1047 )
1048 : m_basis(basis),
1049 m_shift(shift)
1050 {
1051 // Do nothing
1052 }
1053
1055 inline size_t dimension() const
1056 {
1057 return m_basis.dimension() - m_shift;
1058 }
1059
1061 constexpr inline const BasisType &ancestor() const
1062 {
1063 return m_basis;
1064 }
1065
1067 inline size_t max_degree() const
1068 {
1069 return m_basis.max_degree();
1070 }
1071
1073 inline FunctionValue function(size_t i, const VectorRd &x) const
1074 {
1075 static_assert(hasFunction, "Call to function() not available");
1076
1077 return m_basis.function(i + m_shift, x);
1078 }
1079
1081 inline GradientValue gradient(size_t i, const VectorRd &x) const
1082 {
1083 static_assert(hasGradient, "Call to gradient() not available");
1084
1085 return m_basis.gradient(i + m_shift, x);
1086 }
1087
1089 inline CurlValue curl(size_t i, const VectorRd &x) const
1090 {
1091 static_assert(hasCurl, "Call to curl() not available");
1092
1093 return m_basis.curl(i + m_shift, x);
1094 }
1095
1097 inline DivergenceValue divergence(size_t i, const VectorRd &x) const
1098 {
1099 static_assert(hasDivergence, "Call to divergence() not available");
1100
1101 return m_basis.divergence(i + m_shift, x);
1102 }
1103
1105 inline RotorValue rotor(size_t i, const VectorRd &x) const
1106 {
1107 static_assert(hasRotor, "Call to rotor() not available");
1108
1109 return m_basis.rotor(i + m_shift, x);
1110 }
1111
1113 inline HessianValue hessian(size_t i, const VectorRd & x) const
1114 {
1115 static_assert(hasHessian, "Call to hessian() not available");
1116
1117 return m_basis.hessian(i + m_shift, x);
1118 }
1119
1120 private:
1121 BasisType m_basis;
1122 int m_shift;
1123 };
1124
1125 //-----------------------RESTRICTED BASIS-------------------------------------------------------
1126
1128
1129 template <typename BasisType>
1131 {
1132 public:
1133 typedef typename BasisType::FunctionValue FunctionValue;
1134 typedef typename BasisType::GradientValue GradientValue;
1135 typedef typename BasisType::CurlValue CurlValue;
1136 typedef typename BasisType::DivergenceValue DivergenceValue;
1137 typedef typename BasisType::RotorValue RotorValue;
1138 typedef typename BasisType::HessianValue HessianValue;
1139
1140 typedef typename BasisType::GeometricSupport GeometricSupport;
1141
1142 constexpr static const TensorRankE tensorRank = BasisType::tensorRank;
1143 constexpr static const bool hasAncestor = true;
1144 static const bool hasFunction = BasisType::hasFunction;
1145 static const bool hasGradient = BasisType::hasGradient;
1146 static const bool hasCurl = BasisType::hasCurl;
1147 static const bool hasDivergence = BasisType::hasDivergence;
1148 static const bool hasRotor = BasisType::hasRotor;
1149 static const bool hasHessian = BasisType::hasHessian;
1150 static const bool hasCurlCurl = BasisType::hasCurlCurl;
1151
1152 typedef BasisType AncestorType;
1153
1156 const BasisType &basis,
1157 const size_t &dimension
1158 )
1159 : m_basis(basis),
1160 m_dimension(dimension)
1161 {
1162 // Make sure that the provided dimension is smaller than the one
1163 // of the provided basis
1164 assert(dimension <= basis.dimension());
1165 }
1166
1168 inline size_t dimension() const
1169 {
1170 return m_dimension;
1171 }
1172
1174 constexpr inline const BasisType &ancestor() const
1175 {
1176 return m_basis;
1177 }
1178
1180 inline size_t max_degree() const
1181 {
1182 // We need to find the degree based on the dimension, assumes the basis is hierarchical
1183 size_t deg = 0;
1184 while (PolynomialSpaceDimension<GeometricSupport>::Poly(deg) < m_dimension){
1185 deg++;
1186 }
1187 return deg;
1188 }
1189
1191 inline FunctionValue function(size_t i, const VectorRd &x) const
1192 {
1193 static_assert(hasFunction, "Call to function() not available");
1194
1195 return m_basis.function(i, x);
1196 }
1197
1199 GradientValue gradient(size_t i, const VectorRd &x) const
1200 {
1201 static_assert(hasGradient, "Call to gradient() not available");
1202
1203 return m_basis.gradient(i, x);
1204 }
1205
1207 CurlValue curl(size_t i, const VectorRd &x) const
1208 {
1209 static_assert(hasCurl, "Call to curl() not available");
1210
1211 return m_basis.curl(i, x);
1212 }
1213
1215 DivergenceValue divergence(size_t i, const VectorRd &x) const
1216 {
1217 static_assert(hasDivergence, "Call to divergence() not available");
1218
1219 return m_basis.divergence(i, x);
1220 }
1221
1223 RotorValue rotor(size_t i, const VectorRd &x) const
1224 {
1225 static_assert(hasRotor, "Call to rotor() not available");
1226
1227 return m_basis.rotor(i, x);
1228 }
1229
1230 private:
1231 BasisType m_basis;
1232 size_t m_dimension;
1233 };
1234
1235 //--------------------GRADIENT BASIS----------------------------------------------------------
1236
1238
1240 template <typename BasisType>
1242 {
1243 public:
1244 typedef typename BasisType::GradientValue FunctionValue;
1245 typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1247 typedef void DivergenceValue;
1248 typedef void RotorValue;
1249 typedef void HessianValue;
1250
1251 typedef typename BasisType::GeometricSupport GeometricSupport;
1252
1253 constexpr static const TensorRankE tensorRank = Vector;
1254 constexpr static const bool hasAncestor = true;
1255 static const bool hasFunction = true;
1256 // In future versions, one could include the computation of derivatives
1257 // checking that BasisType has information on the Hessian
1258 static const bool hasGradient = false;
1259 static const bool hasCurl = false;
1260 static const bool hasDivergence = false;
1261 static const bool hasRotor = false;
1262 static const bool hasHessian = false;
1263 static const bool hasCurlCurl = false;
1264
1265 typedef BasisType AncestorType;
1266
1268 GradientBasis(const BasisType &basis)
1269 : m_scalar_basis(basis)
1270 {
1271 static_assert(BasisType::hasGradient,
1272 "Gradient basis requires gradient() for the original basis to be available");
1273 // Do nothing
1274 }
1275
1277 inline size_t dimension() const
1278 {
1279 return m_scalar_basis.dimension();
1280 }
1281
1283 inline FunctionValue function(size_t i, const VectorRd &x) const
1284 {
1285 return m_scalar_basis.gradient(i, x);
1286 }
1287
1289 constexpr inline const BasisType &ancestor() const
1290 {
1291 return m_scalar_basis;
1292 }
1293
1294
1295 private:
1296 BasisType m_scalar_basis;
1297 };
1298
1299 //-------------------CURL BASIS-----------------------------------------------------------
1300
1302
1303 template <typename BasisType>
1305 {
1306 public:
1308 typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1309 typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1310 typedef void DivergenceValue;
1311 typedef void RotorValue;
1312 typedef void HessianValue;
1313
1314 typedef typename BasisType::GeometricSupport GeometricSupport;
1315
1316 constexpr static const TensorRankE tensorRank = Vector;
1317 constexpr static const bool hasAncestor = true;
1318 static const bool hasFunction = true;
1319 static const bool hasGradient = false;
1320 static const bool hasCurl = false;
1321 static const bool hasDivergence = false;
1322 static const bool hasRotor = false;
1323 static const bool hasHessian = false;
1324 static const bool hasCurlCurl = false;
1325
1326 typedef BasisType AncestorType;
1327
1329 CurlBasis(const BasisType &basis)
1330 : m_basis(basis)
1331 {
1332 static_assert(BasisType::tensorRank == Scalar && std::is_same<typename BasisType::GeometricSupport, Cell>::value,
1333 "Curl basis can only be constructed starting from scalar bases on elements");
1334 static_assert(BasisType::hasCurl,
1335 "Curl basis requires curl() for the original basis to be available");
1336 }
1337
1339 inline size_t dimension() const
1340 {
1341 return m_basis.dimension();
1342 }
1343
1345 inline FunctionValue function(size_t i, const VectorRd &x) const
1346 {
1347 return m_basis.curl(i, x);
1348 }
1349
1351 constexpr inline const BasisType &ancestor() const
1352 {
1353 return m_basis;
1354 }
1355
1356
1357 private:
1358 size_t m_degree;
1359 BasisType m_basis;
1360 };
1361
1362
1363 //--------------------DIVERGENCE BASIS----------------------------------------------------------
1364
1366
1367 template <typename BasisType>
1369 {
1370 public:
1371 typedef double FunctionValue;
1374 typedef double DivergenceValue;
1375 typedef void HessianValue;
1376
1377 typedef typename BasisType::GeometricSupport GeometricSupport;
1378
1379 constexpr static const TensorRankE tensorRank = Scalar;
1380 constexpr static const bool hasAncestor = true;
1381 static const bool hasFunction = true;
1382 static const bool hasGradient = false;
1383 static const bool hasCurl = false;
1384 static const bool hasDivergence = false;
1385 static const bool hasHessian = false;
1386 static const bool hasCurlCurl = false;
1387
1388 typedef BasisType AncestorType;
1389
1391 DivergenceBasis(const BasisType &basis)
1392 : m_vector_basis(basis)
1393 {
1394 static_assert(BasisType::tensorRank == Vector || BasisType::tensorRank == Matrix,
1395 "Divergence basis can only be constructed starting from vector bases");
1396 static_assert(BasisType::hasDivergence,
1397 "Divergence basis requires divergence() for the original basis to be available");
1398 // Do nothing
1399 }
1400
1402 inline size_t dimension() const
1403 {
1404 return m_vector_basis.dimension();
1405 }
1406
1408 inline FunctionValue function(size_t i, const VectorRd &x) const
1409 {
1410 return m_vector_basis.divergence(i, x);
1411 }
1412
1414 constexpr inline const BasisType &ancestor() const
1415 {
1416 return m_vector_basis;
1417 }
1418
1419 private:
1420 BasisType m_vector_basis;
1421 };
1422
1423
1424 //--------------------ROTOR BASIS----------------------------------------------------------
1425
1427
1428 template <typename BasisType>
1430 {
1431 public:
1432 typedef double FunctionValue;
1435 typedef void DivergenceValue;
1436 typedef void RotorValue;
1437 typedef void HessianValue;
1438
1439 typedef typename BasisType::GeometricSupport GeometricSupport;
1440
1441 constexpr static const TensorRankE tensorRank = Scalar;
1442 constexpr static const bool hasAncestor = true;
1443 static const bool hasFunction = true;
1444 static const bool hasGradient = false;
1445 static const bool hasCurl = false;
1446 static const bool hasDivergence = false;
1447 static const bool hasRotor = false;
1448 static const bool hasHessian = false;
1449 static const bool hasCurlCurl = false;
1450
1451 typedef BasisType AncestorType;
1452
1454 RotorBasis(const BasisType &basis)
1455 : m_vector_basis(basis)
1456 {
1457 static_assert(BasisType::tensorRank == Vector,
1458 "Rotor basis can only be constructed starting from vector bases");
1459 static_assert(BasisType::hasRotor,
1460 "Rotor basis requires rotor() for the original basis to be available");
1461 // Do nothing
1462 }
1463
1465 inline size_t dimension() const
1466 {
1467 return m_vector_basis.dimension();
1468 }
1469
1471 inline FunctionValue function(size_t i, const VectorRd &x) const
1472 {
1473 return m_vector_basis.rotor(i, x);
1474 }
1475
1477 constexpr inline const BasisType &ancestor() const
1478 {
1479 return m_vector_basis;
1480 }
1481
1482 private:
1483 BasisType m_vector_basis;
1484 };
1485
1486
1487 //--------------------HESSIAN BASIS----------------------------------------------------------
1488
1490
1492 template <typename BasisType>
1494 {
1495 public:
1497 // The following types do not make sense in this context and are set to void
1498 typedef void GradientValue;
1499 typedef void CurlValue;
1500 typedef void DivergenceValue;
1501 typedef void RotorValue;
1502 typedef void HessianValue;
1503
1504 typedef typename BasisType::GeometricSupport GeometricSupport;
1505
1506 constexpr static const TensorRankE tensorRank = Matrix;
1507 constexpr static const bool hasAncestor = true;
1508 static const bool hasFunction = true;
1509 // In future versions, one could include the computation of derivatives
1510 // checking that BasisType has information on the Hessian
1511 static const bool hasGradient = false;
1512 static const bool hasCurl = false;
1513 static const bool hasDivergence = false;
1514 static const bool hasRotor = false;
1515 static const bool hasHessian = false;
1516
1517 typedef BasisType AncestorType;
1518
1520 HessianBasis(const BasisType &basis)
1521 : m_scalar_basis(basis)
1522 {
1523 static_assert(BasisType::tensorRank == Scalar,
1524 "Hessian basis can only be constructed starting from scalar bases");
1525 static_assert(BasisType::hasHessian,
1526 "Hessian basis requires hessian() for the original basis to be available");
1527 // Do nothing
1528 }
1529
1531 inline size_t dimension() const
1532 {
1533 return m_scalar_basis.dimension();
1534 }
1535
1537 inline FunctionValue function(size_t i, const VectorRd &x) const
1538 {
1539 return m_scalar_basis.hessian(i, x);
1540 }
1541
1543 constexpr inline const BasisType &ancestor() const
1544 {
1545 return m_scalar_basis;
1546 }
1547
1548
1549 private:
1550 BasisType m_scalar_basis;
1551 };
1552
1553 //---------------------------------------------------------------------
1554 // BASES FOR THE KOSZUL COMPLEMENTS OF G^k, R^k, H^k
1555 //---------------------------------------------------------------------
1558 {
1559 public:
1561 typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1562 typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1563 typedef double DivergenceValue;
1564 typedef void RotorValue;
1565 typedef void HessianValue;
1566
1567 typedef Cell GeometricSupport;
1568
1569 constexpr static const TensorRankE tensorRank = Vector;
1570 constexpr static const bool hasAncestor = false;
1571 static const bool hasFunction = true;
1572 static const bool hasGradient = false;
1573 static const bool hasCurl = false;
1574 static const bool hasDivergence = true;
1575 static const bool hasRotor = false;
1576 static const bool hasHessian = false;
1577 static const bool hasCurlCurl = false;
1578
1581 const Cell &T,
1582 size_t degree
1583 );
1584
1586 inline size_t dimension() const
1587 {
1589 }
1590
1592 FunctionValue function(size_t i, const VectorRd &x) const;
1593
1595 DivergenceValue divergence(size_t i, const VectorRd &x) const;
1596
1598 inline size_t max_degree() const
1599 {
1600 return m_degree;
1601 }
1602
1604 inline VectorZd powers(size_t i) const
1605 {
1606 return m_powers[i];
1607 }
1608
1609 private:
1611 inline VectorRd _coordinate_transform(const VectorRd &x) const
1612 {
1613 return (x - m_xT) / m_hT;
1614 }
1615
1616 size_t m_degree;
1617 VectorRd m_xT;
1618 double m_hT;
1619 std::vector<VectorZd> m_powers;
1620 };
1621
1622
1625 {
1626 public:
1628 typedef Eigen::Matrix<double, dimspace, dimspace> GradientValue;
1629 typedef Eigen::Matrix<double, dimspace, dimspace> CurlValue;
1630 typedef void DivergenceValue;
1631 typedef double RotorValue;
1632 typedef void HessianValue;
1633
1634 typedef Cell GeometricSupport;
1635
1636 constexpr static const TensorRankE tensorRank = Vector;
1637 constexpr static const bool hasAncestor = false;
1638 static const bool hasFunction = true;
1639 static const bool hasGradient = false;
1640 static const bool hasCurl = false;
1641 static const bool hasDivergence = false;
1642 static const bool hasRotor = true;
1643 static const bool hasHessian = false;
1644 static const bool hasCurlCurl = false;
1645
1646
1649 const Cell &T,
1650 size_t degree
1651 );
1652
1654 inline size_t dimension() const
1655 {
1657 }
1658
1660 FunctionValue function(size_t i, const VectorRd &x) const;
1661
1663 RotorValue rotor(size_t i, const VectorRd &x) const;
1664
1666 inline const std::shared_ptr<RolyComplBasisCell> &rck() const
1667 {
1668 return m_Rck_basis;
1669 }
1670
1671 private:
1672 size_t m_degree;
1673 Eigen::Matrix2d m_rot; // Rotation of pi/2: the basis of Gck is the rotated basis of Rck
1674 std::shared_ptr<RolyComplBasisCell> m_Rck_basis; // A basis of Rck, whose rotation gives a basis of Gck
1675 };
1676
1679 {
1680 public:
1682 // The following types do not make sense in this context and are set to void
1683 typedef void GradientValue;
1684 typedef void CurlValue;
1685 typedef void DivergenceValue;
1686 typedef void RotorValue;
1687 typedef void HessianValue;
1688
1689 typedef Cell GeometricSupport;
1690
1691 constexpr static const TensorRankE tensorRank = Matrix;
1692 constexpr static const bool hasAncestor = false;
1693 static const bool hasFunction = true;
1694 static const bool hasGradient = false;
1695 static const bool hasCurl = false;
1696 static const bool hasDivergence = true;
1697 static const bool hasRotor = false;
1698 static const bool hasHessian = false;
1699
1702 const Cell &T,
1703 size_t degree
1704 );
1705
1707 inline size_t dimension() const
1708 {
1710 }
1711
1713 FunctionValue function(size_t i, const VectorRd &x) const;
1714
1716 inline size_t max_degree() const
1717 {
1718 return m_degree;
1719 }
1720
1721 private:
1723 inline VectorRd _coordinate_transform(const VectorRd &x) const
1724 {
1725 return (x - m_xT) / m_hT;
1726 }
1727
1728 size_t m_degree;
1729 VectorRd m_xT;
1730 double m_hT;
1731 Eigen::Matrix2d m_rot;
1732 TensorizedVectorFamily<MonomialScalarBasisCell, dimspace> m_Pkmo;
1733 };
1734
1735 //------------------------------------------------------------------------------
1736 // Free functions
1737 //------------------------------------------------------------------------------
1738
1751
1753 template <typename outValue, typename inValue, typename FunctionType>
1754 boost::multi_array<outValue, 2> transform_values_quad(
1755 const boost::multi_array<inValue, 2> &B_quad,
1756 const FunctionType &F
1757 )
1758 {
1759 boost::multi_array<outValue, 2> transformed_B_quad( boost::extents[B_quad.shape()[0]][B_quad.shape()[1]] );
1760
1761 std::transform( B_quad.origin(), B_quad.origin() + B_quad.num_elements(), transformed_B_quad.origin(), F);
1762
1763 return transformed_B_quad;
1764 };
1765
1767
1768 template <typename ScalarBasisType, size_t N>
1770 const ScalarBasisType & B,
1771 const std::vector<Eigen::VectorXd> & v
1772 )
1773 {
1774 size_t r = B.dimension();
1775 size_t k = v.size();
1776
1777 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(r*k, r*N);
1778
1779 for (size_t i=0; i < k; i++){
1780 // Check the dimension of vector v[i]
1781 assert(v[i].size() == N);
1782
1783 // Fill in M
1784 for (size_t j=0; j < N; j++){
1785 M.block(i*r, j*r, r, r) = v[i](j) * Eigen::MatrixXd::Identity(r,r);
1786 }
1787 }
1788
1791 }
1792
1794
1797 Eigen::MatrixXd PermuteTensorization( const size_t a,
1798 const size_t b
1799 );
1800
1802 inline static std::function<Eigen::MatrixXd(const Eigen::MatrixXd &)>
1803 symmetrise_matrix = [](const Eigen::MatrixXd & x)->Eigen::MatrixXd { return 0.5*(x+x.transpose());};
1804
1806 inline static std::function<Eigen::MatrixXd(const Eigen::MatrixXd &)>
1807 skew_symmetrise_matrix = [](const Eigen::MatrixXd & x)->Eigen::MatrixXd { return 0.5*(x-x.transpose());};
1808
1810
1811 template <typename ScalarBasisType, size_t N>
1813 const ScalarBasisType & B
1814 )
1815 {
1816 size_t r = B.dimension();
1817 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(r, r*N*N);
1818
1819 for (size_t k=0; k < N; k++){
1820 M.block(0, k*r*(N+1), r, r) = Eigen::MatrixXd::Identity(r, r);
1821 }
1822
1824 return Family<MatrixFamily<ScalarBasisType, N>>(matbasis, M);
1825 }
1826 //------------------------------------------------------------------------------
1827 // BASIS EVALUATION
1828 //------------------------------------------------------------------------------
1829
1830 namespace detail {
1832
1833 template<typename BasisType, BasisFunctionE BasisFunction>
1835
1836 //---------- GENERIC EVALUATION TRAITS -----------------------------------------
1837 // Evaluate the function value at x
1838 template<typename BasisType>
1840 {
1841 static_assert(BasisType::hasFunction, "Call to function not available");
1842 typedef typename BasisType::FunctionValue ReturnValue;
1843 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1844 {
1845 return basis.function(i, x);
1846 }
1847
1848 // Computes function value at quadrature node iqn, knowing values of ancestor basis at quadrature nodes
1849 static inline ReturnValue evaluate(
1850 const BasisType &basis,
1851 size_t i,
1852 size_t iqn,
1853 const boost::multi_array<ReturnValue, 2> &ancestor_value_quad
1854 )
1855 {
1856 return basis.function(i, iqn, ancestor_value_quad);
1857 }
1858
1859 };
1860
1861 // Evaluate the gradient value at x
1862 template<typename BasisType>
1864 {
1865 static_assert(BasisType::hasGradient, "Call to gradient not available");
1866 typedef typename BasisType::GradientValue ReturnValue;
1867 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1868 {
1869 return basis.gradient(i, x);
1870 }
1871
1872 // Computes gradient value at quadrature node iqn, knowing gradients of ancestor basis at quadrature nodes
1873 static inline ReturnValue evaluate(
1874 const BasisType &basis,
1875 size_t i,
1876 size_t iqn,
1877 const boost::multi_array<ReturnValue, 2> &ancestor_gradient_quad
1878 )
1879 {
1880 return basis.gradient(i, iqn, ancestor_gradient_quad);
1881 }
1882 };
1883
1884 // AC - it's supposed to be used only in case of vector variables (vhhospace)
1885 // Evaluate the symmetric part of gradient at x
1886 template<typename BasisType>
1888 {
1889 static_assert(BasisType::hasGradient, "Call to gradient not available");
1890 typedef typename BasisType::GradientValue ReturnValue;
1891 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1892 {
1893 return 0.5 * (basis.gradient(i, x) + basis.gradient(i, x).transpose());
1894 }
1895
1896 // Computes gradient value at quadrature node iqn, knowing gradients of ancestor basis at quadrature nodes
1897 static inline ReturnValue evaluate(
1898 const BasisType &basis,
1899 size_t i,
1900 size_t iqn,
1901 const boost::multi_array<ReturnValue, 2> &ancestor_gradient_quad
1902 )
1903 {
1904 return 0.5 * (basis.gradient(i, iqn, ancestor_gradient_quad) + basis.gradient(i, iqn, ancestor_gradient_quad).transpose());
1905 }
1906 };
1907
1908 // AC - it's supposed to be used only in case of vector variables (vhhospace)
1909 // Evaluate the symmetric part of gradient at x
1910 template<typename BasisType>
1912 {
1913 static_assert(BasisType::hasGradient, "Call to gradient not available");
1914 typedef typename BasisType::GradientValue ReturnValue;
1915 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1916 {
1917 return 0.5 * (basis.gradient(i, x) - basis.gradient(i, x).transpose());
1918 }
1919
1920 // Computes gradient value at quadrature node iqn, knowing gradients of ancestor basis at quadrature nodes
1921 static inline ReturnValue evaluate(
1922 const BasisType &basis,
1923 size_t i,
1924 size_t iqn,
1925 const boost::multi_array<ReturnValue, 2> &ancestor_gradient_quad
1926 )
1927 {
1928 return 0.5 * (basis.gradient(i, iqn, ancestor_gradient_quad) - basis.gradient(i, iqn, ancestor_gradient_quad).transpose());
1929 }
1930 };
1931
1932 // Evaluate the curl value at x
1933 template<typename BasisType>
1935 {
1936 static_assert(BasisType::hasCurl, "Call to curl not available");
1937 typedef typename BasisType::CurlValue ReturnValue;
1938 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1939 {
1940 return basis.curl(i, x);
1941 }
1942
1943 // Computes curl value at quadrature node iqn, knowing curls of ancestor basis at quadrature nodes
1944 static inline ReturnValue evaluate(
1945 const BasisType &basis,
1946 size_t i,
1947 size_t iqn,
1948 const boost::multi_array<ReturnValue, 2> &ancestor_curl_quad
1949 )
1950 {
1951 return basis.curl(i, iqn, ancestor_curl_quad);
1952 }
1953 };
1954
1955 // Evaluate the divergence value at x
1956 template<typename BasisType>
1958 {
1959 static_assert(BasisType::hasDivergence, "Call to divergence not available");
1960 typedef typename BasisType::DivergenceValue ReturnValue;
1961 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1962 {
1963 return basis.divergence(i, x);
1964 }
1965
1966 // Computes divergence value at quadrature node iqn, knowing divergences of ancestor basis at quadrature nodes
1967 static inline ReturnValue evaluate(
1968 const BasisType &basis,
1969 size_t i,
1970 size_t iqn,
1971 const boost::multi_array<ReturnValue, 2> &ancestor_divergence_quad
1972 )
1973 {
1974 return basis.divergence(i, iqn, ancestor_divergence_quad);
1975 }
1976 };
1977
1978 // Evaluate the rotor value at x
1979 template<typename BasisType>
1981 {
1982 static_assert(BasisType::hasRotor, "Call to rotor not available");
1983 typedef typename BasisType::RotorValue ReturnValue;
1984 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
1985 {
1986 return basis.rotor(i, x);
1987 }
1988
1989 // Computes rotor value at quadrature node iqn, knowing rotors of ancestor basis at quadrature nodes
1990 static inline ReturnValue evaluate(
1991 const BasisType &basis,
1992 size_t i,
1993 size_t iqn,
1994 const boost::multi_array<ReturnValue, 2> &ancestor_rotor_quad
1995 )
1996 {
1997 return basis.rotor(i, iqn, ancestor_rotor_quad);
1998 }
1999 };
2000
2001 // Evaluate the Hessian value at x
2002 template<typename BasisType>
2004 {
2005 static_assert(BasisType::hasHessian, "Call to Hessian not available");
2006 typedef typename BasisType::HessianValue ReturnValue;
2007 static inline ReturnValue evaluate(const BasisType & basis, size_t i, const VectorRd & x)
2008 {
2009 return basis.hessian(i, x);
2010 }
2011
2012 // Computes Hessian value at quadrature node iqn, knowing Hessians of ancestor basis at quadrature nodes
2013 static inline ReturnValue evaluate(
2014 const BasisType &basis,
2015 size_t i,
2016 size_t iqn,
2017 const boost::multi_array<ReturnValue, 2> &ancestor_hessian_quad
2018 )
2019 {
2020 return basis.hessian(i, iqn, ancestor_hessian_quad);
2021 }
2022 };
2023
2024 // Evaluate the curl curl value at x
2025 template <typename BasisType>
2027 {
2028 static_assert(BasisType::hasCurlCurl, "Call to curl curl not available");
2029 typedef typename BasisType::CurlCurlValue ReturnValue;
2030 static inline ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
2031 {
2032 return basis.curlcurl(i, x);
2033 }
2034
2035 // Computes hessian value at quadrature node iqn, knowing hessian of ancestor basis at quadrature nodes
2036 static inline ReturnValue evaluate(
2037 const BasisType &basis,
2038 size_t i,
2039 size_t iqn,
2040 const boost::multi_array<ReturnValue, 2> &ancestor_curlcurl_quad
2041 )
2042 {
2043 return basis.curlcurl(i, iqn, ancestor_curlcurl_quad);
2044 }
2045
2046 };
2047
2048 //---------- TENSORIZED FAMILY EVALUATION TRAITS -----------------------------------------
2049 // Evaluate the value 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>::hasFunction, "Call to function not available");
2054
2056 static const BasisFunctionE AncestorBasisFunction = Function; // Type of values needed from ancestor basis
2058
2059 // Computes function values at x
2060 static inline ReturnValue evaluate(
2062 size_t i,
2063 const VectorRd &x
2064 )
2065 {
2066 return basis.function(i, x);
2067 }
2068
2069 // Computes function 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<double, 2> &ancestor_basis_quad
2075 )
2076 {
2077 return basis.function(i, iqn, ancestor_basis_quad);
2078 }
2079 };
2080
2081 // Evaluate the gradient at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2082 template <typename ScalarBasisType, size_t N>
2084 {
2085 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasGradient, "Call to gradient not available");
2086
2088 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2090
2091 // Computes gradient value at x
2092 static inline ReturnValue evaluate(
2094 size_t i,
2095 const VectorRd &x
2096 )
2097 {
2098 return basis.gradient(i, x);
2099 }
2100
2101 // Computes gradient value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2102 static inline ReturnValue evaluate(
2104 size_t i,
2105 size_t iqn,
2106 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2107 )
2108 {
2109 return basis.gradient(i, iqn, ancestor_basis_quad);
2110 }
2111 };
2112
2113 // AC - supposed to be used only in case of vector variables (vhhospace)
2114 // Evaluate the symmetric gradient 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>::hasGradient, "Call to gradient not available");
2119
2121 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2123
2124 // Computes gradient value at x
2125 static inline ReturnValue evaluate(
2127 size_t i,
2128 const VectorRd &x
2129 )
2130 {
2131 return 0.5 * (basis.gradient(i, x) + basis.gradient(i, x).transpose()) ;
2132 }
2133
2134 // Computes gradient value 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 0.5 * (basis.gradient(i, iqn, ancestor_basis_quad) + basis.gradient(i, iqn, ancestor_basis_quad).transpose());
2143 }
2144 };
2145
2146 // AC - supposed to be used only in case of vector variables (so gradient is a matrix)
2147 // Evaluate the symmetric gradient 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>::hasGradient, "Call to gradient not available");
2152
2154 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2156
2157 // Computes gradient value at x
2158 static inline ReturnValue evaluate(
2160 size_t i,
2161 const VectorRd &x
2162 )
2163 {
2164 return 0.5 * (basis.gradient(i, x) - basis.gradient(i, x).transpose()) ;
2165 }
2166
2167 // Computes gradient 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 0.5 * (basis.gradient(i, iqn, ancestor_basis_quad) - basis.gradient(i, iqn, ancestor_basis_quad).transpose());
2176 }
2177 };
2178
2179 // Evaluate the curl at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2180 template <typename ScalarBasisType, size_t N>
2182 {
2183 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasCurl, "Call to curl not available");
2184
2186 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2188
2189 // Computes curl values at x
2190 static inline ReturnValue evaluate(
2192 size_t i,
2193 const VectorRd &x
2194 )
2195 {
2196 return basis.curl(i, x);
2197 }
2198
2199 // Computes curl values at quadrature node iqn, knowing ancestor basis at quadrature nodes
2200 static inline ReturnValue evaluate(
2202 size_t i,
2203 size_t iqn,
2204 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2205 )
2206 {
2207 return basis.curl(i, iqn, ancestor_basis_quad);
2208 }
2209
2210 };
2211
2212 // Evaluate the divergence at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2213 template <typename ScalarBasisType, size_t N>
2215 {
2216 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasDivergence, "Call to divergence not available");
2217
2219 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2221
2222 // Computes divergence value at x
2223 static inline ReturnValue evaluate(
2225 size_t i,
2226 const VectorRd &x
2227 )
2228 {
2229 return basis.divergence(i, x);
2230 }
2231
2232 // Computes divergence value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2233 static inline ReturnValue evaluate(
2235 size_t i,
2236 size_t iqn,
2237 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2238 )
2239 {
2240 return basis.divergence(i, iqn, ancestor_basis_quad);
2241 }
2242
2243 };
2244
2245 // Evaluate the rotor at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2246 template <typename ScalarBasisType, size_t N>
2248 {
2249 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasRotor, "Call to rotor not available");
2250
2252 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2254
2255 // Computes divergence value at x
2256 static inline ReturnValue evaluate(
2258 size_t i,
2259 const VectorRd &x
2260 )
2261 {
2262 return basis.rotor(i, x);
2263 }
2264
2265 // Computes rotor value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2266 static inline ReturnValue evaluate(
2268 size_t i,
2269 size_t iqn,
2270 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2271 )
2272 {
2273 return basis.rotor(i, iqn, ancestor_basis_quad);
2274 }
2275
2276 };
2277
2278 // Evaluate the curl curl at x of a TensorizedVectorFamily (includes information on the ancestor basis, to optimise eval_quad for tensorized bases)
2279 template <typename ScalarBasisType, size_t N>
2281 {
2282 static_assert(TensorizedVectorFamily<ScalarBasisType, N>::hasCurlCurl, "Call to curl curl not available");
2283
2285 static const BasisFunctionE AncestorBasisFunction = Hessian; // Type of values needed from ancestor basis
2287
2288 // Computes curl curl value at x
2289 static inline ReturnValue evaluate(
2291 size_t i,
2292 const VectorRd &x
2293 )
2294 {
2295 return basis.curlcurl(i, x);
2296 }
2297
2298
2299
2300 // Computes curl curl 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<MatrixRd, 2> &ancestor_basis_quad
2306 )
2307 {
2308 return basis.curlcurl(i, iqn, ancestor_basis_quad);
2309 }
2310
2311 };
2312
2313
2314 //---------- MATRIX FAMILY EVALUATION TRAITS -----------------------------------------
2315 // Evaluate the value at x of a MatrixFamily (includes information on the ancestor basis, to optimise eval_quad for matrix families)
2316 template <typename ScalarBasisType, size_t N>
2317 struct basis_evaluation_traits<MatrixFamily<ScalarBasisType, N>, Function>
2318 {
2319 static_assert(MatrixFamily<ScalarBasisType, N>::hasFunction, "Call to function not available");
2320
2322 static const BasisFunctionE AncestorBasisFunction = Function; // Type of values needed from ancestor basis
2324
2325 // Computes function values at x
2326 static inline ReturnValue evaluate(
2328 size_t i,
2329 const VectorRd &x
2330 )
2331 {
2332 return basis.function(i, x);
2333 }
2334
2335 // Computes function value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2336 static inline ReturnValue evaluate(
2338 size_t i,
2339 size_t iqn,
2340 const boost::multi_array<double, 2> &ancestor_basis_quad
2341 )
2342 {
2343 return basis.function(i, iqn, ancestor_basis_quad);
2344 }
2345 };
2346
2347 // Evaluate the divergence at x of a MatrixFamily (includes information on the ancestor basis, to optimise eval_quad for matrix families)
2348 template <typename ScalarBasisType, size_t N>
2350 {
2351 static_assert(MatrixFamily<ScalarBasisType, N>::hasDivergence, "Call to divergence not available");
2352
2354 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2356
2357 // Computes divergence value at x
2358 static inline ReturnValue evaluate(
2360 size_t i,
2361 const VectorRd &x
2362 )
2363 {
2364 return basis.divergence(i, x);
2365 }
2366
2367 // Computes divergence value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2368 static inline ReturnValue evaluate(
2370 size_t i,
2371 size_t iqn,
2372 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2373 )
2374 {
2375 return basis.divergence(i, iqn, ancestor_basis_quad);
2376 }
2377
2378 };
2379
2380
2381 // Evaluate the gradient at x of a MatrixFamily (includes information on the ancestor basis, to optimise eval_quad for matrix families)
2382 template <typename ScalarBasisType, size_t N>
2383 struct basis_evaluation_traits<MatrixFamily<ScalarBasisType, N>, Gradient>
2384 {
2385 static_assert(MatrixFamily<ScalarBasisType, N>::hasGradient, "Call to gradient not available");
2386
2388 static const BasisFunctionE AncestorBasisFunction = Gradient; // Type of values needed from ancestor basis
2390
2391 // Computes gradient value at x
2392 static inline ReturnValue evaluate(
2394 size_t i,
2395 const VectorRd &x
2396 )
2397 {
2398 return basis.gradient(i, x);
2399 }
2400
2401 // Computes gradient value at quadrature node iqn, knowing ancestor basis at quadrature nodes
2402 static inline ReturnValue evaluate(
2404 size_t i,
2405 size_t iqn,
2406 const boost::multi_array<VectorRd, 2> &ancestor_basis_quad
2407 )
2408 {
2409 return basis.gradient(i, iqn, ancestor_basis_quad);
2410 }
2411
2412 };
2413
2414 } // end of namespace detail
2415
2416
2417 //-----------------------------------EVALUATE_QUAD--------------------------------------
2418
2420 template<BasisFunctionE BasisFunction>
2423 template<typename BasisType>
2424 static boost::multi_array<typename detail::basis_evaluation_traits<BasisType, BasisFunction>::ReturnValue, 2>
2426 const BasisType & basis,
2427 const QuadratureRule & quad
2428 )
2429 {
2431
2432 boost::multi_array<typename traits::ReturnValue, 2>
2433 basis_quad( boost::extents[basis.dimension()][quad.size()] );
2434
2435 for (size_t i = 0; i < basis.dimension(); i++) {
2436 for (size_t iqn = 0; iqn < quad.size(); iqn++) {
2437 basis_quad[i][iqn] = traits::evaluate(basis, i, quad[iqn].vector());
2438 } // for iqn
2439 } // for i
2440
2441 return basis_quad;
2442 }
2443
2445 template<typename BasisType>
2446 static boost::multi_array<typename detail::basis_evaluation_traits<Family<BasisType>, BasisFunction>::ReturnValue, 2>
2448 const Family<BasisType> & basis,
2449 const QuadratureRule & quad
2450 )
2451 {
2452 typedef detail::basis_evaluation_traits<Family<BasisType>, BasisFunction> traits;
2453
2454 boost::multi_array<typename traits::ReturnValue, 2>
2455 basis_quad( boost::extents[basis.dimension()][quad.size()] );
2456
2457 // Compute values at quadrature note on ancestor basis, and then do a transformation
2458 const auto & ancestor_basis = basis.ancestor();
2459 boost::multi_array<typename traits::ReturnValue, 2>
2460 ancestor_basis_quad = evaluate_quad<BasisFunction>::compute(ancestor_basis, quad);
2461
2462 Eigen::MatrixXd M = basis.matrix();
2463 for (size_t i = 0; i < size_t(M.rows()); i++) {
2464 for (size_t iqn = 0; iqn < quad.size(); iqn++) {
2465 basis_quad[i][iqn] = M(i,0) * ancestor_basis_quad[0][iqn];
2466 }
2467 for (size_t j = 1; j < size_t(M.cols()); j++) {
2468 for (size_t iqn = 0; iqn < quad.size(); iqn++) {
2469 basis_quad[i][iqn] += M(i,j) * ancestor_basis_quad[j][iqn];
2470 }
2471 } // for j
2472 } // for i
2473
2474 return basis_quad;
2475 }
2476
2478 template <typename BasisType, size_t N>
2479 static boost::multi_array<typename detail::basis_evaluation_traits<TensorizedVectorFamily<BasisType, N>, BasisFunction>::ReturnValue, 2>
2482 const QuadratureRule &quad
2483 )
2484 {
2486
2487 boost::multi_array<typename traits::ReturnValue, 2>
2488 basis_quad(boost::extents[basis.dimension()][quad.size()]);
2489
2490 const auto &ancestor_basis = basis.ancestor();
2491 const boost::multi_array<typename traits::AncestorBasisFunctionValue, 2> ancestor_basis_quad
2493
2494 for (size_t i = 0; i < basis.dimension(); i++){
2495 for (size_t iqn = 0; iqn < quad.size(); iqn++){
2496 basis_quad[i][iqn] = traits::evaluate(basis, i, iqn, ancestor_basis_quad);
2497 }
2498 }
2499 return basis_quad;
2500 }
2501
2503 template <typename BasisType, size_t N>
2504 static boost::multi_array<typename detail::basis_evaluation_traits<MatrixFamily<BasisType, N>, BasisFunction>::ReturnValue, 2>
2506 const MatrixFamily<BasisType, N> &basis,
2507 const QuadratureRule &quad
2508 )
2509 {
2511
2512 boost::multi_array<typename traits::ReturnValue, 2>
2513 basis_quad(boost::extents[basis.dimension()][quad.size()]);
2514
2515 const auto &ancestor_basis = basis.ancestor();
2516 const boost::multi_array<typename traits::AncestorBasisFunctionValue, 2> ancestor_basis_quad
2518
2519 for (size_t i = 0; i < basis.dimension(); i++){
2520 for (size_t iqn = 0; iqn < quad.size(); iqn++){
2521 basis_quad[i][iqn] = traits::evaluate(basis, i, iqn, ancestor_basis_quad);
2522 }
2523 }
2524 return basis_quad;
2525 }
2526 };
2527
2528 //------------------------------------------------------------------------------
2529 // ORTHONORMALISATION
2530 //------------------------------------------------------------------------------
2531
2540 template<typename T>
2541 Eigen::MatrixXd gram_schmidt(
2542 boost::multi_array<T, 2> & basis_eval,
2543 const std::function<double(size_t, size_t)> & inner_product
2544 )
2545 {
2546 auto induced_norm = [inner_product](size_t i)->double
2547 {
2548 return std::sqrt( inner_product(i, i) );
2549 };
2550
2551 // Number of basis functions
2552 size_t Nb = basis_eval.shape()[0];
2553 // Number of quadrature nodes
2554 size_t Nqn = basis_eval.shape()[1];
2555
2556 Eigen::MatrixXd B = Eigen::MatrixXd::Zero(Nb, Nb);
2557
2558 // Normalise the first element
2559 double norm = induced_norm(0);
2560 for (size_t iqn = 0; iqn < Nqn; iqn++) {
2561 basis_eval[0][iqn] /= norm;
2562 } // for iqn
2563 B(0,0) = 1./norm;
2564
2565 for (size_t ib = 1; ib < Nb; ib++) {
2566 // 'coeffs' represents the coefficients of the ib-th orthogonal function on the ON basis functions 0 to ib-1
2567 Eigen::RowVectorXd coeffs = Eigen::RowVectorXd::Zero(ib);
2568 for (size_t pb = 0; pb < ib; pb++) {
2569 coeffs(pb) = - inner_product(ib, pb);
2570 } // for pb
2571
2572 // store the values of the orthogonalised ib-th basis function
2573 for (size_t pb = 0; pb < ib; pb++) {
2574 for (size_t iqn = 0; iqn < Nqn; iqn++) {
2575 basis_eval[ib][iqn] += coeffs(pb) * basis_eval[pb][iqn];
2576 } // for iqn
2577 } // for pb
2578
2579 // normalise ib-th basis function
2580 double norm = induced_norm(ib);
2581 for (size_t iqn = 0; iqn < Nqn; iqn++) {
2582 basis_eval[ib][iqn] /= norm;
2583 } // for iqn
2584 coeffs /= norm;
2585 // Compute ib-th row of B.
2586 // B.topLeftCorner(ib, ib) contains the rows that represent the ON basis functions 0 to ib-1 on
2587 // the original basis. Multiplying on the left by coeffs gives the coefficients of the ON basis
2588 // functions on the original basis functions from 0 to ib-1.
2589 B.block(ib, 0, 1, ib) = coeffs * B.topLeftCorner(ib, ib);
2590 B(ib, ib) = 1./norm;
2591 }
2592 return B;
2593 }
2594
2595 //------------------------------------------------------------------------------
2596
2598 double scalar_product(const double & x, const double & y);
2599
2601 double scalar_product(const VectorRd & x, const VectorRd & y);
2602
2604 template<int N>
2605 double scalar_product(const Eigen::Matrix<double, N, N> & x, const Eigen::Matrix<double, N, N> & y)
2606 {
2607 return (x.transpose() * y).trace();
2608 }
2609
2611 template <typename Value>
2612 boost::multi_array<double, 2> scalar_product(
2613 const boost::multi_array<Value, 2> &basis_quad,
2614 const Value &v
2615 )
2616 {
2617 boost::multi_array<double, 2> basis_dot_v_quad(boost::extents[basis_quad.shape()[0]][basis_quad.shape()[1]]);
2618 std::transform(basis_quad.origin(), basis_quad.origin() + basis_quad.num_elements(),
2619 basis_dot_v_quad.origin(), [&v](const Value &x) -> double { return scalar_product(x,v); });
2620 return basis_dot_v_quad;
2621 }
2622
2624 template <typename Value>
2625 boost::multi_array<double, 2> scalar_product(
2626 const boost::multi_array<Value, 2> & basis_quad,
2627 const std::vector<Value> & v
2628 )
2629 {
2630 boost::multi_array<double, 2> basis_dot_v_quad(boost::extents[basis_quad.shape()[0]][basis_quad.shape()[1]]);
2631 for (std::size_t i = 0; i < basis_quad.shape()[0]; i++) {
2632 for (std::size_t iqn = 0; iqn < basis_quad.shape()[1]; iqn++) {
2633 basis_dot_v_quad[i][iqn] = scalar_product(basis_quad[i][iqn], v[iqn]);
2634 } // for iqn
2635 } // for i
2636 return basis_dot_v_quad;
2637 }
2638
2640 boost::multi_array<VectorRd, 2> matrix_vector_product(
2641 const boost::multi_array<MatrixRd, 2> & basis_quad,
2642 const std::vector<VectorRd> & v_quad
2643 );
2644
2646 boost::multi_array<VectorRd, 2> matrix_vector_product(
2647 const std::vector<MatrixRd> & m_quad,
2648 const boost::multi_array<VectorRd, 2> & basis_quad
2649 );
2650
2652 boost::multi_array<VectorRd, 2> vector_matrix_product(
2653 const std::vector<VectorRd> & v_quad,
2654 const boost::multi_array<MatrixRd, 2> & basis_quad
2655 );
2656
2658 template<typename BasisType>
2660 const BasisType & basis,
2661 const QuadratureRule & qr,
2662 boost::multi_array<typename BasisType::FunctionValue, 2> & basis_quad
2663 )
2664 {
2665 // Check that the basis evaluation and quadrature rule are coherent
2666 assert ( basis.dimension() == basis_quad.shape()[0] && qr.size() == basis_quad.shape()[1] );
2667
2668 // The inner product between the i-th and j-th basis vectors
2669 std::function<double(size_t, size_t)> inner_product
2670 = [&basis_quad, &qr](size_t i, size_t j)->double
2671 {
2672 double r = 0.;
2673 for(size_t iqn = 0; iqn < qr.size(); iqn++) {
2674 r += qr[iqn].w * scalar_product(basis_quad[i][iqn], basis_quad[j][iqn]);
2675 } // for iqn
2676 return r;
2677 };
2678
2679 Eigen::MatrixXd B = gram_schmidt(basis_quad, inner_product);
2680
2681 return Family<BasisType>(basis, B);
2682 }
2683
2685 /* This method is more robust that the previous one based on values at quadrature nodes */
2686 template <typename BasisType>
2688 const BasisType &basis,
2689 const Eigen::MatrixXd & GM
2690 )
2691 {
2692 // Check that the basis and Gram matrix are coherent
2693 assert(basis.dimension() == size_t(GM.rows()) && GM.rows() == GM.cols());
2694
2695 Eigen::MatrixXd L = GM.llt().matrixL();
2696
2697 return Family<BasisType>(basis, L.inverse());
2698 }
2699
2700
2701 //------------------------------------------------------------------------------
2702 // GRAM MATRICES
2703 //------------------------------------------------------------------------------
2704
2706 template<typename FunctionValue>
2707 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> & B1,
2708 const boost::multi_array<FunctionValue, 2> & B2,
2709 const QuadratureRule & qr,
2710 const size_t nrows,
2711 const size_t ncols,
2712 const std::string sym = "nonsym"
2713 )
2714 {
2715 // Check that the basis evaluation and quadrature rule are coherent
2716 assert ( qr.size() == B1.shape()[1] && qr.size() == B2.shape()[1] );
2717 // Check that we don't ask for more members of family than available
2718 assert ( nrows <= B1.shape()[0] && ncols <= B2.shape()[0] );
2719
2720 // Re-cast quadrature weights into ArrayXd to make computations faster
2721 Eigen::ArrayXd qr_weights = Eigen::ArrayXd::Zero(qr.size());
2722 for (size_t iqn = 0; iqn < qr.size(); iqn++){
2723 qr_weights(iqn) = qr[iqn].w;
2724 }
2725
2726 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(nrows, ncols);
2727 for (size_t i = 0; i < nrows; i++) {
2728 size_t jcut = 0;
2729 if ( sym=="sym" ) jcut = i;
2730 for (size_t j = 0; j < jcut; j++){
2731 M(i, j) = M(j, i);
2732 }
2733 for(size_t j = jcut; j < ncols; j++) {
2734 std::vector<double> tmp(B1.shape()[1]);
2735 // Extract values at quadrature nodes for elements i of B1 and j of B2
2736 auto B1i = B1[ boost::indices[i][boost::multi_array_types::index_range(0, B1.shape()[1])] ];
2737 auto B2j = B2[ boost::indices[j][boost::multi_array_types::index_range(0, B1.shape()[1])] ];
2738 // Compute scalar product of B1i and B2j, and recast it as ArrayXd
2739 std::transform(B1i.begin(), B1i.end(), B2j.begin(), tmp.begin(), [](FunctionValue a, FunctionValue b)->double { return scalar_product(a,b);});
2740 Eigen::ArrayXd tmp_array = Eigen::Map<Eigen::ArrayXd, Eigen::Unaligned>(tmp.data(), tmp.size());
2741 // Multiply by quadrature weights and sum (using .sum() of ArrayXd makes this step faster than a loop)
2742 M(i,j) = (qr_weights * tmp_array).sum();
2743
2744
2745 // Simple version with loop (replaces everything above after the for on j)
2746 /*
2747 for (size_t iqn = 0; iqn < qr.size(); iqn++) {
2748 M(i,j) += qr[iqn].w * scalar_product(B1[i][iqn], B2[j][iqn]);
2749 } // for iqn
2750 */
2751
2752 } // for j
2753 } // for i
2754 return M;
2755 }
2756
2758 template<typename FunctionValue>
2759 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> & B1,
2760 const boost::multi_array<FunctionValue, 2> & B2,
2761 const QuadratureRule & qr,
2762 const std::string sym = "nonsym"
2763 )
2764 {
2765 return compute_gram_matrix<FunctionValue>(B1, B2, qr, B1.shape()[0], B2.shape()[0], sym);
2766 }
2767
2769 template<typename FunctionValue>
2770 inline Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<FunctionValue, 2> & B,
2771 const QuadratureRule & qr
2772 )
2773 {
2774 return compute_gram_matrix<FunctionValue>(B, B, qr, "sym");
2775 }
2776
2778 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> & B1,
2779 const boost::multi_array<double, 2> & B2,
2780 const QuadratureRule & qr
2781 );
2782
2784 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<double, 2> & B1,
2785 const boost::multi_array<double, 2> & B2,
2786 const QuadratureRule & qr,
2787 const size_t nrows,
2788 const size_t ncols,
2789 const std::string sym = "nonsym"
2790 );
2791
2793 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<double, 2> & B1,
2794 const boost::multi_array<double, 2> & B2,
2795 const QuadratureRule & qr,
2796 const std::string sym = "nonsym"
2797 );
2798
2800 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> & B1,
2801 const boost::multi_array<VectorRd, 2> & B2,
2802 const QuadratureRule & qr,
2803 const size_t nrows,
2804 const size_t ncols,
2805 const std::string sym = "nonsym"
2806 );
2807
2809 Eigen::MatrixXd compute_gram_matrix(const boost::multi_array<VectorRd, 2> & B1,
2810 const boost::multi_array<VectorRd, 2> & B2,
2811 const QuadratureRule & qr,
2812 const std::string sym = "nonsym"
2813 );
2814
2816 template<typename ScalarFamilyType, size_t N>
2818 const boost::multi_array<double, 2> & scalar_family_quad,
2819 const QuadratureRule & qr
2820 )
2821 {
2822 Eigen::MatrixXd Gram = Eigen::MatrixXd::Zero(MatFam.dimension(), MatFam.dimension());
2823
2824 // Gram matrix of the scalar family
2825 Eigen::MatrixXd scalarGram = compute_gram_matrix<double>(scalar_family_quad, qr);
2826 for (size_t i = 0; i < MatFam.dimension(); i = i+scalarGram.rows()){
2827 Gram.block(i, i, scalarGram.rows(), scalarGram.cols()) = scalarGram;
2828 }
2829
2830 return Gram;
2831 }
2832
2833
2835
2836 template <typename T>
2837 Eigen::VectorXd integrate(
2838 const FType<T> &f,
2839 const BasisQuad<T> &B,
2840 const QuadratureRule &qr,
2841 size_t n_rows = 0
2842 )
2843 {
2844 // If default, set n_rows to size of family
2845 if (n_rows == 0)
2846 {
2847 n_rows = B.shape()[0];
2848 }
2849
2850 // Number of quadrature nodes
2851 const size_t num_quads = qr.size();
2852
2853 // Check number of quadrature nodes is compatible with B
2854 assert(num_quads == B.shape()[1]);
2855
2856 // Check that we don't ask for more members of family than available
2857 assert(n_rows <= B.shape()[0]);
2858
2859 Eigen::VectorXd V = Eigen::VectorXd::Zero(n_rows);
2860
2861 for (size_t iqn = 0; iqn < num_quads; iqn++)
2862 {
2863 double qr_weight = qr[iqn].w;
2864 T f_on_qr = f(qr[iqn].vector());
2865 for (size_t i = 0; i < n_rows; i++)
2866 {
2867 V(i) += qr_weight * scalar_product(B[i][iqn], f_on_qr);
2868 }
2869 }
2870
2871 return V;
2872 }
2873
2875 template <typename T, typename U>
2877 const FType<U> &f,
2878 const BasisQuad<T> &B1,
2879 const BasisQuad<T> &B2,
2880 const QuadratureRule &qr,
2881 size_t n_rows = 0,
2882 size_t n_cols = 0,
2883 const std::string sym = "nonsym"
2884 )
2885 {
2886 // If default, set n_rows and n_cols to size of families
2887 if (n_rows == 0 && n_cols == 0)
2888 {
2889 n_rows = B1.shape()[0];
2890 n_cols = B2.shape()[0];
2891 }
2892
2893 // Number of quadrature nodes
2894 const size_t num_quads = qr.size();
2895 // Check number of quadrature nodes is compatible with B1 and B2
2896 assert(num_quads == B1.shape()[1] && num_quads == B2.shape()[1]);
2897 // Check that we don't ask for more members of family than available
2898 assert(n_rows <= B1.shape()[0] && n_cols <= B2.shape()[0]);
2899
2900 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(n_rows, n_cols);
2901 for (size_t iqn = 0; iqn < num_quads; iqn++)
2902 {
2903 double qr_weight = qr[iqn].w;
2904 U f_on_qr = f(qr[iqn].vector());
2905 for (size_t i = 0; i < n_rows; i++)
2906 {
2907 T f_B1 = f_on_qr * B1[i][iqn];
2908 size_t jcut = 0;
2909 if (sym == "sym")
2910 jcut = i;
2911 for (size_t j = 0; j < jcut; j++)
2912 {
2913 M(i, j) = M(j, i);
2914 }
2915 for (size_t j = jcut; j < n_cols; j++)
2916 {
2917 M(i, j) += qr_weight * scalar_product(f_B1, B2[j][iqn]);
2918 }
2919 }
2920 }
2921 return M;
2922 }
2923
2925 template <typename T, typename U>
2927 const FType<U> &f,
2928 const BasisQuad<T> &B1,
2929 const BasisQuad<T> &B2,
2930 const QuadratureRule &qr,
2931 const std::string sym
2932 )
2933 {
2934 return compute_weighted_gram_matrix(f, B1, B2, qr, B1.shape()[0], B2.shape()[0], sym);
2935 }
2936
2938 Eigen::MatrixXd compute_weighted_gram_matrix(
2939 const FType<VectorRd> &f,
2940 const BasisQuad<VectorRd> &B1,
2941 const BasisQuad<double> &B2,
2942 const QuadratureRule &qr,
2943 size_t n_rows = 0,
2944 size_t n_cols = 0
2945 );
2946
2947
2949 Eigen::MatrixXd compute_weighted_gram_matrix(
2950 const FType<VectorRd> &f,
2951 const BasisQuad<double> &B1,
2952 const BasisQuad<VectorRd> &B2,
2953 const QuadratureRule &qr,
2954 size_t n_rows = 0,
2955 size_t n_cols = 0
2956 );
2957
2959 template <typename Value>
2960 Eigen::MatrixXd compute_closure_matrix(
2961 const boost::multi_array<Value, 2> & f_quad,
2962 const boost::multi_array<Value, 2> & g_quad,
2963 const QuadratureRule & qr_f,
2964 const QuadratureRule & qr_g
2965 )
2966 {
2967 const size_t dimf = f_quad.shape()[0];
2968 const size_t dimg = g_quad.shape()[0];
2969 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(dimf, dimg);
2970
2971 std::vector<Value> int_f(dimf);
2972 for (size_t i = 0; i < dimf; i++){
2973 int_f[i] = qr_f[0].w * f_quad[i][0];
2974 for (size_t iqn = 1; iqn < qr_f.size(); iqn++){
2975 int_f[i] += qr_f[iqn].w * f_quad[i][iqn];
2976 }
2977 }
2978 std::vector<Value> int_g(dimg);
2979 for (size_t j = 0; j < dimg; j++){
2980 int_g[j] = qr_g[0].w * g_quad[j][0];
2981 for (size_t iqn = 1; iqn < qr_g.size(); iqn++){
2982 int_g[j] += qr_g[iqn].w * g_quad[j][iqn];
2983 }
2984 }
2985
2986 // Compute (int w_i) and create dot product with (int w_j) for j<=i, then fill in M by symmetry
2987 for (size_t i = 0; i < dimf; i++){
2988 for (size_t j = 0; j < dimg; j++){
2989 M(i,j) = scalar_product(int_f[i], int_g[j]);
2990 }
2991 }
2992
2993 return M;
2994 }
2995
2997 template <typename Value>
2998 Eigen::MatrixXd compute_closure_matrix(
2999 const boost::multi_array<Value, 2> & f_quad,
3000 const boost::multi_array<Value, 2> & g_quad,
3001 const QuadratureRule & qr
3002 )
3003 {
3004 return compute_closure_matrix(f_quad, g_quad, qr, qr);
3005 }
3006
3008 template <typename Value>
3009 Eigen::MatrixXd compute_closure_matrix(
3010 const boost::multi_array<Value, 2> & f_quad,
3011 const QuadratureRule & qr
3012 )
3013 {
3014 return compute_closure_matrix(f_quad, f_quad, qr, qr);
3015 }
3016
3017 //------------------------------------------------------------------------------
3018 // L2 projection of a function
3019 //------------------------------------------------------------------------------
3020
3022 template<typename BasisType>
3023 Eigen::VectorXd l2_projection(
3024 const std::function<typename BasisType::FunctionValue(const VectorRd &)> & f,
3025 const BasisType & basis,
3026 QuadratureRule & quad,
3027 const boost::multi_array<typename BasisType::FunctionValue, 2> & basis_quad,
3028 const Eigen::MatrixXd &mass_basis = Eigen::MatrixXd::Zero(1,1)
3029 )
3030 {
3031 Eigen::MatrixXd Mass = mass_basis;
3032 if (Mass.norm() < 1e-13){
3033 Mass = compute_gram_matrix(basis_quad, quad);
3034 }
3035
3036 Eigen::LDLT<Eigen::MatrixXd> cholesky_mass(Mass);
3037 Eigen::VectorXd b = Eigen::VectorXd::Zero(basis.dimension());
3038 for (size_t i = 0; i < basis.dimension(); i++) {
3039 for (size_t iqn = 0; iqn < quad.size(); iqn++) {
3040 b(i) += quad[iqn].w * scalar_product(f(quad[iqn].vector()), basis_quad[i][iqn]);
3041 } // for iqn
3042 } // for i
3043
3044 return cholesky_mass.solve(b);
3045 }
3046
3047 //------------------------------------------------------------------------------
3048 // Decomposition on a polynomial basis
3049 //------------------------------------------------------------------------------
3050
3052
3057 template <typename BasisType>
3059 {
3061
3067 const Edge &E,
3068 const BasisType &basis
3069 ):
3070 m_dim(basis.dimension()),
3071 m_basis(basis),
3072 m_on_basis(basis, Eigen::MatrixXd::Identity(m_dim,m_dim)) // Need to initialise before we compute the real ON basis
3073 {
3074 /* The decomposition will be performed using an orthonormalised version of m_basis, for stability.
3075 The scalar product for which we orthonormalise is a minimal one (much less expensive than integrating
3076 over the edge): \sum_i phi(x_i) psi(x_i) where (x_i)_i are nodes that are sufficient to determine
3077 entirely polynomials up to the considered degree.
3078 The nodes we build here correspond to equidistant P^k nodes on the edge */
3079
3080 // Nodes
3081 m_nb_nodes = basis.max_degree() + 1;
3082 m_nodes.reserve(m_nb_nodes);
3083 double h = 1./std::max(1., double(basis.max_degree()));
3084 for (size_t i=0; i<m_nb_nodes; i++){
3085 VectorRd xi = E.vertex(0)->coords() + double(i) * h * (E.vertex(1)->coords() - E.vertex(0)->coords());
3086 m_nodes.emplace_back(xi.x(), xi.y(), 1.);
3087 }
3088
3089 // We then orthonormalise Orthonormalise basis for simple scalar product
3090 m_on_basis_nodes.resize(boost::extents[m_dim][m_nb_nodes]);
3093 };
3094
3097 const Cell &T,
3098 const BasisType &basis
3099 ):
3100 m_dim(basis.dimension()),
3101 m_basis(basis),
3102 m_on_basis(basis, Eigen::MatrixXd::Identity(m_dim,m_dim)) // Need to initialise before we compute the real ON basis
3103 {
3104 /* The decomposition will be performed using an orthonormalised version of m_basis, for stability.
3105 The scalar product for which we orthonormalise is a minimal one (much less expensive than integrating
3106 over the cell): \sum_i phi(x_i) psi(x_i) where (x_i)_i are nodes that are sufficient to determine
3107 entirely polynomials up to the considered degree.
3108 The nodes we build here correspond to P^k nodes on a tetrahedron */
3109
3110 // Create nodes
3111 std::vector<Eigen::Vector2i> indices = MonomialPowers<Cell>::complete(basis.max_degree());
3112 VectorRd e1 = VectorRd(1., 0.);
3113 VectorRd e2 = VectorRd(0., 1.);
3114 VectorRd x0 = T.center_mass() - T.diam()*VectorRd(1., 1.)/2.0;
3115
3116 // Nodes
3117 m_nb_nodes = indices.size();
3118 m_nodes.reserve(m_nb_nodes);
3119 for (size_t i=0; i<m_nb_nodes; i++){
3120 VectorRd xi = x0 + T.diam()*(double(indices[i](0)) * e1 + double(indices[i](1)) * e2)/std::max(1.,double(basis.max_degree()));
3121 m_nodes.emplace_back(xi.x(), xi.y(), 1.);
3122 }
3123
3124 // We then orthonormalise Orthonormalise basis for simple scalar product
3125 m_on_basis_nodes.resize(boost::extents[m_dim][m_nb_nodes]);
3128 };
3129
3132 {
3133 return m_nodes;
3134 };
3135
3138 boost::multi_array<typename BasisType::FunctionValue, 2> &values
3139 )
3140 {
3141 // Gram matrix of the polynomials and the ON basis
3142 Eigen::MatrixXd Gram_P_onbasis = compute_gram_matrix(values, m_on_basis_nodes, m_nodes);
3143 // L=matrix of P as a family of the ON basis. In theory, Gram_onbasis is identity, but due to rounding errors it
3144 // can be a bit different. Computing L as if it's not the case improves stability
3145 Eigen::MatrixXd Gram_onbasis = compute_gram_matrix(m_on_basis_nodes, m_nodes);
3146 Eigen::MatrixXd L = Gram_onbasis.ldlt().solve(Gram_P_onbasis.transpose());
3147 return Family<BasisType>(m_basis, L.transpose() * m_on_basis.matrix());
3148 };
3149
3150
3151 // Member variables
3152 size_t m_dim; // dimension of basis
3153 BasisType m_basis; // Basis on which we decompose
3154 Family<BasisType> m_on_basis; // Orthonormalised basis (for simple scalar product)
3155 boost::multi_array<typename BasisType::FunctionValue, 2> m_on_basis_nodes; // Values of ON basis at the nodes
3156 size_t m_nb_nodes; // nb of nodes
3158
3159 };
3160
3161
3163
3164} // end of namespace HArDCore2D
3165
3166#endif
Basis for the space of curls (vectorial rot) of polynomials.
Definition basis.hpp:1305
Basis (or rather family) of divergence of an existing basis.
Definition basis.hpp:1369
Definition basis.hpp:315
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:1625
Basis for the space of gradients of polynomials.
Definition basis.hpp:1242
Basis for the space of Hessians of polynomials.
Definition basis.hpp:1494
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:1679
Matrix family obtained from a scalar family.
Definition basis.hpp:750
Scalar monomial basis on a cell.
Definition basis.hpp:168
Scalar monomial basis on an edge.
Definition basis.hpp:243
Generate a basis restricted to the first "dimension" functions.
Definition basis.hpp:1131
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:1558
Basis (or rather family) of scalar rotor of an existing basis.
Definition basis.hpp:1430
Generate a basis where the function indices are shifted.
Definition basis.hpp:1020
Vector family for polynomial functions that are tangent to an edge (determined by the generator)
Definition basis.hpp:942
Vector family obtained by tensorization of a scalar family.
Definition basis.hpp:564
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:2092
void RotorValue
Definition basis.hpp:1501
static constexpr const TensorRankE tensorRank
Definition basis.hpp:576
VectorRd CurlValue
Definition basis.hpp:1434
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1636
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1277
TensorizedVectorFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition basis.hpp:2120
static const bool hasRotor
Definition basis.hpp:1575
Eigen::Matrix< double, N, dimspace > GradientValue
Definition basis.hpp:567
static const bool hasGradient
Definition basis.hpp:1572
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, size_t iqn, const boost::multi_array< MatrixRd, 2 > &ancestor_basis_quad)
Definition basis.hpp:2301
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:383
BasisType::GradientValue GradientValue
Definition basis.hpp:318
Cell GeometricSupport
Definition basis.hpp:1689
static const bool hasFunction
Definition basis.hpp:256
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:283
BasisType AncestorType
Definition basis.hpp:1451
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:2480
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
static const bool hasDivergence
Definition basis.hpp:1147
MatrixFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition basis.hpp:2387
VectorRd FunctionValue
Definition basis.hpp:1560
static const bool hasFunction
Definition basis.hpp:1033
static constexpr const bool hasAncestor
Definition basis.hpp:1692
size_t dimension() const
Return the dimension of the family.
Definition basis.hpp:979
double DivergenceValue
Definition basis.hpp:1374
VectorRd CurlValue
Definition basis.hpp:247
static const bool hasCurlCurl
Definition basis.hpp:587
BasisType::RotorValue ReturnValue
Definition basis.hpp:1983
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the Hessian of the i-th basis function at point x.
Definition basis.hpp:487
static const bool hasGradient
Definition basis.hpp:579
static const bool hasFunction
Definition basis.hpp:578
const size_t matrixSize() const
Return the dimension of the matrices in the family.
Definition basis.hpp:865
static const bool hasCurlCurl
Definition basis.hpp:1150
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:672
BasisType m_basis
Definition basis.hpp:3153
static constexpr const bool hasAncestor
Definition basis.hpp:954
BasisType::FunctionValue FunctionValue
Definition basis.hpp:317
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1569
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1531
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th function at point x.
Definition basis.hpp:356
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:2358
BasisType::FunctionValue ReturnValue
Definition basis.hpp:1842
static constexpr const bool hasAncestor
Definition basis.hpp:762
static const bool hasHessian
Definition basis.hpp:1576
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition basis.hpp:648
static const bool hasDivergence
Definition basis.hpp:184
size_t dimension() const
Return the dimension of the family.
Definition basis.hpp:799
void RotorValue
Definition basis.hpp:1564
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1314
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:2960
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1191
CurlBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1329
void HessianValue
Definition basis.hpp:572
BasisType::HessianValue HessianValue
Definition basis.hpp:322
MatrixGradient()
Default constructor.
Definition basis.hpp:125
static const bool hasCurlCurl
Definition basis.hpp:1263
VectorRd CurlValue
Definition basis.hpp:1373
BasisFunctionE
Definition basis.hpp:1740
double FunctionValue
Definition basis.hpp:1371
void RotorValue
Definition basis.hpp:174
static const bool hasHessian
Definition basis.hpp:1698
static const bool hasCurl
Definition basis.hpp:1512
static const bool hasFunction
Definition basis.hpp:1381
TensorizedVectorFamily< ScalarBasisType, N >::CurlCurlValue ReturnValue
Definition basis.hpp:2284
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_hessian_quad)
Definition basis.hpp:2013
static const bool hasDivergence
Definition basis.hpp:958
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:324
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_gradient_quad)
Definition basis.hpp:1921
static const bool hasRotor
Definition basis.hpp:1514
static constexpr const TensorRankE tensorRank
Definition basis.hpp:953
DivergenceBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1391
static constexpr const bool hasAncestor
Definition basis.hpp:1442
static constexpr const bool hasAncestor
Definition basis.hpp:1143
VectorRd CurlValue
Definition basis.hpp:946
static const bool hasGradient
Definition basis.hpp:1319
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_divergence_quad)
Definition basis.hpp:1967
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1441
void HessianValue
Definition basis.hpp:949
Eigen::Vector2d VectorRd
Definition basis.hpp:55
Eigen::Vector2i VectorZd
Definition basis.hpp:56
BasisType::RotorValue RotorValue
Definition basis.hpp:1026
void DivergenceValue
Definition basis.hpp:1630
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1439
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition basis.hpp:1309
static const bool hasHessian
Definition basis.hpp:960
static const bool hasGradient
Definition basis.hpp:956
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition basis.hpp:1308
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:320
Family(const BasisType &basis, const Eigen::MatrixXd &matrix)
Constructor.
Definition basis.hpp:339
TensorizedVectorFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition basis.hpp:2087
BasisType::GradientValue GradientValue
Definition basis.hpp:1134
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2392
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1915
static const bool hasRotor
Definition basis.hpp:1148
static const bool hasRotor
Definition basis.hpp:766
BasisType AncestorType
Definition basis.hpp:1517
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:2447
void GradientValue
Definition basis.hpp:1683
static const bool hasFunction
Definition basis.hpp:1693
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_curl_quad)
Definition basis.hpp:1944
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:720
static const bool hasRotor
Definition basis.hpp:1322
BasisType AncestorType
Definition basis.hpp:336
static const bool hasDivergence
Definition basis.hpp:259
static const bool hasCurl
Definition basis.hpp:258
void HessianValue
Definition basis.hpp:1249
static const bool hasCurl
Definition basis.hpp:957
size_t dimension() const
Dimension of the family. This is actually the number of functions in the family, not necessarily line...
Definition basis.hpp:350
static const bool hasDivergence
Definition basis.hpp:1513
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1289
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:2336
static const bool hasCurl
Definition basis.hpp:1640
void GradientValue
Definition basis.hpp:1498
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:688
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2289
void HessianValue
Definition basis.hpp:250
RestrictedBasis(const BasisType &basis, const size_t &dimension)
Constructor.
Definition basis.hpp:1155
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2256
BasisType::CurlValue CurlValue
Definition basis.hpp:1024
static const bool hasFunction
Definition basis.hpp:1255
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2030
BasisType::HessianValue HessianValue
Definition basis.hpp:1138
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1345
Edge GeometricSupport
Definition basis.hpp:951
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2125
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:877
GradientBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1268
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:830
VectorRd generator() const
Returns the generator of the basis functions.
Definition basis.hpp:1003
static const bool hasCurl
Definition basis.hpp:583
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1316
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.hpp:628
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:331
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1465
TensorizedVectorFamily< ScalarBasisType, N >::FunctionValue ReturnValue
Definition basis.hpp:2055
void DivergenceValue
Definition basis.hpp:248
static const bool hasHessian
Definition basis.hpp:1385
VectorRd FunctionValue
Definition basis.hpp:1627
static const bool hasHessian
Definition basis.hpp:1262
Cell GeometricSupport
Definition basis.hpp:1634
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:871
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.hpp:839
MatrixGradient & operator+=(const MatrixGradient &G)
Increment.
Definition basis.hpp:137
void RotorValue
Definition basis.hpp:948
static const bool hasCurlCurl
Definition basis.hpp:1577
RotorBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1454
VectorRd GradientValue
Definition basis.hpp:1433
ScalarFamilyType AncestorType
Definition basis.hpp:771
size_t dimension() const
Return the dimension of the basis.
Definition basis.hpp:1168
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:638
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:396
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:608
MatrixGradient< N > GradientValue
Definition basis.hpp:753
double scalar_product(const double &x, const double &y)
Scalar product between two reals.
Definition basis.cpp:163
VectorRd CurlCurlValue
Definition basis.hpp:569
void HessianValue
Definition basis.hpp:1502
size_t dimension() const
Dimension of the basis.
Definition basis.hpp:1654
Eigen::Matrix< double, N, 1 > FunctionValue
Definition basis.hpp:566
void DivergenceValue
Definition basis.hpp:1685
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:618
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:1133
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1504
static constexpr const bool hasAncestor
Definition basis.hpp:1254
QuadratureRule m_nodes
Nodes for the interpolation.
Definition basis.hpp:3157
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:1812
BasisType AncestorType
Definition basis.hpp:1152
BasisType::GradientValue ReturnValue
Definition basis.hpp:1866
TensorizedVectorFamily< ScalarBasisType, N >::CurlValue ReturnValue
Definition basis.hpp:2185
static constexpr const bool hasAncestor
Definition basis.hpp:577
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1031
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:1283
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition basis.hpp:1245
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:2233
BasisType::RotorValue RotorValue
Definition basis.hpp:321
static const bool hasGradient
Definition basis.hpp:1145
BasisType::DivergenceValue ReturnValue
Definition basis.hpp:1960
static const bool hasCurl
Definition basis.hpp:767
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:726
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_gradient_quad)
Definition basis.hpp:1897
static const bool hasHessian
Definition basis.hpp:333
static const std::vector< VectorRd > basisRd
Definition basis.hpp:58
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1029
static const bool hasDivergence
Definition basis.hpp:581
static const bool hasDivergence
Definition basis.hpp:1446
static const bool hasHessian
Definition basis.hpp:768
static constexpr const bool hasAncestor
Definition basis.hpp:1507
void HessianValue
Definition basis.hpp:1312
static const bool hasHessian
Definition basis.hpp:1323
static const bool hasCurlCurl
Definition basis.hpp:1386
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1142
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:500
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:1180
static const bool hasCurlCurl
Definition basis.hpp:262
TangentFamily(const ScalarFamilyType &scalar_family, const VectorRd &generator)
Constructor.
Definition basis.hpp:966
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:985
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:680
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1707
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition basis.hpp:664
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1586
MatrixFamily< ScalarBasisType, N >::DivergenceValue ReturnValue
Definition basis.hpp:2353
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:2102
CurlCurlValue curlcurl(size_t i, size_t iqn, const boost::multi_array< typename ScalarFamilyType::HessianValue, 2 > &ancestor_hessian_quad) const
Evaluate the curl curl of the i-th basis function at a quadrature point iqn, knowing all the values o...
Definition basis.hpp:708
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:1022
void HessianValue
Definition basis.hpp:1565
static const bool hasHessian
Definition basis.hpp:1643
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1253
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1073
static ReturnValue evaluate(const MatrixFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2326
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:1754
static const bool hasDivergence
Definition basis.hpp:1384
static constexpr const TensorRankE tensorRank
Definition basis.hpp:254
size_t dimension() const
Return the dimension of the basis.
Definition basis.hpp:1055
VectorRd FunctionValue
Definition basis.hpp:944
static const bool hasHessian
Definition basis.hpp:261
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:2505
static const bool hasFunction
Definition basis.hpp:955
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:1105
static const bool hasFunction
Definition basis.hpp:763
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:196
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:1067
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1691
static const bool hasCurlCurl
Definition basis.hpp:769
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.hpp:1081
ScalarFamilyType::GeometricSupport GeometricSupport
Definition basis.hpp:759
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition basis.hpp:1089
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:2402
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1537
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:805
boost::multi_array< typename BasisType::FunctionValue, 2 > m_on_basis_nodes
Definition basis.hpp:3155
double RotorValue
Definition basis.hpp:1631
void RotorValue
Definition basis.hpp:1311
Eigen::Matrix2d MatrixRd
Definition basis.hpp:54
BasisType::DivergenceValue DivergenceValue
Definition basis.hpp:1025
GradientValue CurlValue
Definition basis.hpp:568
BasisType::CurlValue ReturnValue
Definition basis.hpp:1937
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:474
static const bool hasDivergence
Definition basis.hpp:765
TensorizedVectorFamily< ScalarBasisType, N >::RotorValue ReturnValue
Definition basis.hpp:2251
CurlCurlValue curlcurl(size_t i, const VectorRd &x) const
Evaluate the curl curl of the i-th basis function at point x. We use the formula curl curl = - Laplac...
Definition basis.hpp:696
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:2200
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th basis function at point x.
Definition basis.hpp:1207
static const bool hasRotor
Definition basis.hpp:1261
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2158
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2060
void RotorValue
Definition basis.hpp:1686
static std::function< Eigen::MatrixXd(const Eigen::MatrixXd &)> symmetrise_matrix
Function to symmetrise a matrix (useful together with transform_values_quad)
Definition basis.hpp:1803
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition basis.hpp:1097
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:220
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th function at point x.
Definition basis.hpp:435
static constexpr const bool hasAncestor
Definition basis.hpp:1032
BasisType::GradientValue FunctionValue
Definition basis.hpp:1244
static const bool hasGradient
Definition basis.hpp:1639
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition basis.hpp:1629
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:214
VectorRd FunctionValue
Definition basis.hpp:1307
void DivergenceValue
Definition basis.hpp:1247
void DivergenceValue
Definition basis.hpp:947
constexpr const BasisType & ancestor() const
Return the underlying complete basis.
Definition basis.hpp:1061
BasisType::GradientValue GradientValue
Definition basis.hpp:1023
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
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th basis function at point x.
Definition basis.hpp:1199
static const bool hasHessian
Definition basis.hpp:1448
double DivergenceValue
Definition basis.hpp:1563
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:461
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:2266
VectorRd GradientValue
Definition basis.hpp:945
constexpr const BasisType & ancestor() const
Return the underlying complete basis.
Definition basis.hpp:1174
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:3023
void CurlValue
Definition basis.hpp:1684
BasisType AncestorType
Definition basis.hpp:1326
static const bool hasCurlCurl
Definition basis.hpp:961
static const bool hasCurl
Definition basis.hpp:1146
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1506
static const bool hasCurl
Definition basis.hpp:1259
static const bool hasFunction
Definition basis.hpp:1571
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:1447
void DivergenceValue
Definition basis.hpp:1500
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:813
static const bool hasGradient
Definition basis.hpp:257
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:1567
MatrixFamily(const ScalarFamilyType &scalar_family)
Definition basis.hpp:773
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:908
Eigen::MatrixXd gram_schmidt(boost::multi_array< T, 2 > &basis_eval, const std::function< double(size_t, size_t)> &inner_product)
Definition basis.hpp:2541
CurlValue curl(size_t i, const VectorRd &x) const
Evaluate the curl of the i-th function at point x.
Definition basis.hpp:409
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2190
VectorRd CurlValue
Definition basis.hpp:754
static const bool hasRotor
Definition basis.hpp:185
BasisType::GradientValue ReturnValue
Definition basis.hpp:1890
static constexpr const bool hasAncestor
Definition basis.hpp:1637
DivergenceValue divergence(size_t i, const VectorRd &x) const
Evaluate the divergence of the i-th basis function at point x.
Definition basis.hpp:1215
void RotorValue
Definition basis.hpp:1248
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:1351
static const bool hasCurl
Definition basis.hpp:330
BasisType::CurlValue CurlValue
Definition basis.hpp:319
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1938
static const bool hasGradient
Definition basis.hpp:1258
MatrixRd FunctionValue
Definition basis.hpp:1681
static const bool hasGradient
Definition basis.hpp:1382
Family< BasisType > m_on_basis
Definition basis.hpp:3154
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:1807
static const bool hasCurl
Definition basis.hpp:1573
void RotorValue
Definition basis.hpp:756
static constexpr const bool hasAncestor
Definition basis.hpp:255
BasisType::HessianValue HessianValue
Definition basis.hpp:1027
static ReturnValue evaluate(const TensorizedVectorFamily< ScalarBasisType, N > &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2223
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:448
static const bool hasCurlCurl
Definition basis.hpp:334
double DivergenceValue
Definition basis.hpp:570
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:1265
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:821
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1414
RotorValue rotor(size_t i, const VectorRd &x) const
Evaluate the rotor of the i-th basis function at point x.
Definition basis.hpp:1223
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:422
static constexpr const TensorRankE tensorRank
Definition basis.hpp:761
static const bool hasRotor
Definition basis.hpp:582
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition basis.hpp:1561
Eigen::Matrix< double, N, N > dx
Definition basis.hpp:149
static const bool hasGradient
Definition basis.hpp:1444
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:2659
static const bool hasDivergence
Definition basis.hpp:1696
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1377
static constexpr const TensorRankE tensorRank
Definition basis.hpp:179
constexpr const BasisType & ancestor() const
Return the ancestor.
Definition basis.hpp:519
static const bool hasDivergence
Definition basis.hpp:1321
static const bool hasCurl
Definition basis.hpp:1035
Eigen::Matrix< double, N, N > FunctionValue
Definition basis.hpp:752
VectorRd GradientValue
Definition basis.hpp:1372
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:1769
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1984
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:3137
static const bool hasRotor
Definition basis.hpp:332
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1339
static const bool hasFunction
Definition basis.hpp:1318
ScalarFamilyType AncestorType
Definition basis.hpp:963
size_t dimension() const
Return the dimension of the family.
Definition basis.hpp:602
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:2007
static const bool hasCurl
Definition basis.hpp:1320
const ScalarFamilyType & ancestor() const
Return the ancestor (family that has been tensorized)
Definition basis.hpp:859
size_t dimension() const
Compute the dimension of the basis.
Definition basis.hpp:1402
static const bool hasGradient
Definition basis.hpp:1511
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:1990
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1140
VectorRd CurlValue
Definition basis.hpp:1246
BasisType AncestorType
Definition basis.hpp:1041
void HessianValue
Definition basis.hpp:1375
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:369
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:849
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:1598
MatrixRd FunctionValue
Definition basis.hpp:1496
Eigen::Matrix< double, dimspace, dimspace > GradientValue
Definition basis.hpp:1628
VectorRd GradientValue
Definition basis.hpp:246
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:1716
DecomposePoly(const Cell &T, const BasisType &basis)
Constructor for cell.
Definition basis.hpp:3096
static const bool hasGradient
Definition basis.hpp:764
static const bool hasRotor
Definition basis.hpp:260
static const bool hasCurlCurl
Definition basis.hpp:1644
static const bool hasCurl
Definition basis.hpp:1445
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1961
static const bool hasRotor
Definition basis.hpp:1697
void RotorValue
Definition basis.hpp:1436
TensorizedVectorFamily< ScalarBasisType, N >::GradientValue ReturnValue
Definition basis.hpp:2153
static const bool hasDivergence
Definition basis.hpp:1260
static const bool hasHessian
Definition basis.hpp:1038
void HessianValue
Definition basis.hpp:1632
static const bool hasFunction
Definition basis.hpp:1144
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_gradient_quad)
Definition basis.hpp:1873
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:883
static const bool hasRotor
Definition basis.hpp:1642
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:997
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:571
BasisType::DivergenceValue DivergenceValue
Definition basis.hpp:1136
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1843
ScalarFamilyType::GeometricSupport GeometricSupport
Definition basis.hpp:574
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:2837
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_value_quad)
Definition basis.hpp:1849
BasisType::CurlCurlValue ReturnValue
Definition basis.hpp:2029
VectorZd powers(size_t i) const
Returns the powers of the i-th basis function (not including the vector part)
Definition basis.hpp:1604
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1471
static const bool hasHessian
Definition basis.hpp:586
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition basis.hpp:525
HessianBasis(const BasisType &basis)
Constructor.
Definition basis.hpp:1520
static const bool hasRotor
Definition basis.hpp:959
void HessianValue
Definition basis.hpp:757
Eigen::Matrix< double, N, N > dy
Definition basis.hpp:150
BasisType::GeometricSupport GeometricSupport
Definition basis.hpp:1251
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1891
static const bool hasFunction
Definition basis.hpp:328
static const bool hasGradient
Definition basis.hpp:182
ShiftedBasis(const BasisType &basis, const int shift)
Constructor.
Definition basis.hpp:1044
static constexpr const bool hasAncestor
Definition basis.hpp:1570
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th basis function at point x.
Definition basis.hpp:1408
HessianValue hessian(size_t i, const VectorRd &x) const
Evaluate the Hessian of the i-th basis function at point x.
Definition basis.hpp:1113
ScalarFamilyType AncestorType
Definition basis.hpp:589
void HessianValue
Definition basis.hpp:1687
const std::shared_ptr< RolyComplBasisCell > & rck() const
Return the Rck basis.
Definition basis.hpp:1666
void CurlValue
Definition basis.hpp:1499
static const bool hasHessian
Definition basis.hpp:1515
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:656
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1477
static const bool hasGradient
Definition basis.hpp:329
static const bool hasCurlCurl
Definition basis.hpp:1039
static constexpr const TensorRankE tensorRank
Definition basis.hpp:326
static constexpr const TensorRankE tensorRank
Definition basis.hpp:1379
size_t dimension() const
Dimension of the basis.
Definition basis.hpp:271
static constexpr const bool hasAncestor
Definition basis.hpp:1317
static const bool hasCurlCurl
Definition basis.hpp:1449
void DivergenceValue
Definition basis.hpp:1310
static const bool hasFunction
Definition basis.hpp:1508
BasisType AncestorType
Definition basis.hpp:1388
static const bool hasDivergence
Definition basis.hpp:1574
QuadratureRule get_nodes() const
Return the set of nodes (useful to compute value of polynomial to decompose via evaluate_quad)
Definition basis.hpp:3131
static const bool hasFunction
Definition basis.hpp:1638
DecomposePoly(const Edge &E, const BasisType &basis)
Constructor for edge.
Definition basis.hpp:3066
void HessianValue
Definition basis.hpp:1437
size_t m_dim
Definition basis.hpp:3152
static ReturnValue evaluate(const BasisType &basis, size_t i, size_t iqn, const boost::multi_array< ReturnValue, 2 > &ancestor_curlcurl_quad)
Definition basis.hpp:2036
static const bool hasCurlCurl
Definition basis.hpp:187
static const bool hasCurl
Definition basis.hpp:1695
static const bool hasCurl
Definition basis.hpp:183
Edge GeometricSupport
Definition basis.hpp:252
static const bool hasCurlCurl
Definition basis.hpp:1324
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:2070
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:991
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:2425
double FunctionValue
Definition basis.hpp:1432
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:2368
BasisType::HessianValue ReturnValue
Definition basis.hpp:2006
Eigen::Matrix< double, N, 1 > DivergenceValue
Definition basis.hpp:755
static const bool hasDivergence
Definition basis.hpp:1036
const Eigen::MatrixXd & matrix() const
Return the coefficient matrix.
Definition basis.hpp:513
size_t m_nb_nodes
Definition basis.hpp:3156
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition basis.hpp:1543
static const bool hasDivergence
Definition basis.hpp:1641
static const bool hasRotor
Definition basis.hpp:1037
static const bool hasGradient
Definition basis.hpp:1034
MatrixGradient operator-(const MatrixGradient &G)
Subtraction.
Definition basis.hpp:144
MatrixFamily< ScalarBasisType, N >::FunctionValue ReturnValue
Definition basis.hpp:2321
double FunctionValue
Definition basis.hpp:245
static const bool hasCurl
Definition basis.hpp:1383
static constexpr const bool hasAncestor
Definition basis.hpp:327
static constexpr const bool hasAncestor
Definition basis.hpp:1380
static const bool hasHessian
Definition basis.hpp:1149
static const bool hasGradient
Definition basis.hpp:1694
static ReturnValue evaluate(const BasisType &basis, size_t i, const VectorRd &x)
Definition basis.hpp:1867
TensorizedVectorFamily< ScalarBasisType, N >::DivergenceValue ReturnValue
Definition basis.hpp:2218
TensorizedVectorFamily(const ScalarFamilyType &scalar_family)
Definition basis.hpp:591
static const bool hasFunction
Definition basis.hpp:1443
BasisType::CurlValue CurlValue
Definition basis.hpp:1135
Eigen::Matrix< double, dimspace, dimspace > CurlValue
Definition basis.hpp:1562
void RotorValue
Definition basis.hpp:249
void DivergenceValue
Definition basis.hpp:1435
BasisType::RotorValue RotorValue
Definition basis.hpp:1137
VectorRd CurlValue
Definition basis.hpp:172
@ Curl
Definition basis.hpp:1745
@ Function
Definition basis.hpp:1741
@ CurlCurl
Definition basis.hpp:1749
@ Gradient
Definition basis.hpp:1742
@ SkewsymmetricGradient
Definition basis.hpp:1744
@ Rotor
Definition basis.hpp:1747
@ Divergence
Definition basis.hpp:1746
@ SymmetricGradient
Definition basis.hpp:1743
@ Hessian
Definition basis.hpp:1748
@ 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:3059
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:1834
Evaluate a basis at quadrature nodes. 'BasisFunction' (=Function, Gradient, Curl, Divergence,...
Definition basis.hpp:2421