HArD::Core3D
Hybrid Arbitrary Degree::Core 3D - Library to implement 3D schemes with vertex, edge, face and cell polynomials as unknowns
Loading...
Searching...
No Matches
GMpoly_face.hpp
Go to the documentation of this file.
1# ifndef _GMPOLY_FACE_HPP
2# define _GMPOLY_FACE_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#include <GMpoly_cell.hpp>
25
26namespace HArDCore3D {
27
34//----------------------------------------------------------------------
35//----------------------------------------------------------------------
36// INTEGRALS OF MONOMIALS
37//----------------------------------------------------------------------
38//----------------------------------------------------------------------
39
42{
43 size_t operator()(const Eigen::Vector2i & p) const
44 {
45 constexpr size_t b = 100; // max degree must be less than the basis b
46 return p(0) + p(1) * b;
47 }
48};
49
51typedef std::unordered_map<Eigen::Vector2i, double, VecFaceHash> MonomialFaceIntegralsType;
52
54std::vector<MonomialFaceIntegralsType> IntegrateFaceMonomials_onEdges
55 (const Face & F,
56 const size_t maxdeg
57 );
58
61 (const Face & F,
62 const int maxdeg
63 );
64
67 (const Face & F,
68 const size_t degree,
70 );
71
72
73//----------------------------------------------------------------------
74//----------------------------------------------------------------------
75// FUNCTIONS TO COMPUTE GRAM MATRICES
76//----------------------------------------------------------------------
77//----------------------------------------------------------------------
78
79//
80/* BASIC ONES: Monomial, tensorized, and generic template */
81
83template<typename BasisType1, typename BasisType2>
84Eigen::MatrixXd GramMatrix(const Face& F,
85 const BasisType1 & basis1,
86 const BasisType2 & basis2,
88 )
89 {
90 // If no ancestor is to be used, we shouldn't be in this overload
91 static_assert(useAncestor<BasisType1>() || useAncestor<BasisType2>(), "No method to compute this Gram matrix");
92
94 return transformGM(basis2, 'C', GramMatrix(F, basis1, basis2.ancestor(), mono_int_map) );
95 } else if constexpr (useAncestor<BasisType1>() && !useAncestor<BasisType2>()) {
96 return transformGM(basis1, 'R', GramMatrix(F, basis1.ancestor(), basis2, mono_int_map) );
97 } else {
98 return transformGM(basis1, 'R', transformGM(basis2, 'C', GramMatrix(F, basis1.ancestor(), basis2.ancestor(), mono_int_map) ) );
99 }
100
101 }
102
104Eigen::MatrixXd GramMatrix(
105 const Face & F,
106 const MonomialScalarBasisFace & basis1,
107 const MonomialScalarBasisFace & basis2,
109 );
110
112template<typename BasisType>
113Eigen::MatrixXd GramMatrix(const Face& F, const BasisType & basis, MonomialFaceIntegralsType mono_int_map = {})
114 {
115 return GramMatrix(F, basis, basis, mono_int_map);
116 }
117
119template<typename BasisType1, typename BasisType2, size_t N>
120Eigen::MatrixXd GramMatrix(
121 const Face& F,
125 )
126 {
127 Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(basis1.dimension(), basis2.dimension());
128
129 Eigen::MatrixXd anc_gm = GramMatrix(F, basis1.ancestor(), basis2.ancestor(), mono_int_map);
130 size_t dim1 = anc_gm.rows();
131 size_t dim2 = anc_gm.cols();
132
133 for (size_t i=0; i<N; i++){
134 gm.block(i*dim1, i*dim2, dim1, dim2) = anc_gm;
135 }
136 return gm;
137 }
138
140template<typename BasisType1, typename BasisType2>
141Eigen::MatrixXd GramMatrix(
142 const Face & F,
146 )
147 {
148 Eigen::MatrixXd gm(basis1.dimension(), basis2.dimension());
149
150 Eigen::MatrixXd anc_gm = GramMatrix(F, basis1.ancestor(), basis2.ancestor(), mono_int_map);
151 size_t dim1 = anc_gm.rows();
152 size_t dim2 = anc_gm.cols();
153
154 Eigen::Matrix<double, 2, 3> generators1 = basis1.generators();
155 Eigen::Matrix<double, 2, 3> generators2 = basis2.generators();
156
157 for (size_t i=0; i<2; i++) {
158 for (size_t j=0; j<2; j++) {
159 gm.block(i*dim1, j*dim2, dim1, dim2) = generators1.row(i).dot(generators2.row(j)) * anc_gm;
160 }
161 }
162
163 return gm;
164 }
165
167Eigen::MatrixXd GramMatrix(
168 const Face & F,
169 const RolyComplBasisFace & basis1,
170 const RolyComplBasisFace & basis2,
172 );
173
175Eigen::MatrixXd GramMatrix(
176 const Face & F,
177 const GolyComplBasisFace & basis1,
178 const GolyComplBasisFace & basis2,
180 );
181
183template<typename BasisType>
184Eigen::MatrixXd GramMatrix(
185 const Face & F,
186 const RolyComplBasisFace & basis1,
189 )
190 {
191 size_t dim1 = basis1.dimension();
192 size_t dim2 = basis2.dimension()/2;
193 size_t totaldegree = basis1.max_degree()+basis2.max_degree();
194 Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1, 2*dim2);
195
196 // Obtain integration data from IntegrateFaceMonomials
198
199 std::vector<Eigen::MatrixXd> gmrs = {GMRolyComplScalar(F, basis1, basis2.ancestor(), 0, intmap), GMRolyComplScalar(F, basis1, basis2.ancestor(), 1, intmap)};
200 Eigen::Matrix<double, 2, 3> jacobian1 = basis1.jacobian();
201 Eigen::Matrix<double, 2, 3> generators2 = basis2.generators();
202 Eigen::Matrix2d W = jacobian1 * generators2.transpose();
203
204 for (size_t k=0; k<2; k++) {
205 for (size_t j=0; j<2; j++) {
206 gm.block(0, j*dim2, dim1, dim2) += W(k,j) * gmrs[k];
207 }
208 }
209
210 return F.diam() * gm;
211 }
212
214template<typename BasisType>
215Eigen::MatrixXd GramMatrix(
216 const Face & F,
218 const RolyComplBasisFace & basis2,
220 )
221 {
222 return GramMatrix(F, basis2, basis1, mono_int_map).transpose();
223 }
224
226Eigen::MatrixXd GMRolyComplScalar(
227 const Face & F,
228 const RolyComplBasisFace & rolycompl_basis,
229 const MonomialScalarBasisFace & mono_basis,
230 const size_t m,
232 );
233
235template<typename BasisType>
236Eigen::MatrixXd GMRolyComplScalar(
237 const Face & F,
238 const RolyComplBasisFace & basis1,
239 const BasisType & basis2,
240 const size_t m,
242 )
243 {
244 // If no ancestor is to be used, we shouldn't be in this overload
245 static_assert(BasisType::hasAncestor, "No method to compute this Gram matrix of derivatives");
246 return transformGM(basis2, 'C', GMRolyComplScalar(F, basis1, basis2.ancestor(), m, mono_int_map) );
247 }
248
250Eigen::MatrixXd GMScalarDerivative(
251 const Face & F,
252 const MonomialScalarBasisFace & basis1,
253 const MonomialScalarBasisFace & basis2,
254 const size_t m,
256 );
257
259Eigen::MatrixXd GMScalarDerivative(
260 const Face & F,
261 const MonomialScalarBasisFace & basis1,
262 const MonomialScalarBasisFace & basis2,
263 const size_t m,
264 const size_t l,
266 );
267
269template<typename BasisType1, typename BasisType2>
270Eigen::MatrixXd GMScalarDerivative(
271 const Face& F,
272 const BasisType1 & basis1,
273 const BasisType2 & basis2,
274 const size_t m,
276 )
277 {
278 // If no ancestor is to be used, we shouldn't be in this overload
279 static_assert(BasisType1::hasAncestor || BasisType2::hasAncestor, "No method to compute this Gram matrix of derivatives");
280
281 if constexpr (!BasisType1::hasAncestor && BasisType2::hasAncestor) {
282 return transformGM(basis2, 'C', GMScalarDerivative(F, basis1, basis2.ancestor(), m, mono_int_map) );
283 } else if constexpr (BasisType1::hasAncestor && !BasisType2::hasAncestor) {
284 return transformGM(basis1, 'R', GMScalarDerivative(F, basis1.ancestor(), basis2, m, mono_int_map) );
285 } else {
286 return transformGM(basis1, 'R', transformGM(basis2, 'C', GMScalarDerivative(F, basis1.ancestor(), basis2.ancestor(), m, mono_int_map) ) );
287 }
288 }
289
291template<typename BasisType1, typename BasisType2>
292Eigen::MatrixXd GMScalarDerivative(
293 const Face& F,
294 const BasisType1 & basis1,
295 const BasisType2 & basis2,
296 const size_t m,
297 const size_t l,
299 )
300 {
301 // If no ancestor is to be used, we shouldn't be in this overload
302 static_assert(BasisType1::hasAncestor || BasisType2::hasAncestor, "No method to compute this Gram matrix of derivatives");
303
304 if constexpr (!BasisType1::hasAncestor && BasisType2::hasAncestor) {
305 return transformGM(basis2, 'C', GMScalarDerivative(F, basis1, basis2.ancestor(), m, l, mono_int_map) );
306 } else if constexpr (BasisType1::hasAncestor && !BasisType2::hasAncestor) {
307 return transformGM(basis1, 'R', GMScalarDerivative(F, basis1.ancestor(), basis2, m, l, mono_int_map) );
308 } else {
309 return transformGM(basis1, 'R', transformGM(basis2, 'C', GMScalarDerivative(F, basis1.ancestor(), basis2.ancestor(), m, l, mono_int_map) ) );
310 }
311
312 }
313
315template<typename BasisType1, typename BasisType2>
316Eigen::MatrixXd GramMatrix(
317 const Face & F,
321 )
322 {
323 // Dimension of the gram matrix
324 size_t dim1 = basis1.dimension();
325 size_t dim2 = basis2.dimension();
326 size_t totaldegree = basis1.ancestor().max_degree()+basis2.ancestor().max_degree()-2;
327 Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1,dim2);
328
329 // Obtain integration data from IntegrateFaceMonomials
331
332 for (size_t m=0; m<2; m++){
333 gm += GMScalarDerivative(F, basis1.ancestor(), basis2.ancestor(), m, m, intmap);
334 }
335
336 return gm/std::pow(F.diam(), 2);
337 }
338
340template<typename BasisType1, typename BasisType2>
341Eigen::MatrixXd GramMatrix(
342 const Face & F,
346 )
347 {
348 // Dimension of the gram matrix
349 size_t dim1 = basis1.dimension();
350 size_t dim2 = basis2.dimension()/2;
351 size_t totaldegree = basis1.ancestor().max_degree()+basis2.max_degree()-1;
352 Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1,dim2*2);
353
354 // Obtain integration data from IntegrateFaceMonomials
356
357 std::vector<Eigen::MatrixXd> gmd = {GMScalarDerivative(F, basis1.ancestor(), basis2.ancestor(), 0, intmap), GMScalarDerivative(F, basis1.ancestor(), basis2.ancestor(), 1, intmap)};
358 // JF must be the jacobian (change of variable 3D->2D) of a scalar basis on the face (underlying basis1, perhaps after
359 // several derived bases). We create one to make sure we capture the correct jacobian
360 MonomialScalarBasisFace mono_P0_F(F, 0);
361 Eigen::Matrix<double, 2, 3> JF = mono_P0_F.jacobian();
362 VectorRd nF = F.normal();
363 Eigen::Matrix<double, 2, 3> generators2 = basis2.generators();
364 Eigen::Matrix2d W;
365 W.col(0) = JF * nF.cross(generators2.row(0));
366 W.col(1) = JF * nF.cross(generators2.row(1));
367
368 for (size_t k=0; k<2; k++) {
369 for (size_t j=0; j<2; j++) {
370 gm.block(0, j*dim2, dim1, dim2) += W(k,j) * gmd[k];
371 }
372 }
373
374 return gm;
375 }
376
378template<typename BasisType1, typename BasisType2>
379Eigen::MatrixXd GramMatrix(
380 const Face & F,
384 )
385 {
386 return GramMatrix(F, basis2, basis1, mono_int_map).transpose();
387 }
388
389
391template<typename BasisType1, typename BasisType2>
392typename boost::disable_if<boost::is_same<BasisType2, MonomialFaceIntegralsType>, Eigen::MatrixXd>::type GramMatrix(
393 const Face& F,
395 const BasisType2 & basis2,
397 )
398 {
399 return GramMatrixDiv(F, basis1.ancestor(), basis2, mono_int_map);
400 }
401
403template<typename BasisType1, typename Basis2>
404Eigen::MatrixXd GramMatrix(
405 const Face & F,
406 const BasisType1 & basis1,
409 )
410 {
411 return GramMatrixDiv(F, basis2.ancestor(), basis1, mono_int_map).transpose();
412 }
413
415/* This will work only if the generators of the TangentFamily are an orthonormal version of the Jacobian (change of variable 3D->2D) on the face */
416template<typename BasisType1>
417Eigen::MatrixXd GramMatrixDiv(
418 const Face & F,
422 )
423 {
424 size_t dim1 = basis1.dimension();
425 size_t dim2 = basis2.dimension();
426 Eigen::MatrixXd gm = Eigen::MatrixXd::Zero(dim1, dim2);
427
428 // Integrals of monomials
429 size_t totaldegree = basis1.max_degree()+basis2.max_degree()-1;
431
432 for (size_t i = 0; i < 2; i++) {
433 gm.block(i*dim1/2, 0, dim1/2, dim2) = GMScalarDerivative(F, basis1.ancestor(), basis2, i, intmap);
434 }
435
436 return gm/F.diam();
437 }
438
440Eigen::MatrixXd GramMatrixDiv(
441 const Face & F,
442 const RolyComplBasisFace & basis1,
443 const MonomialScalarBasisFace & basis2,
445 );
446
448template<typename BasisType1, typename BasisType2>
449Eigen::MatrixXd GramMatrixDiv(
450 const Face& F,
451 const BasisType1 & basis1,
452 const BasisType2 & basis2,
454 )
455 {
456 // If no ancestor is to be used, we shouldn't be in this overload
457 static_assert(useAncestor<BasisType1>() || useAncestor<BasisType2>(), "No method to compute this Gram matrix");
458
459 if constexpr (!useAncestor<BasisType1>() && useAncestor<BasisType2>()) {
460 return transformGM(basis2, 'C', GramMatrixDiv(F, basis1, basis2.ancestor(), mono_int_map) );
461 } else if constexpr (useAncestor<BasisType1>() && !useAncestor<BasisType2>()) {
462 return transformGM(basis1, 'R', GramMatrixDiv(F, basis1.ancestor(), basis2, mono_int_map) );
463 } else {
464 return transformGM(basis1, 'R', transformGM(basis2, 'C', GramMatrixDiv(F, basis1.ancestor(), basis2.ancestor(), mono_int_map) ) );
465 }
466 }
467
468
469
470
472} // end of namespace HArDCore3D
473
474#endif // end of _GMPOLY_FACE_HPP
Basis for the space of curls of polynomials.
Definition basis.hpp:1318
Basis (or rather family) of divergence of an existing basis.
Definition basis.hpp:1381
Scalar monomial basis on a face.
Definition basis.hpp:226
Basis for the complement R^{c,k}(F) in P^k(F)^2 of the range of the vectorial rotational on a face.
Definition basis.hpp:1608
Vector family for polynomial functions that are tangent to a certain place (determined by the generat...
Definition basis.hpp:948
Vector family obtained by tensorization of a scalar family.
Definition basis.hpp:610
@ Matrix
Definition basis.hpp:67
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
MonomialFaceIntegralsType IntegrateFaceMonomials(const Face &F, const int maxdeg)
Compute all integrals on a face of face monomials up to a total degree.
Definition GMpoly_face.cpp:67
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
std::unordered_map< Eigen::Vector2i, double, VecFaceHash > MonomialFaceIntegralsType
Type for list of face integrals of monomials.
Definition GMpoly_face.hpp:51
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 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 Eigen::Vector2i &p) const
Definition GMpoly_face.hpp:43
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
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::vector< MonomialFaceIntegralsType > IntegrateFaceMonomials_onEdges(const Face &F, const size_t maxdeg)
Compute all integrals, on the edges of a face, of the face monomials up to a total degree.
Definition GMpoly_face.cpp:6
Definition ddr-magnetostatics.hpp:41
MeshND::VectorRd< 2 > VectorRd
Definition Mesh2D.hpp:14
Hash function for VectorZd type.
Definition GMpoly_face.hpp:42