HArD::Core3D
Hybrid Arbitrary Degree::Core 3D - Library to implement 3D schemes with vertex, edge, face and cell polynomials as unknowns
GMpoly_cell.hpp
Go to the documentation of this file.
1 # ifndef _GMPOLY_CELL_HPP
2 # define _GMPOLY_CELL_HPP
3 
4 /*
5 
6  Classes to implement the quadrature-free polynomial integration rules
7 
8 */
9 
10 #include <cassert>
11 #include <cmath>
12 
13 #include <algorithm>
14 #include <array>
15 #include <iostream>
16 #include <vector>
17 #include <unordered_map>
18 
19 #include <mesh.hpp>
20 #include <quadraturerule.hpp>
21 #include <basis.hpp>
22 #include <typeinfo>
23 
24 namespace HArDCore3D {
25 
32 //----------------------------------------------------------------------
33 //----------------------------------------------------------------------
34 // INTEGRALS OF MONOMIALS
35 //----------------------------------------------------------------------
36 //----------------------------------------------------------------------
37 
39 struct VecHash
40 {
41  size_t operator()(const VectorZd & p) const
42  {
43  constexpr size_t b = 100; // max degree must be less than the basis b
44  return p(0) + p(1) * b + p(2) * b*b;
45  }
46 };
47 
49 typedef std::unordered_map<VectorZd, double, VecHash> MonomialCellIntegralsType;
50 
52 std::vector<MonomialCellIntegralsType> IntegrateCellMonomials_onEdges
53  (const Cell & T,
54  const size_t maxdeg
55  );
56 
58 std::vector<MonomialCellIntegralsType> IntegrateCellMonomials_onFaces
59  (const Cell & T,
60  const size_t maxdeg,
61  std::vector<MonomialCellIntegralsType> & integrals_edges
62  );
63 
66  (const Cell & T,
67  const int maxdeg
68  );
69 
72  (const Cell & T,
73  const size_t degree,
74  const MonomialCellIntegralsType & mono_int_map = {}
75  );
76 
77 //----------------------------------------------------------------------
78 //----------------------------------------------------------------------
79 // TRANSFORMATIONS OF GRAM MATRICES FOR DERIVED BASES
80 //----------------------------------------------------------------------
81 //----------------------------------------------------------------------
82 
84 template<typename BasisType>
85 inline Eigen::MatrixXd transformGM(const Family<BasisType> & family_basis,
86  const char RC,
87  const Eigen::MatrixXd & anc_GM
88  )
89  {
90  if (RC=='R'){
91  return family_basis.matrix() * anc_GM;
92  }else{
93  return anc_GM * (family_basis.matrix()).transpose();
94  }
95  }
96 
98 template<typename BasisType>
99 inline Eigen::MatrixXd transformGM(const RestrictedBasis<BasisType> & restr_basis,
100  const char RC,
101  const Eigen::MatrixXd & anc_GM
102  )
103  {
104  if (RC=='R'){
105  return anc_GM.topRows(restr_basis.dimension());
106  }else{
107  return anc_GM.leftCols(restr_basis.dimension());
108  }
109  }
110 
112 template<typename BasisType>
113 inline Eigen::MatrixXd transformGM(const ShiftedBasis<BasisType> & shifted_basis,
114  const char RC,
115  const Eigen::MatrixXd & anc_GM
116  )
117  {
118  if (RC=='R'){
119  return anc_GM.bottomRows(shifted_basis.dimension());
120  }else{
121  return anc_GM.rightCols(shifted_basis.dimension());
122  }
123  }
124 
125 
126 //----------------------------------------------------------------------
127 //----------------------------------------------------------------------
128 // FUNCTIONS TO COMPUTE GRAM MATRICES
129 //----------------------------------------------------------------------
130 //----------------------------------------------------------------------
131 
132 //
133 /* BASIC ONES: Monomial, tensorized, and generic template */
134 
136 Eigen::MatrixXd GramMatrix(
137  const Cell & T,
138  const MonomialScalarBasisCell & basis1,
139  const MonomialScalarBasisCell & basis2,
140  MonomialCellIntegralsType mono_int_map = {}
141  );
142 
144 template<typename BasisType>
145 Eigen::MatrixXd GramMatrix(const Cell& T, const BasisType & basis, MonomialCellIntegralsType mono_int_map = {})
146  {
147  return GramMatrix(T, basis, basis, mono_int_map);
148  }
149 
151 template<typename BasisType1, typename BasisType2, size_t N>
152 Eigen::MatrixXd GramMatrix(
153  const Cell& T,
156  MonomialCellIntegralsType mono_int_map = {}
157  )
158  {
159  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(basis1.dimension(), basis2.dimension());
160 
161  Eigen::MatrixXd anc_gm = GramMatrix(T, basis1.ancestor(), basis2.ancestor(), mono_int_map);
162  size_t dim1 = anc_gm.rows();
163  size_t dim2 = anc_gm.cols();
164 
165  for (size_t i=0; i<N; i++){
166  gm.block(i*dim1, i*dim2, dim1, dim2) = anc_gm;
167  }
168  return gm;
169  }
170 
171 
173 Eigen::MatrixXd GramMatrix(
174  const Cell & T,
175  const RolyComplBasisCell & basis1,
176  const RolyComplBasisCell & basis2,
177  MonomialCellIntegralsType mono_int_map = {}
178  );
179 
181 template<typename BasisType1, size_t N>
182 Eigen::MatrixXd GramMatrix(
183  const Cell & T,
184  const RolyComplBasisCell & rolycompl_basis,
185  const TensorizedVectorFamily<BasisType1, N> & tens_family,
186  MonomialCellIntegralsType mono_int_map = {}
187  )
188  {
189  size_t dim1 = rolycompl_basis.dimension();
190  size_t dim2 = tens_family.dimension();
191  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1, dim2);
192 
193  // Integrals of monomials
194  size_t totaldegree = rolycompl_basis.max_degree()+tens_family.max_degree();
195  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
196 
197  for (size_t m=0; m<N; m++){
198  gm.block(0, m*dim2/N, dim1, dim2/N) = GMRolyComplScalar(T, rolycompl_basis, tens_family.ancestor(), m, intmap);
199  }
200  return gm;
201  }
202 
204 template<typename BasisType1, size_t N>
205 Eigen::MatrixXd GramMatrix(
206  const Cell & T,
207  const TensorizedVectorFamily<BasisType1, N> & tens_family,
208  const RolyComplBasisCell & rolycompl_basis,
209  MonomialCellIntegralsType mono_int_map = {}
210  )
211  {
212  return GramMatrix(T, rolycompl_basis, tens_family, mono_int_map).transpose();
213  }
214 
216 Eigen::MatrixXd GramMatrix(
217  const Cell & T,
218  const GolyComplBasisCell & basis1,
219  const GolyComplBasisCell & basis2,
220  MonomialCellIntegralsType mono_int_map = {}
221  );
222 
224 template<typename BasisType1, size_t N>
225 Eigen::MatrixXd GramMatrix(
226  const Cell & T,
227  const GolyComplBasisCell & golycompl_basis,
228  const TensorizedVectorFamily<BasisType1, N> & tens_family,
229  MonomialCellIntegralsType mono_int_map = {}
230  )
231  {
232  size_t dim1 = golycompl_basis.dimension();
233  size_t dim2 = tens_family.dimension();
234  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1, dim2);
235 
236  // Integrals of monomials
237  size_t totaldegree = golycompl_basis.max_degree()+tens_family.max_degree();
238  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
239 
240  size_t dim_l1 = golycompl_basis.dimPkmo();
241  size_t dim_l2 = tens_family.ancestor().dimension();
242  gm.block(0, dim_l2, dim_l1, dim_l2) = GMGolyComplScalar(T, golycompl_basis, tens_family.ancestor(), 0, intmap, 2);
243  gm.block(0, 2*dim_l2, dim_l1, dim_l2) = -GMGolyComplScalar(T, golycompl_basis, tens_family.ancestor(), 0, intmap, 1);
244  gm.block(dim_l1, 0, dim_l1, dim_l2) = -GMGolyComplScalar(T, golycompl_basis, tens_family.ancestor(), 1, intmap, 2);
245  gm.block(dim_l1, 2*dim_l2, dim_l1, dim_l2) = GMGolyComplScalar(T, golycompl_basis, tens_family.ancestor(), 1, intmap, 0);
246  gm.block(2*dim_l1, 0, dim1-2*dim_l1, dim_l2) = GMGolyComplScalar(T, golycompl_basis, tens_family.ancestor(), 2, intmap, 1);
247  gm.block(2*dim_l1, dim_l2, dim1-2*dim_l1, dim_l2) = -GMGolyComplScalar(T, golycompl_basis, tens_family.ancestor(), 2, intmap, 0);
248 
249  return gm;
250  }
251 
253 template<typename BasisType1, size_t N>
254 Eigen::MatrixXd GramMatrix(
255  const Cell & T,
256  const TensorizedVectorFamily<BasisType1, N> & tens_family,
257  const GolyComplBasisCell & golycompl_basis,
258  MonomialCellIntegralsType mono_int_map = {}
259  )
260  {
261  return GramMatrix(T, golycompl_basis, tens_family, mono_int_map).transpose();
262  }
263 
265 Eigen::MatrixXd GMRolyComplScalar(
266  const Cell & T,
267  const RolyComplBasisCell & rolycompl_basis,
268  const MonomialScalarBasisCell & mono_basis,
269  const size_t m,
270  MonomialCellIntegralsType mono_int_map = {}
271  );
272 
274 template<typename BasisType>
275 Eigen::MatrixXd GMRolyComplScalar(
276  const Cell& T,
277  const RolyComplBasisCell & basis1,
278  const BasisType & basis2,
279  const size_t m,
280  MonomialCellIntegralsType mono_int_map = {}
281  )
282  {
283  // If no ancestor is to be used, we shouldn't be in this overload
284  static_assert(BasisType::hasAncestor, "No method to compute this Gram matrix of derivatives");
285  return transformGM(basis2, 'C', GMRolyComplScalar(T, basis1, basis2.ancestor(), m, mono_int_map) );
286  }
287 
289 Eigen::MatrixXd GMGolyComplScalar(
290  const Cell & T,
291  const GolyComplBasisCell & golycompl_basis,
292  const MonomialScalarBasisCell & mono_basis,
293  const size_t s,
294  MonomialCellIntegralsType mono_int_map,
295  const size_t m = 3,
296  const size_t k1 = 3,
297  const size_t k2 = 3
298  );
299 
301 template<typename BasisType>
302 Eigen::MatrixXd GMGolyComplScalar(
303  const Cell& T,
304  const GolyComplBasisCell & basis1,
305  const BasisType & basis2,
306  const size_t s,
307  MonomialCellIntegralsType mono_int_map,
308  const size_t m = 3,
309  const size_t k1 = 3,
310  const size_t k2 = 3
311  )
312  {
313  // If no ancestor is to be used, we shouldn't be in this overload
314  static_assert(BasisType::hasAncestor, "No method to compute this Gram matrix of derivatives");
315  return transformGM(basis2, 'C', GMGolyComplScalar(T, basis1, basis2.ancestor(), s, mono_int_map, m, k1, k2) );
316  }
317 
319 Eigen::MatrixXd GMGolyCompl(
320  const Cell & T,
321  const GolyComplBasisCell & basis1,
322  const GolyComplBasisCell & basis2,
323  const size_t s1,
324  const size_t s2,
325  MonomialCellIntegralsType mono_int_map,
326  const size_t m1 = 3,
327  const size_t m2 = 3,
328  const size_t k1 = 3,
329  const size_t k2 = 3
330  );
331 
332 
334 template<typename BasisType>
335 constexpr bool useAncestor()
336  {
337  // For a given basis, we only use the ancestor if it has an ancestor and has the same rank as its
338  // ancestor. If it has a different rank than its ancestor, it must be dealt with a specific overload
339 
340  if constexpr(BasisType::hasAncestor){
341  return (BasisType::tensorRank == BasisType::AncestorType::tensorRank);
342  } else {
343  return false;
344  }
345  }
346 
348 template<typename BasisType1, typename BasisType2>
349 Eigen::MatrixXd GramMatrix(const Cell& T,
350  const BasisType1 & basis1,
351  const BasisType2 & basis2,
352  MonomialCellIntegralsType mono_int_map = {}
353  )
354  {
355  // If no ancestor is to be used, we shouldn't be in this overload
356  static_assert(useAncestor<BasisType1>() || useAncestor<BasisType2>(), "No method to compute this Gram matrix");
357 
358  if constexpr (!useAncestor<BasisType1>() && useAncestor<BasisType2>()) {
359  return transformGM(basis2, 'C', GramMatrix(T, basis1, basis2.ancestor(), mono_int_map) );
360  } else if constexpr (useAncestor<BasisType1>() && !useAncestor<BasisType2>()) {
361  return transformGM(basis1, 'R', GramMatrix(T, basis1.ancestor(), basis2, mono_int_map) );
362  } else {
363  return transformGM(basis1, 'R', transformGM(basis2, 'C', GramMatrix(T, basis1.ancestor(), basis2.ancestor(), mono_int_map) ) );
364  }
365 
366  }
367 
368 //
369 /* Gram matrix of scalar basis with one or two derivatives */
370 
372 Eigen::MatrixXd GMScalarDerivative(
373  const Cell & T,
374  const MonomialScalarBasisCell & basis1,
375  const MonomialScalarBasisCell & basis2,
376  const size_t m,
377  MonomialCellIntegralsType mono_int_map = {}
378  );
379 
381 Eigen::MatrixXd GMScalarDerivative(
382  const Cell & T,
383  const MonomialScalarBasisCell & basis1,
384  const MonomialScalarBasisCell & basis2,
385  const size_t m,
386  const size_t l,
387  MonomialCellIntegralsType mono_int_map = {}
388  );
389 
391 template<typename BasisType1, typename BasisType2>
392 Eigen::MatrixXd GMScalarDerivative(
393  const Cell& T,
394  const BasisType1 & basis1,
395  const BasisType2 & basis2,
396  const size_t m,
397  MonomialCellIntegralsType mono_int_map = {}
398  )
399  {
400  // If no ancestor is to be used, we shouldn't be in this overload
401  static_assert(BasisType1::hasAncestor || BasisType2::hasAncestor, "No method to compute this Gram matrix of derivatives");
402 
403  if constexpr (!BasisType1::hasAncestor && BasisType2::hasAncestor) {
404  return transformGM(basis2, 'C', GMScalarDerivative(T, basis1, basis2.ancestor(), m, mono_int_map) );
405  } else if constexpr (BasisType1::hasAncestor && !BasisType2::hasAncestor) {
406  return transformGM(basis1, 'R', GMScalarDerivative(T, basis1.ancestor(), basis2, m, mono_int_map) );
407  } else {
408  return transformGM(basis1, 'R', transformGM(basis2, 'C', GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), m, mono_int_map) ) );
409  }
410  }
411 
413 template<typename BasisType1, typename BasisType2>
414 Eigen::MatrixXd GMScalarDerivative(
415  const Cell& T,
416  const BasisType1 & basis1,
417  const BasisType2 & basis2,
418  const size_t m,
419  const size_t l,
420  MonomialCellIntegralsType mono_int_map = {}
421  )
422  {
423  // If no ancestor is to be used, we shouldn't be in this overload
424  static_assert(BasisType1::hasAncestor || BasisType2::hasAncestor, "No method to compute this Gram matrix of derivatives");
425 
426  if constexpr (!BasisType1::hasAncestor && BasisType2::hasAncestor) {
427  return transformGM(basis2, 'C', GMScalarDerivative(T, basis1, basis2.ancestor(), m, l, mono_int_map) );
428  } else if constexpr (BasisType1::hasAncestor && !BasisType2::hasAncestor) {
429  return transformGM(basis1, 'R', GMScalarDerivative(T, basis1.ancestor(), basis2, m, l, mono_int_map) );
430  } else {
431  return transformGM(basis1, 'R', transformGM(basis2, 'C', GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), m, l, mono_int_map) ) );
432  }
433 
434  }
435 
436 //
437 /* Gram matrices of vector-valued basis with gradient, curl... */
438 
440 template<typename BasisType1, typename BasisType2, size_t N>
441 Eigen::MatrixXd GramMatrix(
442  const Cell& T,
443  const GradientBasis<BasisType1> & grad_basis,
444  const TensorizedVectorFamily<BasisType2, N> & tens_family,
445  MonomialCellIntegralsType mono_int_map = {}
446  )
447  {
448  size_t dim1 = grad_basis.dimension();
449  size_t dim2 = tens_family.dimension();
450  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1, dim2);
451 
452  // Integrals of monomials
453  size_t totaldegree = grad_basis.ancestor().max_degree()+tens_family.max_degree()-1;
454  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
455 
456  for (size_t m=0; m<N; m++){
457  gm.block(0, m*dim2/N, dim1, dim2/N) = GMScalarDerivative(T, grad_basis.ancestor(), tens_family.ancestor(), m, intmap);
458  }
459  return gm/T.diam();
460  }
461 
462 
464 template<typename BasisType1, typename BasisType2, size_t N>
465 Eigen::MatrixXd GramMatrix(
466  const Cell& T,
467  const TensorizedVectorFamily<BasisType1, N> & tens_family,
468  const GradientBasis<BasisType2> & grad_basis,
469  MonomialCellIntegralsType mono_int_map = {}
470  )
471  {
472  return GramMatrix(T, grad_basis, tens_family, mono_int_map).transpose();
473  }
474 
475 
477 template<typename BasisType1, typename BasisType2>
478 Eigen::MatrixXd GramMatrix(
479  const Cell& T,
480  const GradientBasis<BasisType1> & grad_basis1,
481  const GradientBasis<BasisType2> & grad_basis2,
482  MonomialCellIntegralsType mono_int_map = {}
483  )
484  {
485  size_t dim1 = grad_basis1.dimension();
486  size_t dim2 = grad_basis2.dimension();
487  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1, dim2);
488 
489  // Integrals of monomials
490  size_t totaldegree = grad_basis1.ancestor().max_degree()+grad_basis2.ancestor().max_degree()-2;
491  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
492 
493  for (size_t m=0; m<3; m++){
494  gm += GMScalarDerivative(T, grad_basis1.ancestor(), grad_basis2.ancestor(), m, m, intmap);
495  }
496  return gm/std::pow(T.diam(), 2);
497  }
498 
500 template<typename BasisType1, typename BasisType2>
501 Eigen::MatrixXd GramMatrix(const Cell& T,
502  const CurlBasis<BasisType1> & basis1,
503  const CurlBasis<BasisType2> & basis2,
504  MonomialCellIntegralsType mono_int_map = {}
505  )
506  {
507  return GramMatrixCurlCurl(T, basis1.ancestor(), basis2.ancestor(), mono_int_map);
508  }
509 
511 template<typename BasisType1, typename BasisType2>
512 typename boost::disable_if<boost::is_same<BasisType2, MonomialCellIntegralsType>, Eigen::MatrixXd>::type GramMatrix(
513  const Cell& T,
514  const CurlBasis<BasisType1> & basis1,
515  const BasisType2 & basis2,
516  MonomialCellIntegralsType mono_int_map = {}
517  )
518  {
519  return GramMatrixCurl(T, basis1.ancestor(), basis2, mono_int_map);
520  }
521 
523 template<typename BasisType1, typename Basis2>
524 Eigen::MatrixXd GramMatrix(
525  const Cell & T,
526  const BasisType1 & basis1,
527  const CurlBasis<Basis2> & basis2,
528  MonomialCellIntegralsType mono_int_map = {}
529  )
530  {
531  return GramMatrixCurl(T, basis2.ancestor(), basis1, mono_int_map).transpose();
532  }
533 
535 template<typename BasisType1, typename BasisType2, size_t N>
536 Eigen::MatrixXd GramMatrixCurlCurl(
537  const Cell& T,
540  MonomialCellIntegralsType mono_int_map = {}
541  )
542  {
543  size_t dim1 = basis1.dimension();
544  size_t dim2 = basis2.dimension();
545  Eigen::MatrixXd gm(dim1, dim2);
546 
547  // Integrals of monomials
548  size_t totaldegree = basis1.max_degree()+basis2.max_degree()-2;
549  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
550 
551  Eigen::MatrixXd GMxx = GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 0, 0, intmap);
552  Eigen::MatrixXd GMyy = GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 1, 1, intmap);
553  Eigen::MatrixXd GMzz = GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 2, 2, intmap);
554 
555  gm.block(0, 0, dim1/N, dim2/N) = GMzz + GMyy;
556  gm.block(0, dim2/N, dim1/N, dim2/N) = -GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 1, 0, intmap);
557  gm.block(0, 2*dim2/N, dim1/N, dim2/N) = -GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 2, 0, intmap);
558  gm.block(dim1/N, 0, dim1/N, dim2/N) = -GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 0, 1, intmap);
559  gm.block(dim1/N, dim2/N, dim1/N, dim2/N) = GMzz + GMxx;
560  gm.block(dim1/N, 2*dim2/N, dim1/N, dim2/N) = -GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 2, 1, intmap);
561  gm.block(2*dim1/N, 0, dim1/N, dim2/N) = -GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 0, 2, intmap);
562  gm.block(2*dim1/N, dim2/N, dim1/N, dim2/N) = -GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 1, 2, intmap);
563  gm.block(2*dim1/N, 2*dim2/N, dim1/N, dim2/N) = GMyy + GMxx;
564 
565  return gm/std::pow(T.diam(), 2);
566  }
567 
569 Eigen::MatrixXd GramMatrixCurlCurl(
570  const Cell& T,
571  const GolyComplBasisCell & basis1,
572  const GolyComplBasisCell & basis2,
573  MonomialCellIntegralsType mono_int_map = {}
574  );
575 
577 template<typename BasisType2, size_t N>
578 Eigen::MatrixXd GramMatrixCurlCurl(
579  const Cell& T,
580  const GolyComplBasisCell & basis1,
582  MonomialCellIntegralsType mono_int_map = {}
583  )
584  {
585  size_t dim1 = basis1.dimension();
586  size_t dim2 = basis2.dimension();
587  Eigen::MatrixXd gm(dim1, dim2);
588 
589  // Integrals of monomials
590  size_t totaldegree = basis1.max_degree()+basis2.max_degree();
591  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
592 
593  size_t dim_l1 = basis1.dimPkmo();
594  gm.block(0, 0, dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 1, 0, 2) - GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 2, 0, 1);
595  gm.block(0, dim2/N, dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 2, 0, 0) + GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 1, 1, 2)
596  + GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 2, 2, 2) + 2/T.diam()*GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 3, 3, 2);
597  gm.block(0, 2*dim2/N, dim_l1, dim2/N) = -GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 1, 0, 0) - GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 1, 1, 1)
598  -GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 2, 2, 1) - 2/T.diam()*GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 3, 3, 1);
599  gm.block(dim_l1, 0, dim_l1, dim2/N) = -GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 2, 1, 1) - GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 0, 0, 2)
600  -GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 2, 2, 2) - 2/T.diam()*GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 3, 3, 2);
601  gm.block(dim_l1, dim2/N, dim_l1, dim2/N) = -GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 0, 1, 2) + GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 2, 1, 0);
602  gm.block(dim_l1, 2*dim2/N, dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 0, 1, 1) + GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 0, 0, 0)
603  +GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 2, 2, 0) + 2/T.diam()*GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 3, 3, 0);
604  gm.block(2*dim_l1, 0, dim1-2*dim_l1, dim2/N) = -GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 1, 2, 2) + GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 0, 0, 1)
605  +GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 1, 1, 1) + 2/T.diam()*GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 3, 3, 1);
606  gm.block(2*dim_l1, dim2/N, dim1-2*dim_l1, dim2/N) = -GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 0, 2, 2) - GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 0, 0, 0)
607  -GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 1, 1, 0) - 2/T.diam()*GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 3, 3, 0);
608  gm.block(2*dim_l1, 2*dim2/N, dim1-2*dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 0, 2, 1) - GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 1, 2, 0);
609 
610  return gm;
611  }
612 
614 template<typename BasisType1, size_t N>
615 Eigen::MatrixXd GramMatrixCurlCurl(
616  const Cell& T,
618  const GolyComplBasisCell & basis2,
619  MonomialCellIntegralsType mono_int_map = {}
620  )
621  {
622  return GramMatrixCurlCurl(T, basis2, basis1, mono_int_map).transpose();
623  }
624 
626 template<typename BasisType1, typename BasisType2>
627 Eigen::MatrixXd GramMatrixCurlCurl(
628  const Cell& T,
629  const BasisType1 & basis1,
630  const BasisType2 & basis2,
631  MonomialCellIntegralsType mono_int_map = {}
632  )
633  {
634  // If no ancestor is to be used, we shouldn't be in this overload
635  static_assert(useAncestor<BasisType1>() || useAncestor<BasisType2>(), "No method to compute this Gram matrix");
636 
637  if constexpr (!useAncestor<BasisType1>() && useAncestor<BasisType2>()) {
638  return transformGM(basis2, 'C', GramMatrixCurlCurl(T, basis1, basis2.ancestor(), mono_int_map) );
639  } else if constexpr (useAncestor<BasisType1>() && !useAncestor<BasisType2>()) {
640  return transformGM(basis1, 'R', GramMatrixCurlCurl(T, basis1.ancestor(), basis2, mono_int_map) );
641  } else {
642  return transformGM(basis1, 'R', transformGM(basis2, 'C', GramMatrixCurlCurl(T, basis1.ancestor(), basis2.ancestor(), mono_int_map) ) );
643  }
644  }
645 
647 template<typename BasisType1, typename BasisType2, size_t N>
648 Eigen::MatrixXd GramMatrixCurl(
649  const Cell & T,
652  MonomialCellIntegralsType mono_int_map = {}
653  )
654  {
655  size_t dim1 = basis1.dimension();
656  size_t dim2 = basis2.dimension();
657  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1, dim2);
658 
659  // Integrals of monomials
660  size_t totaldegree = basis1.max_degree()+basis2.max_degree()-1;
661  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
662 
663  Eigen::MatrixXd GMx = GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 0, intmap);
664  Eigen::MatrixXd GMy = GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 1, intmap);
665  Eigen::MatrixXd GMz = GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), 2, intmap);
666 
667  gm.block(0, dim2/N, dim1/N, dim2/N) = GMz;
668  gm.block(0, 2*dim2/N, dim1/N, dim2/N) = -GMy;
669  gm.block(dim1/N, 0, dim1/N, dim2/N) = -GMz;
670  gm.block(dim1/N, 2*dim2/N, dim1/N, dim2/N) = GMx;
671  gm.block(2*dim1/N, 0, dim1/N, dim2/N) = GMy;
672  gm.block(2*dim1/N, dim2/N, dim1/N, dim2/N) = -GMx;
673 
674  return gm/T.diam();
675  }
676 
678 template<typename BasisType2, size_t N>
679 Eigen::MatrixXd GramMatrixCurl(
680  const Cell & T,
681  const GolyComplBasisCell & basis1,
683  MonomialCellIntegralsType mono_int_map = {}
684  )
685  {
686  size_t dim1 = basis1.dimension();
687  size_t dim2 = basis2.dimension();
688  Eigen::MatrixXd gm(dim1, dim2);
689 
690  // Integrals of monomials
691  size_t totaldegree = basis1.max_degree()+basis2.max_degree();
692  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
693 
694  size_t dim_l1 = basis1.dimPkmo();
695  gm.block(0, 0, dim_l1, dim2/N) = -GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 1, 1)
696  -GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 2, 2)
697  -2*GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap)/T.diam();
698  gm.block(0, dim2/N, dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 1, 0);
699  gm.block(0, 2*dim2/N, dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 0, intmap, 2, 0);
700  gm.block(dim_l1, 0, dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 0, 1);
701  gm.block(dim_l1, dim2/N, dim_l1, dim2/N) = -GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 0, 0)
702  -GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 2, 2)
703  -2*GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap)/T.diam();
704  gm.block(dim_l1, 2*dim2/N, dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 1, intmap, 2, 1);
705  gm.block(2*dim_l1, 0, dim1-2*dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 0, 2);
706  gm.block(2*dim_l1, dim2/N, dim1-2*dim_l1, dim2/N) = GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 1, 2);
707  gm.block(2*dim_l1, 2*dim2/N, dim1-2*dim_l1, dim2/N) = -GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 0, 0)
708  -GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap, 1, 1)
709  -2*GMGolyComplScalar(T, basis1, basis2.ancestor(), 2, intmap)/T.diam();
710 
711  return gm;
712  }
713 
715 template<typename BasisType1, typename BasisType2>
716 Eigen::MatrixXd GramMatrixCurl(
717  const Cell& T,
718  const BasisType1 & basis1,
719  const BasisType2 & basis2,
720  MonomialCellIntegralsType mono_int_map = {}
721  )
722  {
723  // If no ancestor is to be used, we shouldn't be in this overload
724  static_assert(useAncestor<BasisType1>() || useAncestor<BasisType2>(), "No method to compute this Gram matrix");
725 
726  if constexpr (!useAncestor<BasisType1>() && useAncestor<BasisType2>()) {
727  return transformGM(basis2, 'C', GramMatrixCurl(T, basis1, basis2.ancestor(), mono_int_map) );
728  } else if constexpr (useAncestor<BasisType1>() && !useAncestor<BasisType2>()) {
729  return transformGM(basis1, 'R', GramMatrixCurl(T, basis1.ancestor(), basis2, mono_int_map) );
730  } else {
731  return transformGM(basis1, 'R', transformGM(basis2, 'C', GramMatrixCurl(T, basis1.ancestor(), basis2.ancestor(), mono_int_map) ) );
732  }
733  }
734 
736 template<typename BasisType1, typename BasisType2>
737 Eigen::MatrixXd GramMatrixCurl(
738  const Cell& T,
739  const BasisType1 & basis1,
740  const CurlBasis<BasisType2> & basis2,
741  MonomialCellIntegralsType mono_int_map = {}
742  )
743  {
744  if constexpr (!useAncestor<BasisType1>()) {
745  return GramMatrixCurlCurl(T, basis1, basis2.ancestor(), mono_int_map);
746  } else {
747  return transformGM(basis1, 'R', GramMatrixCurlCurl(T, basis1.ancestor(), basis2.ancestor(), mono_int_map) );
748  }
749  }
750 
752 template<typename BasisType1, typename BasisType2>
753 Eigen::MatrixXd GramMatrix(const Cell& T,
754  const DivergenceBasis<BasisType1> & basis1,
755  const DivergenceBasis<BasisType2> & basis2,
756  MonomialCellIntegralsType mono_int_map = {}
757  )
758  {
759  return GramMatrixDivDiv(T, basis1.ancestor(), basis2.ancestor(), mono_int_map);
760  }
761 
763 Eigen::MatrixXd GMRolyComplScalarDiv(
764  const Cell & T,
765  const MonomialScalarBasisCell & mono_basis,
766  const RolyComplBasisCell & rolycompl_basis,
767  const size_t k,
768  MonomialCellIntegralsType mono_int_map
769  );
770 
772 template<typename BasisType>
773 Eigen::MatrixXd GMRolyComplScalarDiv(
774  const Cell& T,
775  const BasisType & basis1,
776  const RolyComplBasisCell & basis2,
777  const size_t k,
778  MonomialCellIntegralsType mono_int_map
779  )
780  {
781  // If no ancestor is to be used, we shouldn't be in this overload
782  static_assert(BasisType::hasAncestor, "No method to compute this Gram matrix of derivatives");
783  return transformGM(basis1, 'R', GMRolyComplScalarDiv(T, basis1.ancestor(), basis2, k, mono_int_map) );
784  }
785 
787 template<typename BasisType1, typename BasisType2, size_t N>
788 Eigen::MatrixXd GramMatrixDivDiv(
789  const Cell& T,
792  MonomialCellIntegralsType mono_int_map = {}
793  )
794  {
795  size_t dim1 = basis1.dimension();
796  size_t dim2 = basis2.dimension();
797  Eigen::MatrixXd gm(dim1, dim2);
798 
799  // Integrals of monomials
800  size_t totaldegree = basis1.max_degree()+basis2.max_degree()-2;
801  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
802 
803  for (size_t i = 0; i < N; i++) {
804  for (size_t j = 0; j < N; j++) {
805  gm.block(i*dim1/N, j*dim2/N, dim1/N, dim2/N) = GMScalarDerivative(T, basis1.ancestor(), basis2.ancestor(), i, j, intmap);
806  }
807  }
808 
809  return gm/std::pow(T.diam(), 2);
810  }
811 
813 Eigen::MatrixXd GramMatrixDivDiv(
814  const Cell& T,
815  const RolyComplBasisCell & basis1,
816  const RolyComplBasisCell & basis2,
817  MonomialCellIntegralsType mono_int_map = {}
818  );
819 
821 template<typename BasisType2, size_t N>
822 Eigen::MatrixXd GramMatrixDivDiv(
823  const Cell& T,
824  const RolyComplBasisCell & basis1,
826  MonomialCellIntegralsType mono_int_map = {}
827  )
828  {
829  return GramMatrixDivDiv(T, basis2, basis1, mono_int_map).transpose();
830  }
831 
833 template<typename BasisType1, size_t N>
834 Eigen::MatrixXd GramMatrixDivDiv(
835  const Cell& T,
837  const RolyComplBasisCell & basis2,
838  MonomialCellIntegralsType mono_int_map = {}
839  )
840  {
841  size_t dim1 = basis1.dimension();
842  size_t dim2 = basis2.dimension();
843  Eigen::MatrixXd gm(dim1, dim2);
844 
845  // Integrals of monomials
846  size_t totaldegree = basis1.max_degree()+basis2.max_degree();
847  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
848 
849  for (size_t i = 0; i < N; i++) {
850  gm.block(i*dim1/N, 0, dim1/N, dim2) = GMRolyComplScalarDiv(T, basis1.ancestor(), basis2, i, mono_int_map);
851  }
852 
853  return gm;
854  }
855 
857 template<typename BasisType1, typename BasisType2>
858 Eigen::MatrixXd GramMatrixDivDiv(
859  const Cell& T,
860  const BasisType1 & basis1,
861  const BasisType2 & basis2,
862  MonomialCellIntegralsType mono_int_map = {}
863  )
864  {
865  // If no ancestor is to be used, we shouldn't be in this overload
866  static_assert(useAncestor<BasisType1>() || useAncestor<BasisType2>(), "No method to compute this Gram matrix");
867 
868  if constexpr (!useAncestor<BasisType1>() && useAncestor<BasisType2>()) {
869  return transformGM(basis2, 'C', GramMatrixDivDiv(T, basis1, basis2.ancestor(), mono_int_map) );
870  } else if constexpr (useAncestor<BasisType1>() && !useAncestor<BasisType2>()) {
871  return transformGM(basis1, 'R', GramMatrixDivDiv(T, basis1.ancestor(), basis2, mono_int_map) );
872  } else {
873  return transformGM(basis1, 'R', transformGM(basis2, 'C', GramMatrixDivDiv(T, basis1.ancestor(), basis2.ancestor(), mono_int_map) ) );
874  }
875  }
876 
878 template<typename BasisType1, typename BasisType2>
879 typename boost::disable_if<boost::is_same<BasisType2, MonomialCellIntegralsType>, Eigen::MatrixXd>::type GramMatrix(
880  const Cell& T,
881  const DivergenceBasis<BasisType1> & basis1,
882  const BasisType2 & basis2,
883  MonomialCellIntegralsType mono_int_map = {}
884  )
885  {
886  return GramMatrixDiv(T, basis1.ancestor(), basis2, mono_int_map);
887  }
888 
890 template<typename BasisType1, typename Basis2>
891 Eigen::MatrixXd GramMatrix(
892  const Cell & T,
893  const BasisType1 & basis1,
894  const DivergenceBasis<Basis2> & basis2,
895  MonomialCellIntegralsType mono_int_map = {}
896  )
897  {
898  return GramMatrixDiv(T, basis2.ancestor(), basis1, mono_int_map).transpose();
899  }
900 
902 template<typename BasisType1, size_t N>
903 Eigen::MatrixXd GramMatrixDiv(
904  const Cell & T,
906  const MonomialScalarBasisCell & basis2,
907  MonomialCellIntegralsType mono_int_map = {}
908  )
909  {
910  size_t dim1 = basis1.dimension();
911  size_t dim2 = basis2.dimension();
912  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1, dim2);
913 
914  // Integrals of monomials
915  size_t totaldegree = basis1.max_degree()+basis2.max_degree()-1;
916  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
917 
918  for (size_t i = 0; i < N; i++) {
919  gm.block(i*dim1/N, 0, dim1/N, dim2) = GMScalarDerivative(T, basis1.ancestor(), basis2, i, intmap);
920  }
921 
922  return gm/T.diam();
923  }
924 
926 Eigen::MatrixXd GramMatrixDiv(
927  const Cell & T,
928  const RolyComplBasisCell & basis1,
929  const MonomialScalarBasisCell & basis2,
930  MonomialCellIntegralsType mono_int_map = {}
931  );
932 
934 template<typename BasisType1, typename BasisType2>
935 Eigen::MatrixXd GramMatrixDiv(
936  const Cell& T,
937  const BasisType1 & basis1,
938  const BasisType2 & basis2,
939  MonomialCellIntegralsType mono_int_map = {}
940  )
941  {
942  // If no ancestor is to be used, we shouldn't be in this overload
943  static_assert(useAncestor<BasisType1>() || useAncestor<BasisType2>(), "No method to compute this Gram matrix");
944 
945  if constexpr (!useAncestor<BasisType1>() && useAncestor<BasisType2>()) {
946  return transformGM(basis2, 'C', GramMatrixDiv(T, basis1, basis2.ancestor(), mono_int_map) );
947  } else if constexpr (useAncestor<BasisType1>() && !useAncestor<BasisType2>()) {
948  return transformGM(basis1, 'R', GramMatrixDiv(T, basis1.ancestor(), basis2, mono_int_map) );
949  } else {
950  return transformGM(basis1, 'R', transformGM(basis2, 'C', GramMatrixDiv(T, basis1.ancestor(), basis2.ancestor(), mono_int_map) ) );
951  }
952  }
953 
955 template<typename BasisType1, typename BasisType2>
956 Eigen::MatrixXd GramMatrixDiv(
957  const Cell& T,
958  const BasisType1 & basis1,
959  const DivergenceBasis<BasisType2> & basis2,
960  MonomialCellIntegralsType mono_int_map = {}
961  )
962  {
963  if constexpr (!useAncestor<BasisType1>()) {
964  return GramMatrixDivDiv(T, basis1, basis2.ancestor(), mono_int_map);
965  } else {
966  return transformGM(basis1, 'R', GramMatrixDivDiv(T, basis1.ancestor(), basis2.ancestor(), mono_int_map) );
967  }
968  }
969 
970 /*------------- Templates for MatrixFamily (including Divergence thereof, and vs Gradient<Tensorized> --------------------*/
971 
973 template<typename BasisType1, typename BasisType2, size_t N>
974 Eigen::MatrixXd GramMatrix(
975  const Cell& T,
976  const MatrixFamily<BasisType1, N> & basis1,
977  const MatrixFamily<BasisType2, N> & basis2,
978  MonomialCellIntegralsType mono_int_map = {}
979  )
980  {
981  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(basis1.dimension(), basis2.dimension());
982 
983  Eigen::MatrixXd anc_gm = GramMatrix(T, basis1.ancestor(), basis2.ancestor(), mono_int_map);
984  size_t dim1 = anc_gm.rows();
985  size_t dim2 = anc_gm.cols();
986 
987  for (size_t i=0; i<N*N; i++){
988  gm.block(i*dim1, i*dim2, dim1, dim2) = anc_gm;
989  }
990  return gm;
991  }
992 
994 template<typename BasisType1, typename BasisType2>
995 Eigen::MatrixXd GramMatrix(
996  const Cell& T,
999  MonomialCellIntegralsType mono_int_map = {}
1000  )
1001  {
1002  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(basis1.dimension(), basis2.dimension());
1003 
1004  // Grab the scalar bases underlying basis1 and basis2
1005  BasisType1 scalar_basis1 = basis1.ancestor().ancestor();
1006  BasisType2 scalar_basis2 = basis2.ancestor();
1007  size_t dim1 = scalar_basis1.dimension();
1008  size_t dim2 = scalar_basis2.dimension();
1009 
1010  // Integrals of monomials
1011  size_t totaldegree = scalar_basis1.max_degree() + scalar_basis2.max_degree();
1012  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
1013 
1014  for (size_t j=0; j < dimspace; j++){
1015  Eigen::MatrixXd gm_anc = GMScalarDerivative(T, scalar_basis1, scalar_basis2, j, intmap);
1016  for (size_t i=0; i < dimspace; i++){
1017  gm.block(j*dimspace*dim1 + i*dim1, i*dim2, dim1, dim2) = gm_anc;
1018  }
1019  }
1020 
1021  return gm/T.diam();
1022  }
1023 
1024 
1026 template<typename BasisType1, typename BasisType2>
1027 Eigen::MatrixXd GramMatrix(
1028  const Cell& T,
1031  MonomialCellIntegralsType mono_int_map = {}
1032  )
1033  {
1034  return GramMatrix(T, basis2, basis1, mono_int_map).transpose();
1035  }
1036 
1037 
1039 template<typename BasisType1, typename BasisType2>
1040 Eigen::MatrixXd GramMatrix(
1041  const Cell& T,
1043  const MatrixFamily<BasisType2, dimspace> & basis2,
1044  MonomialCellIntegralsType mono_int_map = {}
1045  )
1046  {
1047  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(basis1.dimension(), basis2.dimension());
1048 
1049  // Grab the scalar bases underlying basis1 and basis2
1050  BasisType1 scalar_basis1 = basis1.ancestor().ancestor();
1051  BasisType2 scalar_basis2 = basis2.ancestor();
1052  size_t dim1 = scalar_basis1.dimension();
1053  size_t dim2 = scalar_basis2.dimension();
1054 
1055  // Integrals of monomials
1056  size_t totaldegree = scalar_basis1.max_degree() + scalar_basis2.max_degree();
1057  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
1058 
1059  for (size_t j=0; j < dimspace; j++){
1060  Eigen::MatrixXd gm_anc = GMScalarDerivative(T, scalar_basis1, scalar_basis2, j, intmap);
1061  for (size_t i=0; i < dimspace; i++){
1062  gm.block(i*dim1, j*dimspace*dim2 + i*dim2, dim1, dim2) = gm_anc;
1063  }
1064  }
1065 
1066  return gm/T.diam();
1067  }
1068 
1070 template<typename BasisType1, typename BasisType2>
1071 Eigen::MatrixXd GramMatrix(
1072  const Cell& T,
1073  const MatrixFamily<BasisType1, dimspace> & basis1,
1075  MonomialCellIntegralsType mono_int_map = {}
1076  )
1077  {
1078  return GramMatrix(T, basis2, basis1, mono_int_map).transpose();
1079  }
1080 
1082 template<typename BasisType1, typename BasisType2, size_t N>
1083 Eigen::MatrixXd GramMatrix(
1084  const Cell& T,
1087  MonomialCellIntegralsType mono_int_map = {}
1088  )
1089  {
1090  Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(basis1.dimension(), basis2.dimension());
1091 
1092  // Grab the scalar bases underlying basis1 and basis2
1093  BasisType1 scalar_basis1 = basis1.ancestor().ancestor();
1094  BasisType2 scalar_basis2 = basis2.ancestor().ancestor();
1095  size_t dim1 = scalar_basis1.dimension();
1096  size_t dim2 = scalar_basis2.dimension();
1097 
1098  // Integrals of monomials
1099  size_t totaldegree = scalar_basis1.max_degree() + scalar_basis2.max_degree();
1100  MonomialCellIntegralsType intmap = CheckIntegralsDegree(T, totaldegree, mono_int_map);
1101 
1102  // Gram matrices of sum_i \partial_i phi \partial_i psi for the two scalar bases phi, psi
1103  Eigen::MatrixXd gm_anc = Eigen::MatrixXd::Zero(dim1, dim2);
1104  for (size_t k=0; k < dimspace; k++){
1105  gm_anc += GMScalarDerivative(T, scalar_basis1, scalar_basis2, k, k, intmap);
1106  }
1107 
1108  for (size_t i=0; i < N; i++){
1109  gm.block(i*dim1, i*dim2, dim1, dim2) = gm_anc;
1110  }
1111 
1112  return gm/(std::pow(T.diam(),2));
1113  }
1114 
1116 } // end of namespace HArDCore3D
1117 
1118 #endif // end of _GMPOLY_CELL_HPP
Basis for the space of curls of polynomials.
Definition: basis.hpp:1290
Basis (or rather family) of divergence of an existing basis.
Definition: basis.hpp:1353
Family of functions expressed as linear combination of the functions of a given basis.
Definition: basis.hpp:388
Basis for the complement G^{c,k}(T) in P^k(T)^3 of the range of grad.
Definition: basis.hpp:1503
Basis for the space of gradients of polynomials.
Definition: basis.hpp:1228
Matrix family obtained from a scalar family.
Definition: basis.hpp:776
Scalar monomial basis on a cell.
Definition: basis.hpp:154
Generate a basis restricted to the first "dimension" functions.
Definition: basis.hpp:1119
Basis for the complement R^{c,k}(T) in P^k(T)^3 of the range of curl.
Definition: basis.hpp:1432
Generate a basis where the function indices are shifted.
Definition: basis.hpp:1012
Vector family obtained by tensorization of a scalar family.
Definition: basis.hpp:609
size_t dimension() const
Return the dimension of the basis.
Definition: basis.hpp:1045
const ScalarFamilyType & ancestor() const
Return the ancestor (family that has been tensorized)
Definition: basis.hpp:863
size_t dimPkmo() const
Returns the dimension of P^{k-1}(R^3)
Definition: basis.hpp:1553
size_t dimension() const
Return the dimension of the family.
Definition: basis.hpp:640
constexpr int dimspace
Dimension, and generic types for vector in correct dimension (makes it easier to translate a code bet...
Definition: basis.hpp:50
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:1470
constexpr const ScalarFamilyType & ancestor() const
Return the ancestor (family that has been tensorized)
Definition: basis.hpp:747
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition: basis.hpp:1335
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:1529
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition: basis.hpp:1398
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:753
constexpr const BasisType & ancestor() const
Return the ancestor (basis that the gradient was taken of)
Definition: basis.hpp:1273
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:1458
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:195
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:180
size_t dimension() const
Compute the dimension of the basis.
Definition: basis.hpp:1261
size_t max_degree() const
Returns the maximum degree of the basis functions.
Definition: basis.hpp:1541
const Eigen::MatrixXd & matrix() const
Return the coefficient matrix.
Definition: basis.hpp:558
size_t dimension() const
Return the dimension of the basis.
Definition: basis.hpp:1154
size_t dimension() const
Return the dimension of the family.
Definition: basis.hpp:823
Eigen::MatrixXd GramMatrix(const Cell &T, const MonomialScalarBasisCell &basis1, const MonomialScalarBasisCell &basis2, MonomialCellIntegralsType mono_int_map={})
Computes the Gram Matrix of a pair of local scalar monomial bases.
Definition: GMpoly_cell.cpp:170
Eigen::MatrixXd GramMatrixDiv(const Cell &T, const TensorizedVectorFamily< BasisType1, N > &basis1, const MonomialScalarBasisCell &basis2, MonomialCellIntegralsType mono_int_map={})
Template to compute the Gram Matrix of a Divergence<Tensorized> basis and a monomial scalar basis.
Definition: GMpoly_cell.hpp:903
Eigen::MatrixXd GramMatrixCurlCurl(const Cell &T, const TensorizedVectorFamily< BasisType1, N > &basis1, const TensorizedVectorFamily< BasisType2, N > &basis2, MonomialCellIntegralsType mono_int_map={})
Template to compute the Gram Matrix of the curl of a tensorized basis and the curl of another tensori...
Definition: GMpoly_cell.hpp:536
Eigen::MatrixXd GramMatrixDivDiv(const Cell &T, const TensorizedVectorFamily< BasisType1, N > &basis1, const TensorizedVectorFamily< BasisType2, N > &basis2, MonomialCellIntegralsType mono_int_map={})
Template to compute the Gram Matrix of the divergence of a tensorized basis and the divergence of ano...
Definition: GMpoly_cell.hpp:788
Eigen::MatrixXd GMScalarDerivative(const Cell &T, const MonomialScalarBasisCell &basis1, const MonomialScalarBasisCell &basis2, const size_t m, MonomialCellIntegralsType mono_int_map={})
Computes the Gram Matrix of a pair of local scalar monomial bases, taking a partial derivative of the...
Definition: GMpoly_cell.cpp:244
MonomialCellIntegralsType IntegrateCellMonomials(const Cell &T, const int maxdeg)
Compute all the integrals of a cell's monomials on the cell.
Definition: GMpoly_cell.cpp:117
Eigen::MatrixXd GMGolyComplScalar(const Cell &T, const GolyComplBasisCell &golycompl_basis, const MonomialScalarBasisCell &mono_basis, const size_t s, MonomialCellIntegralsType mono_int_map, const size_t m=3, const size_t k1=3, const size_t k2=3)
Computes the Gram Matrix of the sth section of a GolyCompl Basis and a monomial basis.
Definition: GMpoly_cell.cpp:321
Eigen::MatrixXd GMRolyComplScalarDiv(const Cell &T, const MonomialScalarBasisCell &mono_basis, const RolyComplBasisCell &rolycompl_basis, const size_t k, MonomialCellIntegralsType mono_int_map)
Gram Matrix of the divergence of a RolyCompl Basis and the kth derivative of a monomial basis.
Definition: GMpoly_cell.cpp:506
MonomialCellIntegralsType CheckIntegralsDegree(const Cell &T, const size_t degree, const MonomialCellIntegralsType &mono_int_map={})
Checks if the degree of an existing list of monomial integrals is sufficient, other re-compute and re...
Definition: GMpoly_cell.cpp:160
size_t operator()(const VectorZd &p) const
Definition: GMpoly_cell.hpp:41
std::vector< MonomialCellIntegralsType > IntegrateCellMonomials_onEdges(const Cell &T, const size_t maxdeg)
Compute all the integrals, on the edges of a cell, of this cell's monomials up to a max degree.
Definition: GMpoly_cell.cpp:7
Eigen::MatrixXd GramMatrixCurl(const Cell &T, const TensorizedVectorFamily< BasisType1, N > &basis1, const TensorizedVectorFamily< BasisType2, N > &basis2, MonomialCellIntegralsType mono_int_map={})
Template to compute the Gram Matrix of a Curl<Tensorized> basis and a tensorized scalar basis.
Definition: GMpoly_cell.hpp:648
Eigen::MatrixXd GMGolyCompl(const Cell &T, const GolyComplBasisCell &basis1, const GolyComplBasisCell &basis2, const size_t s1, const size_t s2, MonomialCellIntegralsType mono_int_map, const size_t m1=3, const size_t m2=3, const size_t k1=3, const size_t k2=3)
Computes the Gram Matrix of the (optionally k1th derivative of the) s1th section of GolyCompl (option...
Definition: GMpoly_cell.cpp:362
Eigen::MatrixXd GMRolyComplScalar(const Cell &T, const RolyComplBasisCell &rolycompl_basis, const MonomialScalarBasisCell &mono_basis, const size_t m, MonomialCellIntegralsType mono_int_map={})
Computes the Gram Matrix of the mth component of a RolyCompl Basis and a monomial basis.
Definition: GMpoly_cell.cpp:298
constexpr bool useAncestor()
Determines if the ancestor of a basis will be used to compute a Gram matrix for this basis.
Definition: GMpoly_cell.hpp:335
Eigen::MatrixXd transformGM(const Family< BasisType > &family_basis, const char RC, const Eigen::MatrixXd &anc_GM)
Transforms a Gram Matrix from an ancestor to a family basis.
Definition: GMpoly_cell.hpp:85
std::unordered_map< VectorZd, double, VecHash > MonomialCellIntegralsType
Type for list of integrals of monomials.
Definition: GMpoly_cell.hpp:49
std::vector< MonomialCellIntegralsType > IntegrateCellMonomials_onFaces(const Cell &T, const size_t maxdeg, std::vector< MonomialCellIntegralsType > &integrals_edges)
Compute all the integrals, on the faces of a cell, of this cell's monomials up to a max degree.
Definition: GMpoly_cell.cpp:61
Definition: ddr-magnetostatics.hpp:40
MeshND::VectorZd< 2 > VectorZd
Definition: Mesh2D.hpp:15
MeshND::Cell< 2 > Cell
Definition: Mesh2D.hpp:13
Hash function for VectorZd type.
Definition: GMpoly_cell.hpp:40