HArD::Core2D
Hybrid Arbitrary Degree::Core 2D - Library to implement 2D schemes with edge and cell polynomials as unknowns
Loading...
Searching...
No Matches
compute-hho-norms.hpp
Go to the documentation of this file.
1#ifndef COMPUTE_HHO_NORMS_HPP
2#define COMPUTE_HHO_NORMS_HPP
3
4#include <sstream>
5
6#include <boost/fusion/include/map.hpp>
7#include <boost/fusion/include/for_each.hpp>
8
9#include "discrete-space.hpp"
10
11#include <parallel_for.hpp>
12#include <GMpoly_cell.hpp>
13#include <GMpoly_edge.hpp>
14
15namespace HArDCore2D {
16
17 namespace DSL {
18
19 template<TensorRankE Rank>
20 std::vector<std::pair<double, double> > compute_hho_component_norms(
21 const DiscreteSpace & Vh,
22 const std::vector<Eigen::VectorXd> & vh,
23 bool use_threads = true
24 )
25 {
26 if( !(Vh.isAvailable<typename HHODOFsTypes<Rank>::CellDOFsType>("CellDOFs") &&
27 Vh.isAvailable<typename HHODOFsTypes<Rank>::EdgeDOFsType>("EdgeDOFs")) ) {
28 std::stringstream message;
29 message << "The following local spaces are not available in '"
30 << Vh.name() << "': "
31 << (!Vh.isAvailable<typename HHODOFsTypes<Rank>::CellDOFsType>("CellDOFs") ? "CellDOFs " : "")
32 << (!Vh.isAvailable<typename HHODOFsTypes<Rank>::EdgeDOFsType>("EdgeDOFs") ? "EdgeDOFs" : "")
33 << std::flush;
34
35 throw DiscreteSpaceError(message.str());
36 } //if
37
38 const auto & cell_dofs = Vh.get<typename HHODOFsTypes<Rank>::CellDOFsType>("CellDOFs");
39 const auto & edge_dofs = Vh.get<typename HHODOFsTypes<Rank>::EdgeDOFsType>("EdgeDOFs");
40
41 size_t cell_degree = cell_dofs[0]->max_degree();
42 size_t edge_degree = edge_dofs[0]->max_degree();
43
44 size_t nb_vectors = vh.size();
45 std::vector<Eigen::VectorXd> local_L2_squared_norms(nb_vectors, Eigen::VectorXd::Zero(Vh.mesh().n_cells()));
46 std::vector<Eigen::VectorXd> local_H1_squared_norms(nb_vectors, Eigen::VectorXd::Zero(Vh.mesh().n_cells()));
47
48 auto compute_local_squarednorms
49 = [&Vh, &vh, &cell_dofs, &edge_dofs, cell_degree, edge_degree, &local_L2_squared_norms, &local_H1_squared_norms, &nb_vectors](size_t start, size_t end)->void
50 {
51 for (size_t iT = start; iT < end; iT++){
52 const Cell & T = *Vh.mesh().cell(iT);
53
54 // Mass matrices
55 MonomialCellIntegralsType int_mono_cell = IntegrateCellMonomials(T, 2 * edge_degree);
56 Eigen::MatrixXd mass_cell = GramMatrix(T, *cell_dofs[iT], int_mono_cell);
57 Eigen::MatrixXd stiff_cell = GramMatrix(T, GradientBasis(*cell_dofs[iT]), int_mono_cell);
58
59 // Local vectors
60 std::vector<Eigen::VectorXd> vT(nb_vectors, Eigen::VectorXd::Zero(Vh.dimensionCell(iT)));
61 std::transform(vh.begin(), vh.end(), vT.begin(), [&Vh, &T](const Eigen::VectorXd & wh)->Eigen::VectorXd{ return Vh.restrict(T, wh); });
62
63 // Cell contributions
64 for (size_t i = 0; i < nb_vectors; i++) {
65 Eigen::VectorXd cell_dofs = vT[i].tail(Vh.numberOfLocalCellDofs());
66
67 // L2 norm
68 local_L2_squared_norms[i](iT) += cell_dofs.transpose() * mass_cell * cell_dofs;
69 // H1 norm
70 local_H1_squared_norms[i](iT) += cell_dofs.transpose() * stiff_cell * cell_dofs;
71 } // for
72
73 // Edge contributions
74 for (size_t iE = 0; iE < T.n_edges(); iE++) {
75 Edge & E = *T.edge(iE);
76
77 MonomialEdgeIntegralsType int_mono_edge = IntegrateEdgeMonomials(E, 2 * edge_degree);
78 Eigen::MatrixXd mass_edge = GramMatrix(E, *edge_dofs[E.global_index()], int_mono_edge);
79
80 QuadratureRule quad = generate_quadrature_rule(E, 2 * std::max(edge_degree, cell_degree) + 1);
81 auto cell_dofs_quad = evaluate_quad<Function>::compute(*cell_dofs[iT], quad);
82 auto edge_dofs_quad = evaluate_quad<Function>::compute(*edge_dofs[E.global_index()], quad);
83 Eigen::MatrixXd mass_cell_edge = compute_gram_matrix(cell_dofs_quad, edge_dofs_quad, quad);
84 Eigen::MatrixXd mass_cell = compute_gram_matrix(cell_dofs_quad, quad);
85
86 for (size_t i = 0; i < nb_vectors; i++) {
87 Eigen::VectorXd cell_dofs = vT[i].segment(Vh.localOffset(T), Vh.numberOfLocalCellDofs());
88 Eigen::VectorXd edge_dofs = vT[i].segment(Vh.localOffset(T, E), Vh.numberOfLocalEdgeDofs());
89
90 local_H1_squared_norms[i](iT)
91 += (1. / T.diam()) * (
92 edge_dofs.dot(mass_edge * edge_dofs)
93 -2. * cell_dofs.dot(mass_cell_edge.eval() * edge_dofs)
94 + cell_dofs.dot(mass_cell * cell_dofs)
95 );
96 } // for i
97 } // for iE
98 }
99 };
100 parallel_for(Vh.mesh().n_cells(), compute_local_squarednorms, use_threads);
101
102 // Vector of outputs
103 std::vector<std::pair<double,double> > norms(nb_vectors);
104 for (size_t i = 0; i < nb_vectors; i++){
105 norms[i].first = std::sqrt(std::abs(local_L2_squared_norms[i].sum()));
106 norms[i].second = std::sqrt(std::abs(local_H1_squared_norms[i].sum()));
107 } // for
108
109 return norms;
110 }
111
112 //------------------------------------------------------------------------------
113
114 template<TensorRankE Rank>
115 std::vector<std::pair<double, double> > compute_hho_potential_norms(
116 const DiscreteSpace & Vh,
117 const std::vector<Eigen::MatrixXd> & potential,
118 const std::vector<Eigen::MatrixXd> & stabilization,
119 const std::vector<Eigen::VectorXd> & vh,
120 bool use_threads = true
121 )
122 {
123 if( !(Vh.isAvailable<typename HHODOFsTypes<Rank>::PotentialReconstructionType>("PotentialReconstructionBases")) ) {
124 std::stringstream message;
125 message << "The following local spaces are not available in '"
126 << Vh.name() << "': PotentialReconstructionBases"
127 << std::flush;
128
129 throw DiscreteSpaceError(message.str());
130 } //if
131
132 const auto & potential_bases = Vh.get<typename HHODOFsTypes<Rank>::PotentialReconstructionType>("PotentialReconstructionBases");
133
134 size_t potential_degree = potential_bases[0]->max_degree();
135
136 size_t nb_vectors = vh.size();
137 std::vector<Eigen::VectorXd> local_L2_squared_norms(nb_vectors, Eigen::VectorXd::Zero(Vh.mesh().n_cells()));
138 std::vector<Eigen::VectorXd> local_H1_squared_norms(nb_vectors, Eigen::VectorXd::Zero(Vh.mesh().n_cells()));
139
140 auto compute_local_squared_norms
141 = [&Vh, &vh, &potential, &stabilization, &potential_bases, &potential_degree, &local_L2_squared_norms, &local_H1_squared_norms, &nb_vectors](size_t start, size_t end)->void
142 {
143 for (size_t iT = start; iT < end; iT++) {
144 const Cell & T = *Vh.mesh().cell(iT);
145
146 MonomialCellIntegralsType int_mono_cell = IntegrateCellMonomials(T, 2 * potential_degree);
147 Eigen::MatrixXd mass_cell = GramMatrix(T, *potential_bases[iT], int_mono_cell);
148 Eigen::MatrixXd stiff_cell = GramMatrix(T, GradientBasis(*potential_bases[iT]), int_mono_cell);
149
150 // Local potentials vectors
151 std::vector<Eigen::VectorXd> vT(nb_vectors, Eigen::VectorXd::Zero(Vh.dimensionCell(iT)));
152 std::transform( vh.begin(), vh.end(), vT.begin(),
153 [&Vh, &T](const Eigen::VectorXd & wh)->Eigen::VectorXd{ return Vh.restrict(T, wh); } );
154
155 // Cell contributions
156 for (size_t i = 0; i < nb_vectors; i++) {
157 Eigen::VectorXd potential_vT = potential[iT] * vT[i];
158
159 // L2 norm
160 local_L2_squared_norms[i](iT) += potential_vT.transpose() * mass_cell * potential_vT;
161 // H1 norm
162 local_H1_squared_norms[i](iT) += potential_vT.dot(stiff_cell * potential_vT)
163 + vT[i].dot(stabilization[iT] * vT[i]);
164 }
165 } // for iT
166 };
167 parallel_for(Vh.mesh().n_cells(), compute_local_squared_norms, use_threads);
168
169 // Vector of outputs
170 std::vector<std::pair<double,double> > norms(nb_vectors);
171 for (size_t i = 0; i < nb_vectors; i++){
172 norms[i].first = std::sqrt(std::abs(local_L2_squared_norms[i].sum()));
173 norms[i].second = std::sqrt(std::abs(local_H1_squared_norms[i].sum()));
174 } // for
175
176 return norms;
177 }
178
179 //------------------------------------------------------------------------------
180
181 template<typename MeshEntity>
182 struct ComputeMass {
184 const DiscreteSpace & discrete_space,
185 const MeshEntity & mesh_entity,
186 std::list<Eigen::MatrixXd> & mass_matrices
187 )
188 : m_discrete_space(discrete_space),
189 m_mesh_entity(mesh_entity),
190 m_mass_matrices(mass_matrices)
191 {
192 // Do nothing
193 }
194
195 template<typename DofType>
196 void operator()(const DofType & dof_type) const {
197 const auto & dof_basis = m_discrete_space.get<typename DofType::first_type>(dof_type.second)[m_mesh_entity.global_index()];
198 Eigen::MatrixXd mass = GramMatrix(m_mesh_entity, *dof_basis);
199 m_mass_matrices.push_back(mass);
200 }
201
202 private:
203 const DiscreteSpace & m_discrete_space;
204 const MeshEntity & m_mesh_entity;
205 std::list<Eigen::MatrixXd> & m_mass_matrices;
206 };
207
209 template<typename CellDofsMapType, typename EdgeDofsMapType>
210 std::vector<double> compute_l2_dof_norms(
211 const DiscreteSpace & Vh,
212 const CellDofsMapType & cell_dofs_map,
213 const EdgeDofsMapType & edge_dofs_map,
214 const std::vector<Eigen::VectorXd> & vh,
215 bool use_threads = true
216 )
217 {
218 size_t nb_vectors = vh.size();
219 std::vector<Eigen::VectorXd> local_L2_squared_norms(nb_vectors, Eigen::VectorXd::Zero(Vh.mesh().n_cells()));
220
221 auto compute_local_squarednorms
222 = [&Vh, &cell_dofs_map, &edge_dofs_map, &vh, nb_vectors, &local_L2_squared_norms](size_t start, size_t end)->void
223 {
224 for (size_t iT = start; iT < end; iT++) {
225 const Cell & T = *Vh.mesh().cell(iT);
226 double hT = T.diam();
227
228 // Local vectors
229 std::vector<Eigen::VectorXd> vT(nb_vectors, Eigen::VectorXd::Zero(Vh.dimensionCell(iT)));
230 std::transform(vh.begin(), vh.end(), vT.begin(), [&Vh, &T](const Eigen::VectorXd & wh)->Eigen::VectorXd{ return Vh.restrict(T, wh); });
231
232 // Edge contributions
233 for (size_t iE = 0; iE < T.n_edges(); iE++) {
234 const Edge & E = *T.edge(iE);
235
236 std::list<Eigen::MatrixXd> mass_matrices_E;
237 boost::fusion::for_each(edge_dofs_map, ComputeMass(Vh, E, mass_matrices_E));
238 size_t offset_E = Vh.localOffset(T, E);
239 for (const auto & M : mass_matrices_E) {
240 for (size_t i = 0; i < nb_vectors; i++) {
241 const auto & vT_block = vT[i].segment(offset_E, M.cols());
242 local_L2_squared_norms[i](iT) += hT * vT_block.transpose() * M * vT_block;
243 } // for i
244 offset_E += M.cols();
245 } // for M
246 } // for iE
247
248 // Cell contributions
249 std::list<Eigen::MatrixXd> mass_matrices_T;
250 boost::fusion::for_each(cell_dofs_map, ComputeMass(Vh, T, mass_matrices_T));
251 size_t offset_T = Vh.localOffset(T);
252 for (const auto & M : mass_matrices_T) {
253 for (size_t i = 0; i < nb_vectors; i++) {
254 const auto & vT_block = vT[i].segment(offset_T, M.cols());
255 local_L2_squared_norms[i](iT) += vT_block.transpose() * M * vT_block;
256 } // for i
257 offset_T += M.cols();
258 } // for M
259 } // for iT
260 };
261 parallel_for(Vh.mesh().n_cells(), compute_local_squarednorms, use_threads);
262
263 // Vector of outputs
264 std::vector<double> norms(nb_vectors);
265 for (size_t i = 0; i < nb_vectors; i++){
266 norms[i] = std::sqrt(std::abs(local_L2_squared_norms[i].sum()));
267 } // for
268
269 return norms;
270 }
271
272 } // namespace DSL
273
274} // namespace HArDCore2D
275
276#endif
Definition discrete-space.hpp:20
const std::vector< std::unique_ptr< T > > & get(const std::string &name) const
Definition discrete-space.hpp:84
const Mesh & mesh() const
Definition discrete-space.hpp:68
const std::string & name() const
Definition discrete-space.hpp:63
bool isAvailable(const std::string &name) const
Definition discrete-space.hpp:75
size_t numberOfLocalEdgeDofs() const
Definition local-dof-table.hpp:37
size_t localOffset(const Edge &E, const Vertex &V) const
Definition local-dof-table.cpp:36
size_t dimensionCell(const Cell &T) const
Returns the dimension of the local space on the cell T (including faces, edges and vertices)
Definition local-dof-table.hpp:109
size_t numberOfLocalCellDofs() const
Definition local-dof-table.hpp:47
Basis for the space of gradients of polynomials.
Definition basis.hpp:1181
Compute max and min eigenvalues of all matrices for i
Definition compute_eigs.m:5
end
Definition compute_eigs.m:12
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
Cell * cell(std::size_t index) const
get a constant pointer to a cell using its global index
Definition Mesh2D.hpp:178
double diam() const
Return the diameter of the Polytope.
Definition Polytope2D.hpp:74
std::size_t n_cells() const
number of cells in the mesh.
Definition Mesh2D.hpp:63
std::vector< QuadratureNode > QuadratureRule
Definition quadraturerule.hpp:55
std::vector< double > MonomialEdgeIntegralsType
Type for list of edge integrals of monomials.
Definition GMpoly_edge.hpp:34
std::unordered_map< VectorZd, double, VecHash > MonomialCellIntegralsType
Type for list of integrals of monomials.
Definition GMpoly_cell.hpp:53
MonomialEdgeIntegralsType IntegrateEdgeMonomials(const Edge &E, const size_t maxdeg)
Compute all integrals of edge monomials up to a total degree.
Definition GMpoly_edge.cpp:6
MonomialCellIntegralsType IntegrateCellMonomials(const Cell &T, const size_t maxdeg)
Compute all integrals on a cell of monomials up to a total degree, using vertex values.
Definition GMpoly_cell.cpp:7
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:86
QuadratureRule generate_quadrature_rule(const Cell &T, const int doe, const bool force_split)
Generate quadrature rule on mesh element.
Definition quadraturerule.cpp:10
if(strcmp(field, 'real')) % real valued entries T
Definition mmread.m:93
std::vector< std::pair< double, double > > compute_hho_potential_norms(const DiscreteSpace &Vh, const std::vector< Eigen::MatrixXd > &potential, const std::vector< Eigen::MatrixXd > &stabilization, const std::vector< Eigen::VectorXd > &vh, bool use_threads=true)
Definition compute-hho-norms.hpp:115
std::vector< std::pair< double, double > > compute_hho_component_norms(const DiscreteSpace &Vh, const std::vector< Eigen::VectorXd > &vh, bool use_threads=true)
Definition compute-hho-norms.hpp:20
std::vector< double > compute_l2_dof_norms(const DiscreteSpace &Vh, const CellDofsMapType &cell_dofs_map, const EdgeDofsMapType &edge_dofs_map, const std::vector< Eigen::VectorXd > &vh, bool use_threads=true)
Compute L2 component norms for spaces with generic cell and edge DOFs.
Definition compute-hho-norms.hpp:210
Definition ddr-klplate.hpp:27
Definition compute-hho-norms.hpp:182
ComputeMass(const DiscreteSpace &discrete_space, const MeshEntity &mesh_entity, std::list< Eigen::MatrixXd > &mass_matrices)
Definition compute-hho-norms.hpp:183
void operator()(const DofType &dof_type) const
Definition compute-hho-norms.hpp:196
Definition discrete-space.hpp:113
Definition hho-dofs-types.hpp:11