HArD::Core2D
Hybrid Arbitrary Degree::Core 2D - Library to implement 2D schemes with edge 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 2D, with polynomial unknowns
2// in the cells and on the 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 <cell.hpp>
34//#include <edge.hpp>
35#include <quadraturerule.hpp>
36#include <basis.hpp>
37#include <iostream>
38#include <parallel_for.hpp>
39
45namespace HArDCore2D {
46
47
53 // -----------------------------------------
54 // Free Functions
55 // -----------------------------------------
56
57 // Dimension of polynomial spaces -- only specialisations are relevant
58 template<typename GeometricSupport>
59 inline size_t const DimPoly(int m);
60
62 template<>
63 inline const size_t DimPoly<Cell>(const int m)
64 {
65 return (m >= 0 ? (m + 1) * (m + 2) / 2 : 0);
66 };
67
69 template<>
70 inline const size_t DimPoly<Edge>(const int m)
71 {
72 return (m >= 0 ? m + 1 : 0);
73 }
74
75 //-----------------------------------------------------------------------------
76 // UVector class definition
77 //-----------------------------------------------------------------------------
81 class UVector
82 {
83 public:
84 UVector(
85 const Eigen::VectorXd & values,
86 const Mesh & mesh,
87 const int cell_deg,
88 const size_t edge_deg
89 );
90
92 inline Eigen::VectorXd & asVectorXd() const {
93 return m_values;
94 }
95
97 inline const int get_cell_deg() const{
98 return m_cell_deg;
99 }
100
102 inline const size_t get_edge_deg() const{
103 return m_edge_deg;
104 }
105
107 inline const size_t n_cell_dofs() const{
108 return DimPoly<Cell>( std::max(m_cell_deg,0) );
109 }
110
112 inline const size_t n_edge_dofs() const{
113 return DimPoly<Edge>( m_edge_deg );
114 }
115
117 inline const size_t n_total_cell_dofs() const{
118 return m_mesh.n_cells() * n_cell_dofs();
119 }
120
122 Eigen::VectorXd restr(size_t iT) const;
123
126 assert(m_cell_deg == b.get_cell_deg() || m_edge_deg == b.get_edge_deg() );
127 return UVector(m_values + b.asVectorXd(), m_mesh, m_cell_deg, m_edge_deg);
128 }
129
132 assert(m_cell_deg == b.get_cell_deg() || m_edge_deg == b.get_edge_deg() );
133 return UVector(m_values - b.asVectorXd(), m_mesh, m_cell_deg, m_edge_deg);
134 }
135
137 void operator+=(const UVector& b){
138 assert(m_cell_deg == b.get_cell_deg() || m_edge_deg == b.get_edge_deg() );
139 this->asVectorXd() = m_values + b.asVectorXd();
140 }
141
143 void operator/=(const double & r){
144 this->asVectorXd() = m_values / r;
145 }
146
148 double operator()(size_t index) const{
149 return m_values(index);
150 }
151
152 private:
153 mutable Eigen::VectorXd m_values;
154 const Mesh& m_mesh;
155 const int m_cell_deg;
156 const size_t m_edge_deg;
157
158 };
159
160
161 // ----------------------------------------------------------------------------
162 // HybridCore class definition
163 // ----------------------------------------------------------------------------
164
179 {
180
181 public:
183
187 const Mesh* mesh_ptr,
188 const int cell_deg,
189 const size_t edge_deg,
190 const bool use_threads = true,
191 std::ostream & output = std::cout,
192 const bool ortho = true
193 );
194
195 //---- Basis functions types -----//
198
199 //-------- Getters --------//
201 inline const Mesh* get_mesh() const {return m_mesh;}
202
204 inline const int CellDegree() const { return m_cell_deg; };
205 inline const int CellDegreePos() const { return m_cell_deg_pos; };
207 inline const size_t EdgeDegree() const { return m_edge_deg; };
208
210 inline const PolyCellBasisType & CellBasis(size_t iT) const
211 {
212 // Make sure that the basis has been created
213 assert( m_cell_basis[iT] );
214 return *m_cell_basis[iT].get();
215 }
216
218 inline const PolyEdgeBasisType & EdgeBasis(size_t iE) const
219 {
220 // Make sure that the basis has been created
221 assert( m_edge_basis[iE] );
222 return *m_edge_basis[iE].get();
223 }
224
225 //-------- Functions ------------//
227 double L2norm(
228 const UVector &Xh
229 ) const;
230
232 double H1norm(
233 const UVector &Xh
234 ) const;
235
237 template<typename ContinuousFunction>
239 const ContinuousFunction& f,
240 const int deg_cell,
241 const size_t deg_edge,
242 size_t doe
243 ) const;
246 Eigen::VectorXd compute_weights(size_t iT) const;
247
249 double evaluate_in_cell(const UVector Xh, size_t iT, VectorRd x) const;
251 double evaluate_in_edge(const UVector Xh, size_t iE, VectorRd x) const;
252
254 Eigen::VectorXd VertexValues(
255 const UVector Xh,
256 const std::string from_dofs
257 );
258
259 private:
260 // Mesh
261 const Mesh* m_mesh; // Pointer to mesh data
262 // Degree of the cell polynomials (can be -1).
263 const int m_cell_deg;
264 const size_t m_cell_deg_pos;
265 // Degree of the edge polynomials
266 const int m_edge_deg;
267 // Using threads
268 const bool m_use_threads;
269 // Output stream
270 std::ostream & m_output;
271 // Orthonormalise or not the basis functions
272 const bool m_ortho;
273
274 // Cell and edges bases
275 std::vector<std::unique_ptr<PolyCellBasisType>> m_cell_basis;
276 std::vector<std::unique_ptr<PolyEdgeBasisType>> m_edge_basis;
277
278 // Creates the cell and edge bases
279 PolyCellBasisType _construct_cell_basis(size_t iT);
280 PolyEdgeBasisType _construct_edge_basis(size_t iF);
281
282 };
283
284
285
286 // -------------------------------------------------------------
287 // ------- Interpolates continuous function on discrete space
288
289 template<typename ContinuousFunction>
290 UVector HybridCore::interpolate(const ContinuousFunction& f, int cell_deg, size_t edge_deg, size_t doe) const {
291
292 size_t cell_deg_pos = std::max(cell_deg, 0);
293 assert(cell_deg <= CellDegree() || edge_deg <= EdgeDegree() || cell_deg > -1);
294
295 // Sizes of local interpolation
296 size_t n_cell_dofs = DimPoly<Cell>(cell_deg_pos);
297 size_t n_total_cell_dofs = m_mesh->n_cells() * n_cell_dofs;
298 size_t n_edge_dofs = DimPoly<Edge>(edge_deg);
299 size_t n_total_edge_dofs = m_mesh->n_edges() * n_edge_dofs;
300 Eigen::VectorXd XTF = Eigen::VectorXd::Zero( n_total_cell_dofs + n_total_edge_dofs );
301
302 // Edge projections
303 std::function<void(size_t, size_t)> construct_all_edge_projections
304 = [&](size_t start, size_t end)->void
305 {
306 for (size_t iE = start; iE < end; iE++) {
307 Edge E = *m_mesh->edge(iE);
308
309 // Compute the L2 projection on edge
311 boost::multi_array<double, 2> phiE_quadE = evaluate_quad<Function>::compute(EdgeBasis(iE), quadE);
312 Eigen::VectorXd UF = l2_projection<PolyEdgeBasisType>(f, EdgeBasis(iE), quadE, phiE_quadE);
313
314 // Fill in the complete vector of DOFs
315 XTF.segment(n_total_cell_dofs + iE * n_edge_dofs, n_edge_dofs) = UF;
316 }
317 };
318 parallel_for(m_mesh->n_edges(), construct_all_edge_projections, m_use_threads);
319
320 // Cell projections
321 std::function<void(size_t, size_t)> construct_all_cell_projections
322 = [&](size_t start, size_t end)->void
323 {
324 for (size_t iT = start; iT < end; iT++) {
325 Cell* cell = m_mesh->cell(iT);
326
327 // L2 projection in cell
328 // Mass matrix in cell
329 QuadratureRule quadT = generate_quadrature_rule(*cell, doe);
330 boost::multi_array<double, 2> phiT_quadT = evaluate_quad<Function>::compute(CellBasis(iT), quadT);
331 Eigen::MatrixXd MT = compute_gram_matrix(phiT_quadT, phiT_quadT, quadT, n_cell_dofs, n_cell_dofs, "sym");
332
333 // Vector of integrals of f against basis functions
334 Eigen::VectorXd bT = Eigen::VectorXd::Zero(n_cell_dofs);
335 for (size_t i = 0; i < n_cell_dofs; i++) {
336 for (size_t iqn = 0; iqn < quadT.size(); iqn++){
337 bT(i) += quadT[iqn].w * phiT_quadT[i][iqn] * f(quadT[iqn].vector());
338 }
339 }
340
341 // Vector of coefficients (on cell basis functions) of the L2(T) projection of f
342 Eigen::VectorXd UT = MT.ldlt().solve(bT);
343
344 // Fill in the complete vector of DOFs
345 size_t offset_T = iT * n_cell_dofs;
346 XTF.segment(offset_T, n_cell_dofs) = UT;
347
348 // Special case of L=-1, we replace the previously computed cell value with the proper average of edge values
349 if ( cell_deg==-1 ){
350 size_t nedges = cell->n_edges();
351 // Weights corresponding to the values in cells/on edges
352 Eigen::VectorXd barycoefT = compute_weights(iT);
353 // We transform these weights so that they apply to the coefficients on the basis functions
354 VectorRd xT = cell->center_mass();
355 double phiT_cst = CellBasis(iT).function(0, xT);
356 for (size_t ilE = 0; ilE < nedges; ilE++){
357 VectorRd xE = cell->edge(ilE)->center_mass();
358 size_t iE = cell->edge(ilE)->global_index();
359 double phiE_cst = EdgeBasis(iE).function(0, xE);
360 barycoefT(ilE) *= phiE_cst / phiT_cst;
361 }
362
363 XTF(iT) = 0;
364 for (size_t ilE = 0; ilE < nedges; ilE++) {
365 size_t iE = cell->edge(ilE)->global_index();
366 XTF(iT) += barycoefT(ilE) * XTF(n_total_cell_dofs + iE);
367 }
368 }
369
370 }
371 };
372 parallel_for(m_mesh->n_cells(), construct_all_cell_projections, m_use_threads);
373
374 return UVector(XTF, *get_mesh(), cell_deg, edge_deg);
375 }
376
377
379
380} // end of namespace HArDCore2D
381
382#endif /* HYBRIDCORE_HPP */
Definition basis.hpp:311
Definition hybridcore.hpp:179
Definition hybridcore.hpp:82
Definition Mesh2D.hpp:26
Compute max and min eigenvalues of all matrices for i
Definition compute_eigs.m:5
end
Definition compute_eigs.m:12
FunctionValue function(size_t i, const VectorRd &x) const
Evaluate the i-th function at point x.
Definition basis.hpp:351
Eigen::Vector2d VectorRd
Definition basis.hpp:55
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:225
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:2288
static void parallel_for(unsigned nb_elements, std::function< void(size_t start, size_t end)> functor, bool use_threads=true, unsigned nb_threads_max=1e9)
Generic function to execute threaded processes.
Definition parallel_for.hpp:42
bool use_threads
Definition HHO_DiffAdvecReac.hpp:47
Eigen::VectorXd compute_weights(size_t iT) const
Computes the weights to get cell values from edge values when l=-1.
Definition hybridcore.cpp:138
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:288
Eigen::VectorXd restr(size_t iT) const
Extract the restriction of the unknowns corresponding to cell iT and its edges.
Definition hybridcore.cpp:29
const size_t get_edge_deg() const
Return the edge degree.
Definition hybridcore.hpp:102
const int CellDegreePos() const
Definition hybridcore.hpp:205
const size_t DimPoly< Cell >(const int m)
Compute the size of the basis of 2-variate polynomials up to degree m.
Definition hybridcore.hpp:63
const size_t n_total_cell_dofs() const
Total number of cell dofs (in the vector, this is where the edge dofs start)
Definition hybridcore.hpp:117
const int CellDegree() const
Return the degree of cell polynomials.
Definition hybridcore.hpp:204
UVector operator+(const UVector &b)
Overloads the addition: adds the coefficients.
Definition hybridcore.hpp:125
const int get_cell_deg() const
Return the cell degree.
Definition hybridcore.hpp:97
void operator+=(const UVector &b)
Overloads the increment: adds the coefficients.
Definition hybridcore.hpp:137
const size_t EdgeDegree() const
Return the degree of edge polynomials.
Definition hybridcore.hpp:207
UVector operator-(const UVector &b)
Overloads the subtraction: subtracts the coefficients.
Definition hybridcore.hpp:131
Family< MonomialScalarBasisCell > PolyCellBasisType
type for cell basis
Definition hybridcore.hpp:196
const PolyEdgeBasisType & EdgeBasis(size_t iE) const
Return edge basis for edge with global index iE.
Definition hybridcore.hpp:218
Family< MonomialScalarBasisEdge > PolyEdgeBasisType
type for edge basis
Definition hybridcore.hpp:197
const size_t n_cell_dofs() const
Number of dofs in each cell.
Definition hybridcore.hpp:107
UVector interpolate(const ContinuousFunction &f, const int deg_cell, const size_t deg_edge, size_t doe) const
Compute the interpolant in the discrete space of a continuous function.
Definition hybridcore.hpp:290
Eigen::VectorXd & asVectorXd() const
Return the values as an Eigen vector.
Definition hybridcore.hpp:92
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:261
void operator/=(const double &r)
Overloads the increment: adds the coefficients.
Definition hybridcore.hpp:143
double L2norm(const UVector &Xh) const
Compute L2 norm of a discrete function (using cell values)
Definition hybridcore.cpp:164
double evaluate_in_edge(const UVector Xh, size_t iE, VectorRd x) const
Evaluates a discrete function on the edge iE at point x.
Definition hybridcore.cpp:272
size_t const DimPoly(int m)
double H1norm(const UVector &Xh) const
Compute discrete H1 norm of a discrete function.
Definition hybridcore.cpp:190
const size_t n_edge_dofs() const
Number of dofs on each edge.
Definition hybridcore.hpp:112
const Mesh * get_mesh() const
Returns a pointer to the mesh.
Definition hybridcore.hpp:201
const PolyCellBasisType & CellBasis(size_t iT) const
Return cell basis for element with global index iT.
Definition hybridcore.hpp:210
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:70
double operator()(size_t index) const
Overloads the (): returns the corresponding coefficient.
Definition hybridcore.hpp:148
Cell * cell(std::size_t index) const
get a constant pointer to a cell using its global index
Definition Mesh2D.hpp:178
Edge * edge(std::size_t index) const
get a constant pointer to a edge using its global index
Definition Mesh2D.hpp:168
std::size_t n_cells() const
number of cells in the mesh.
Definition Mesh2D.hpp:63
std::size_t n_edges() const
number of edges in the mesh.
Definition Mesh2D.hpp:61
std::vector< QuadratureNode > QuadratureRule
Definition quadraturerule.hpp:55
QuadratureRule generate_quadrature_rule(const Cell &T, const int doe, const bool force_split)
Generate quadrature rule on mesh element.
Definition quadraturerule.cpp:10
Definition ddr-klplate.hpp:27