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
hybridcore.hpp
Go to the documentation of this file.
1// Data structures and methods to implement hybrid schemes in 3D, with polynomial unknowns
2// in the cells and on the faces (and also edges), such as Hybrid High-order (HHO) schemes.
3//
4//
5// Author: Jerome Droniou (jerome.droniou@monash.edu)
6//
7
8/*
9 *
10 * This library was developed around HHO methods, although some parts of it have a more
11 * general purpose. If you use this code or part of it in a scientific publication,
12 * please mention the following book as a reference for the underlying principles
13 * of HHO schemes:
14 *
15 * The Hybrid High-Order Method for Polytopal Meshes: Design, Analysis, and Applications.
16 * D. A. Di Pietro and J. Droniou. Modeling, Simulation and Applications, vol. 19.
17 * Springer International Publishing, 2020, xxxi + 525p. doi: 10.1007/978-3-030-37203-3.
18 * url: https://hal.archives-ouvertes.fr/hal-02151813.
19 *
20 */
21
22#ifndef HYBRIDCORE_HPP
23#define HYBRIDCORE_HPP
24
25#include <cassert>
26#include <cmath>
27
28#include <functional>
29#include <memory>
30#include <string>
31#include <vector>
32#include <mesh.hpp>
33#include <quadraturerule.hpp>
34#include <basis.hpp>
35#include <iostream>
36#include <parallel_for.hpp>
37
43namespace HArDCore3D {
44
45
51 // -----------------------------------------
52 // Free Functions
53 // -----------------------------------------
54
55 // Dimension of polynomial spaces -- only specialisations are relevant
56 template<typename GeometricSupport>
57 inline size_t const DimPoly(int m);
58
60 template<>
61 inline const size_t DimPoly<Cell>(const int m)
62 {
63 return (m >= 0 ? (m * (m + 1) * (2 * m + 1) + 9 * m * (m + 1) + 12 * (m + 1)) / 12 : 0);
64 }
65
67 template<>
68 inline const size_t DimPoly<Face>(const int m)
69 {
70 return (m >= 0 ? (m + 1) * (m + 2) / 2 : 0);
71 }
72
74 template<>
75 inline const size_t DimPoly<Edge>(const int m)
76 {
77 return (m >= 0 ? m + 1 : 0);
78 }
79
80 //-----------------------------------------------------------------------------
81 // UVector class definition
82 //-----------------------------------------------------------------------------
86 class UVector
87 {
88 public:
89 UVector(
90 const Eigen::VectorXd values,
91 const Mesh& mesh,
92 const int cell_deg,
93 const size_t face_deg
94 );
95
97 inline Eigen::VectorXd & asVectorXd() const {
98 return m_values;
99 }
100
102 inline const int get_cell_deg() const{
103 return m_cell_deg;
104 }
105
107 inline const size_t get_face_deg() const{
108 return m_face_deg;
109 }
110
112 inline const size_t n_cell_dofs() const{
113 return DimPoly<Cell>( std::max(m_cell_deg,0) );
114 }
115
117 inline const size_t n_face_dofs() const{
118 return DimPoly<Face>( m_face_deg );
119 }
120
122 inline const size_t n_total_cell_dofs() const{
123 return m_mesh.n_cells() * n_cell_dofs();
124 }
125
127 Eigen::VectorXd restr(size_t iT) const;
128
131 assert(m_cell_deg == b.get_cell_deg() || m_face_deg == b.get_face_deg() );
132 return UVector(m_values + b.asVectorXd(), m_mesh, m_cell_deg, m_face_deg);
133 }
134
137 assert(m_cell_deg == b.get_cell_deg() || m_face_deg == b.get_face_deg() );
138 return UVector(m_values - b.asVectorXd(), m_mesh, m_cell_deg, m_face_deg);
139 }
140
142 double operator()(size_t index) const{
143 return m_values(index);
144 }
145
146 private:
147 mutable Eigen::VectorXd m_values;
148 const Mesh& m_mesh;
149 const int m_cell_deg;
150 const size_t m_face_deg;
151
152 };
153
154
155 // ----------------------------------------------------------------------------
156 // HybridCore class definition
157 // ----------------------------------------------------------------------------
158
174 {
175
176 public:
178
182 const Mesh* mesh_ptr,
183 const int cell_deg,
184 const size_t face_deg,
185 const int edge_deg,
186 const bool use_threads = true,
187 std::ostream & output = std::cout,
188 const bool ortho = true
189 );
190
191 //---- Basis functions types -----//
195
196 //-------- Getters --------//
198 inline const Mesh* get_mesh() const {return m_mesh;}
199
201 inline const int CellDegree() const { return m_cell_deg; };
202 inline const int CellDegreePos() const { return m_cell_deg_pos; };
204 inline const size_t FaceDegree() const { return m_face_deg; };
205
207 inline const PolyCellBasisType & CellBasis(size_t iT) const
208 {
209 // Make sure that the basis has been created
210 assert( m_cell_basis[iT] );
211 return *m_cell_basis[iT].get();
212 }
213
215 inline const PolyFaceBasisType & FaceBasis(size_t iF) const
216 {
217 // Make sure that the basis has been created
218 assert( m_face_basis[iF] );
219 return *m_face_basis[iF].get();
220 }
221
223 inline const PolyEdgeBasisType & EdgeBasis(size_t iE) const
224 {
225 // Make sure that the basis has been created
226 assert( m_edge_basis[iE] );
227 return *m_edge_basis[iE].get();
228 }
229
230 //-------- Functions ------------//
232 double L2norm(
233 const UVector &Xh
234 ) const;
235
237 double H1norm(
238 const UVector &Xh
239 ) const;
240
242 template<typename ContinuousFunction>
244 const ContinuousFunction& f,
245 const int deg_cell,
246 const size_t deg_face,
247 size_t doe
248 ) const;
251 Eigen::VectorXd compute_weights(size_t iT) const;
252
254 double evaluate_in_cell(const UVector Xh, size_t iT, VectorRd x) const;
256 double evaluate_in_face(const UVector Xh, size_t iF, VectorRd x) const;
257
259 Eigen::VectorXd VertexValues(
260 const UVector Xh,
261 const std::string from_dofs
262 );
263
264 private:
265 // Mesh
266 const Mesh* m_mesh; // Pointer to mesh data
267 // Degree of the cell polynomials (can be -1).
268 const int m_cell_deg;
269 const size_t m_cell_deg_pos;
270 // Degree of the face polynomials
271 const int m_face_deg;
272 // Degree of the edge polynomials
273 const int m_edge_deg;
274 // Using threads
275 bool m_use_threads;
276 // Output stream
277 std::ostream & m_output;
278 // Orthonormalise or not the basis functions
279 bool m_ortho;
280
281 // Cell, face and edges bases
282 std::vector<std::unique_ptr<PolyCellBasisType>> m_cell_basis;
283 std::vector<std::unique_ptr<PolyFaceBasisType>> m_face_basis;
284 std::vector<std::unique_ptr<PolyEdgeBasisType>> m_edge_basis;
285
286 // Creates the cell, face and edge bases
287 PolyCellBasisType _construct_cell_basis(size_t iT);
288 PolyFaceBasisType _construct_face_basis(size_t iF);
289 PolyEdgeBasisType _construct_edge_basis(size_t iF);
290 };
291
292
293
294 // -------------------------------------------------------------
295 // ------- Interpolates continuous function on discrete space
296
297 template<typename ContinuousFunction>
299
300 size_t cell_deg_pos = std::max(cell_deg, 0);
302
303 // Sizes of local interpolation
304 size_t n_cell_dofs = DimPoly<Cell>(cell_deg_pos);
305 size_t n_total_cell_dofs = m_mesh->n_cells() * n_cell_dofs;
306 size_t n_face_dofs = DimPoly<Face>(face_deg);
307 size_t n_total_face_dofs = m_mesh->n_faces() * n_face_dofs;
308 Eigen::VectorXd XTF = Eigen::VectorXd::Zero( n_total_cell_dofs + n_total_face_dofs );
309
310 // Face projections
311 std::function<void(size_t, size_t)> construct_all_face_projections
312 = [&](size_t start, size_t end)->void
313 {
314 for (size_t iF = start; iF < end; iF++) {
315 Face F = *m_mesh->face(iF);
316
317 // Compute the L2 projection on face
319 boost::multi_array<double, 2> phiF_quadF = evaluate_quad<Function>::compute(FaceBasis(iF), quadF);
321
322 // Fill in the complete vector of DOFs
323 XTF.segment(n_total_cell_dofs + iF * n_face_dofs, n_face_dofs) = UF;
324 }
325 };
326 parallel_for(m_mesh->n_faces(), construct_all_face_projections, m_use_threads);
327
328 // Cell projections
329 std::function<void(size_t, size_t)> construct_all_cell_projections
330 = [&](size_t start, size_t end)->void
331 {
332 for (size_t iT = start; iT < end; iT++) {
333 Cell* cell = m_mesh->cell(iT);
334
335 // L2 projection in cell
336 // Mass matrix in cell
338 boost::multi_array<double, 2> phiT_quadT = evaluate_quad<Function>::compute(CellBasis(iT), quadT);
339 Eigen::MatrixXd MT = compute_gram_matrix(phiT_quadT, phiT_quadT, quadT, n_cell_dofs, n_cell_dofs, "sym");
340
341 // Vector of integrals of f against basis functions
342 Eigen::VectorXd bT = Eigen::VectorXd::Zero(n_cell_dofs);
343 for (size_t i = 0; i < n_cell_dofs; i++) {
344 for (size_t iqn = 0; iqn < quadT.size(); iqn++){
345 bT(i) += quadT[iqn].w * phiT_quadT[i][iqn] * f(quadT[iqn].vector());
346 }
347 }
348
349 // Vector of coefficients (on cell basis functions) of the L2(T) projection of f
350 Eigen::VectorXd UT = MT.ldlt().solve(bT);
351
352 // Fill in the complete vector of DOFs
353 size_t offset_T = iT * n_cell_dofs;
354 XTF.segment(offset_T, n_cell_dofs) = UT;
355
356 // Special case of L=-1, we replace the previously computed cell value with the proper average of face values
357 if ( cell_deg==-1 ){
358 size_t nfaces = cell->n_faces();
359 // Weights corresponding to the values in cells/on faces
360 Eigen::VectorXd barycoefT = compute_weights(iT);
361 // We transform these weights so that they apply to the coefficients on the basis functions
362 VectorRd xT = cell->center_mass();
363 double phiT_cst = CellBasis(iT).function(0, xT);
364 for (size_t ilF = 0; ilF < nfaces; ilF++){
365 VectorRd xF = cell->face(ilF)->center_mass();
366 size_t iF = cell->face(ilF)->global_index();
367 double phiF_cst = FaceBasis(iF).function(0, xF);
369 }
370
371 XTF(iT) = 0;
372 for (size_t ilF = 0; ilF < nfaces; ilF++) {
373 size_t iF = cell->face(ilF)->global_index();
374 XTF(iT) += barycoefT(ilF) * XTF(n_total_cell_dofs + iF);
375 }
376 }
377
378 }
379 };
380 parallel_for(m_mesh->n_cells(), construct_all_cell_projections, m_use_threads);
381
382 return UVector(XTF, *get_mesh(), cell_deg, face_deg);
383 }
384
385
386
387 // --------------------------------------------------------------------------------------------------
388 // ------- Functions that return class elements
389
390
391
393
394} // end of namespace HArDCore3D
395
396#endif /* HYBRIDCORE_HPP */
Family of functions expressed as linear combination of the functions of a given basis.
Definition basis.hpp:389
Definition hybridcore.hpp:174
Definition hybridcore.hpp:87
Class to describe a mesh.
Definition MeshND.hpp:17
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th function at point x.
Definition basis.hpp:428
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:2224
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:353
@ Matrix
Definition basis.hpp:67
static void parallel_for(unsigned nb_elements, std::function< void(size_t start, size_t end)> functor, bool use_threads=true)
Generic function to execute threaded processes.
Definition parallel_for.hpp:58
bool use_threads
Definition HHO_DiffAdvecReac.hpp:47
size_t const DimPoly(int m)
Eigen::VectorXd compute_weights(size_t iT) const
Computes the weights to get cell values from face values when l=-1.
Definition hybridcore.cpp:175
double evaluate_in_face(const UVector Xh, size_t iF, VectorRd x) const
Evaluates a discrete function on the face iF at point x.
Definition hybridcore.cpp:309
const size_t n_cell_dofs() const
Number of dofs in each cell.
Definition hybridcore.hpp:112
const int CellDegree() const
Return the degree of cell polynomials.
Definition hybridcore.hpp:201
Eigen::VectorXd VertexValues(const UVector Xh, const std::string from_dofs)
From a hybrid function, computes a vector of values at the vertices of the mesh.
Definition hybridcore.cpp:325
Eigen::VectorXd restr(size_t iT) const
Extract the restriction of the unknowns corresponding to cell iT and its faces.
Definition hybridcore.cpp:28
const PolyFaceBasisType & FaceBasis(size_t iF) const
Return face basis for face with global index iF.
Definition hybridcore.hpp:215
const int CellDegreePos() const
Definition hybridcore.hpp:202
const int get_cell_deg() const
Return the cell degree.
Definition hybridcore.hpp:102
const size_t DimPoly< Face >(const int m)
Compute the size of the basis of 2-variate polynomials up to degree m.
Definition hybridcore.hpp:68
const PolyEdgeBasisType & EdgeBasis(size_t iE) const
Return edge basis for edge with global index iE.
Definition hybridcore.hpp:223
const size_t n_total_cell_dofs() const
Total number of cell dofs (in the vector, this is where the face dofs start)
Definition hybridcore.hpp:122
Family< MonomialScalarBasisCell > PolyCellBasisType
type for cell basis
Definition hybridcore.hpp:192
UVector operator+(const UVector &b)
Overloads the addition: adds the coefficients.
Definition hybridcore.hpp:130
const Mesh * get_mesh() const
Returns a pointer to the mesh.
Definition hybridcore.hpp:198
const size_t get_face_deg() const
Return the face degree.
Definition hybridcore.hpp:107
double evaluate_in_cell(const UVector Xh, size_t iT, VectorRd x) const
Evaluates a discrete function in the cell iT at point x.
Definition hybridcore.cpp:298
const PolyCellBasisType & CellBasis(size_t iT) const
Return cell basis for element with global index iT.
Definition hybridcore.hpp:207
const size_t n_face_dofs() const
Number of dofs on each face.
Definition hybridcore.hpp:117
Family< MonomialScalarBasisFace > PolyFaceBasisType
type for face basis
Definition hybridcore.hpp:193
double L2norm(const UVector &Xh) const
Compute L2 norm of a discrete function (using cell values)
Definition hybridcore.cpp:201
const size_t FaceDegree() const
Return the degree of face polynomials.
Definition hybridcore.hpp:204
const size_t DimPoly< Cell >(const int m)
Compute the size of the basis of 3-variate polynomials up to degree m.
Definition hybridcore.hpp:61
double operator()(size_t index) const
Overloads the (): returns the corresponding coefficient.
Definition hybridcore.hpp:142
const size_t DimPoly< Edge >(const int m)
Compute the size of the basis of 1-variate polynomials up to degree m.
Definition hybridcore.hpp:75
Family< MonomialScalarBasisEdge > PolyEdgeBasisType
type for edge basis
Definition hybridcore.hpp:194
double H1norm(const UVector &Xh) const
Compute discrete H1 norm of a discrete function.
Definition hybridcore.cpp:227
UVector interpolate(const ContinuousFunction &f, const int deg_cell, const size_t deg_face, size_t doe) const
Compute the interpolant in the discrete space of a continuous function.
Definition hybridcore.hpp:298
Eigen::VectorXd & asVectorXd() const
Return the values as an Eigen vector.
Definition hybridcore.hpp:97
UVector operator-(const UVector &b)
Overloads the subtraction: subtracts the coefficients.
Definition hybridcore.hpp:136
Face< dimension > * face(std::size_t index) const
get a constant pointer to a face using its global index
Definition MeshND.hpp:196
std::size_t n_faces() const
number of faces in the mesh.
Definition MeshND.hpp:59
std::size_t n_cells() const
number of cells in the mesh.
Definition MeshND.hpp:60
Cell< dimension > * cell(std::size_t index) const
get a constant pointer to a cell using its global index
Definition MeshND.hpp:197
QuadratureRule generate_quadrature_rule(const Cell &T, const int doe, const bool force_split)
Generate quadrature rule on mesh element.
Definition quadraturerule.cpp:11
std::vector< QuadratureNode > QuadratureRule
Definition quadraturerule.hpp:61
Definition ddr-magnetostatics.hpp:41