41 std::ostream & output = std::cout
88 const std::vector<Eigen::ArrayXd>& f_quad,
89 const std::vector<Eigen::ArrayXd>& g_quad,
94 std::vector<double> L2weight = {}
99 const std::vector<Eigen::ArrayXXd>& F_quad,
100 const std::vector<Eigen::ArrayXXd>& G_quad,
105 std::vector<Eigen::Matrix2d> L2Weight = {}
109 template<
typename Function>
113 template<
typename Function>
116 Eigen::VectorXd
nc_restr(
const Eigen::VectorXd &Xh,
size_t iT)
const;
118 double nc_L2norm(
const Eigen::VectorXd &Xh)
const;
122 double nc_H1norm(
const Eigen::VectorXd &Xh)
const;
125 double nc_evaluate_in_cell(
const Eigen::VectorXd XTF,
size_t iT,
double x,
double y)
const;
129 const Eigen::VectorXd Xh,
130 const double weight = 0
135 std::tuple<std::vector<cell_basis_type>,
136 std::vector<cell_gradient_type>,
138 create_nc_basis(
size_t iT)
const;
140 std::vector<VectorRd> create_ml_nodes(
size_t iT)
const;
143 std::vector<std::vector<cell_basis_type> > _nc_bases;
144 std::vector<std::vector<cell_gradient_type> > _nc_gradients;
146 std::vector<Eigen::MatrixXd> _M_basis;
149 std::vector<std::vector<VectorRd>> _ml_nodes;
152 double sign(
const double s)
const;
155 std::ostream & m_output;
170 std::ostream & output):
171 HybridCore (mesh_ptr, std::min(size_t(1),
K),
L, false, output),
179 _nc_bases.reserve(ncells);
180 _nc_gradients.reserve(ncells);
181 _ml_nodes.reserve(ncells);
182 _M_basis.reserve(ncells);
184 for (
size_t iT = 0; iT < mesh_ptr->
n_cells(); iT++) {
185 std::vector<VectorRd> ml_nodes = create_ml_nodes(iT);
186 _ml_nodes.push_back(ml_nodes);
187 std::tuple<std::vector<cell_basis_type>, std::vector<cell_gradient_type>, Eigen::MatrixXd>
nc_basis = create_nc_basis(iT);
188 _nc_bases.push_back(std::get<0>(
nc_basis));
189 _nc_gradients.push_back(std::get<1>(
nc_basis));
190 _M_basis.push_back(std::get<2>(
nc_basis));
198std::vector<VectorRd> LEPNCCore::create_ml_nodes(
size_t iT)
const {
200 Cell* cell = mesh->
cell(iT);
201 size_t nedges = cell->
n_edges();
202 std::vector<VectorRd> ml_cell(mesh->
dim()+1,VectorRd::Zero());
206 std::vector<VectorRd> v_cur(mesh->
dim()+1,VectorRd::Zero());
208 for (
size_t i=0;
i < nedges;
i++){
209 v_cur[0] = cell->vertex(
i)->coords();
210 for (
size_t j=
i+1;
j < nedges;
j++){
211 v_cur[1] = cell->vertex(
j)->coords();
212 for (
size_t k=
j+1; k < nedges; k++){
213 v_cur[2] = cell->vertex(k)->coords();
214 Eigen::MatrixXd matv = Eigen::MatrixXd::Zero(mesh->
dim(), mesh->
dim());
215 for (
size_t ll=0; ll < mesh->
dim(); ll++){
216 matv.col(ll) = v_cur[ll+1]-v_cur[0];
218 double area_cur = std::abs(matv.determinant());
219 if (area_cur > area_max){
220 for (
size_t z=0; z < mesh->
dim()+1; z++){
221 ml_cell[z] = v_cur[z];
236std::tuple<std::vector<LEPNCCore::cell_basis_type>,
237 std::vector<LEPNCCore::cell_gradient_type>,
239 LEPNCCore::create_nc_basis(
size_t iT)
const {
242 size_t nedgesT = cell->
n_edges();
243 std::vector<cell_basis_type>
nc_basis(
DimPoly<Cell>(1)+nedgesT,[](
double x,
double y)->
double {
return 0;});
253 for (
size_t ilE = 0; ilE < nedgesT; ilE++){
254 Edge* edge = cell->edge(ilE);
258 std::vector<VectorRd> Nint_edge(2, VectorRd::Zero());
259 for (
size_t ilV = 0; ilV < 2; ilV++){
261 VectorRd temp_norm = Rot * (edge->vertex(ilV)->coords() - xT);
263 double orientation = sign( (xT - edge->center_mass()).dot(temp_norm) );
264 Nint_edge[ilV] = orientation * temp_norm.normalized();
268 double edge_length = edge->measure();
269 cell_basis_type unscaled_phi = [Nint_edge, xT, edge_length](
double x,
double y)->
double {
273 for (
size_t ilV = 0; ilV < 2; ilV++){
274 double signed_dist = (xT - posX).dot(Nint_edge[ilV]);
275 val *= std::max(
double(0), signed_dist) / edge_length;
281 double scaling_factor_phi = 0;
283 for (QuadratureNode quadrule : quadE){
284 scaling_factor_phi += quadrule.w * unscaled_phi(quadrule.x, quadrule.y);
286 if (std::abs(scaling_factor_phi) < 1e-10){
287 m_output <<
"Scaling factor of non-conforming basis function too small: " << std::abs(scaling_factor_phi) <<
"\n";
292 scaling_factor_phi /= edge->measure();
293 cell_basis_type phi = [unscaled_phi, scaling_factor_phi](
double x,
double y)->
double {
294 return unscaled_phi(x, y) / scaling_factor_phi;
302 for (
size_t ilV = 0; ilV < 2; ilV++){
304 if ( (xT - posX).dot(Nint_edge[ilV]) < 0){
307 for (
size_t ilVp = 0; ilVp < 2; ilVp++){
309 double signed_dist_ilVp = (xT - posX).dot(Nint_edge[ilVp]);
310 coef_ilV *= std::max(
double(0), signed_dist_ilVp) / edge_length;
313 val -= coef_ilV * Nint_edge[ilV] / edge_length;
315 return val / scaling_factor_phi;
331 for (
size_t i = 0; i < DimPoly<Cell>(1);
i++){
340 for (
size_t ilE = 0; ilE < nedgesT; ilE++){
341 Edge* edge = cell->edge(ilE);
343 for (QuadratureNode quadrule : quadE){
344 M_basis(
i,
DimPoly<Cell>(1)+ilE) -= quadrule.w * phi0(quadrule.x, quadrule.y);
356 std::vector<VectorRd> nodal_points = _ml_nodes[iT];
357 Eigen::MatrixXd M_nodal_values = Eigen::MatrixXd::Zero(
DimPoly<Cell>(1), mesh->dim()+1);
358 for (
size_t i=0; i < DimPoly<Cell>(1);
i++){
359 for (
size_t k=0; k < mesh->dim() + 1; k++){
366 M_basis = (M_nodal_values.inverse() ) * M_basis;
369 for (
size_t i=0; i < DimPoly<Cell>(1);
i++){
370 Eigen::VectorXd M_basis_rowi = M_basis.row(
i);
373 for (
size_t j = 0; j < DimPoly<Cell>(1)+nedgesT;
j++){
379 val += M_basis_rowi(
j) * phi0(x, y);
386 for (
size_t j = 0; j < DimPoly<Cell>(1)+nedgesT;
j++){
392 val += M_basis_rowi(
j) * dphi0(x, y);
411 assert(iT < this->
get_mesh()->n_cells());
412 assert(
i < _nc_bases[iT].size());
413 return _nc_bases[iT][
i];
417 assert(iT < this->
get_mesh()->n_cells());
418 assert(
i < _nc_gradients[iT].size());
419 return _nc_gradients[iT][
i];
423 assert(iT < this->
get_mesh()->n_cells());
425 return _ml_nodes[iT][
i];
434 size_t nbq = quad.size();
437 std::vector<Eigen::ArrayXd> nc_phi_quad(nbasis, Eigen::ArrayXd::Zero(nbq));
440 std::vector<Eigen::ArrayXd> nc_phi_quad_tmp(nbasis, Eigen::ArrayXd::Zero(nbq));
441 for (
size_t i = 0;
i < nbasis;
i++){
445 for (
size_t iqn = 0; iqn < nbq; iqn++){
452 for (
size_t iqn = 0; iqn < nbq; iqn++){
453 nc_phi_quad_tmp[
i](iqn) = nc_phi_i(quad[iqn].x, quad[iqn].y);
460 nc_phi_quad[
i] = nc_phi_quad_tmp[
i];
462 for (
size_t i = 0; i < DimPoly<Cell>(1);
i++){
463 for (
size_t j = 0;
j < nbasis;
j++){
464 nc_phi_quad[
i] += _M_basis[iT](
i,
j) * nc_phi_quad_tmp[
j];
473 size_t nbq = quad.size();
476 std::vector<Eigen::ArrayXXd> Dnc_phi_quad(nbasis, Eigen::ArrayXXd::Zero(
get_mesh()->dim(), nbq));
479 std::vector<Eigen::ArrayXXd> Dnc_phi_quad_tmp(nbasis, Eigen::ArrayXXd::Zero(
get_mesh()->dim(), nbq));
480 for (
size_t i = 0;
i < nbasis;
i++){
484 for (
size_t iqn = 0; iqn < nbq; iqn++){
491 for (
size_t iqn = 0; iqn < nbq; iqn++){
492 Dnc_phi_quad_tmp[
i].col(iqn) = Dnc_phi_i(quad[iqn].x, quad[iqn].y);
499 Dnc_phi_quad[
i] = Dnc_phi_quad_tmp[
i];
501 for (
size_t i = 0; i < DimPoly<Cell>(1);
i++){
502 for (
size_t j = 0;
j < nbasis;
j++){
503 Dnc_phi_quad[
i] += _M_basis[iT](
i,
j) * Dnc_phi_quad_tmp[
j];
517 Eigen::MatrixXd
LEPNCCore::gram_matrix(
const std::vector<Eigen::ArrayXd>& f_quad,
const std::vector<Eigen::ArrayXd>& g_quad,
const size_t& nrows,
const size_t& ncols,
const QuadratureRule& quad,
const bool& sym, std::vector<double> L2weight)
const {
518 Eigen::MatrixXd GGM = Eigen::MatrixXd::Zero(nrows, ncols);
520 size_t nbq = quad.size();
523 Eigen::ArrayXd quad_L2_weights = Eigen::ArrayXd::Zero(nbq);
524 if (L2weight.size() == 0){
525 for (
size_t iqn = 0; iqn < nbq; iqn++){
526 quad_L2_weights(iqn) = quad[iqn].w;
529 for (
size_t iqn = 0; iqn < nbq; iqn++){
530 quad_L2_weights(iqn) = quad[iqn].w * L2weight[iqn];
534 for (
size_t i = 0;
i < nrows;
i++){
537 for (
size_t j = 0;
j < jcut;
j++){
538 GGM(
i,
j) = GGM(
j,
i);
540 for (
size_t j = jcut;
j < ncols;
j++){
543 GGM(
i,
j) = (quad_L2_weights * f_quad[
i] * g_quad[
j]).sum();
551 Eigen::MatrixXd
LEPNCCore::gram_matrix(
const std::vector<Eigen::ArrayXXd>& F_quad,
const std::vector<Eigen::ArrayXXd>& G_quad,
const size_t& nrows,
const size_t& ncols,
const QuadratureRule& quad,
const bool& sym, std::vector<Eigen::Matrix2d> L2Weight)
const {
552 Eigen::MatrixXd GSM = Eigen::MatrixXd::Zero(nrows, ncols);
554 size_t nbq = quad.size();
555 for (
size_t i = 0;
i < nrows;
i++){
558 for (
size_t j = 0;
j < jcut;
j++){
559 GSM(
i,
j) = GSM(
j,
i);
562 Eigen::ArrayXXd WeightsTimesF_quad = Eigen::ArrayXXd::Zero(
get_mesh()->dim(), nbq);
563 if (L2Weight.size() == 0){
564 for (
size_t iqn = 0; iqn < nbq; iqn++){
565 WeightsTimesF_quad.col(iqn) = quad[iqn].w * F_quad[
i].col(iqn);
568 for (
size_t iqn = 0; iqn < nbq; iqn++){
569 WeightsTimesF_quad.col(iqn) = quad[iqn].w * (L2Weight[iqn] * F_quad[
i].col(iqn).matrix());
572 for (
size_t j = jcut;
j < ncols;
j++){
574 GSM(
i,
j) = (WeightsTimesF_quad * G_quad[
j]).sum();
586template<
typename Function>
589 size_t ncells = mesh_ptr->
n_cells();
590 size_t nedges = mesh_ptr->
n_edges();
591 Eigen::VectorXd Xh = Eigen::VectorXd::Zero(
DimPoly<Cell>(1)*ncells + nedges);
595 for (
size_t iF = 0; iF < nedges; iF++) {
598 Xh(offset_edges + iF) += quadrule.w * f(quadrule.x, quadrule.y);
600 Xh(offset_edges + iF) /= mesh_ptr->
edge(iF)->
measure();
607 for (
size_t iT = 0; iT < mesh_ptr->
n_cells(); iT++) {
611 std::vector<Eigen::ArrayXd> nc_phi_quadT =
nc_basis_quad(iT, quadT);
616 Eigen::VectorXd bT = Eigen::VectorXd::Zero(
DimPoly<Cell>(1));
617 for (
size_t i = 0; i < DimPoly<Cell>(1);
i++) {
619 std::function<double(
double,
double)> adjusted_f = [&f, &edgesT, &Xh, &offset_edges, &iT,
this](
double x,
double y) {
621 for (
size_t ilF = 0; ilF < edgesT.size(); ilF++){
622 size_t iF = edgesT[ilF]->global_index();
628 bT(
i) += quadrule.w * phi_i(quadrule.x, quadrule.y) * adjusted_f(quadrule.x, quadrule.y);
634 Eigen::VectorXd UT = MT.ldlt().solve(bT);
644template<
typename Function>
647 size_t ncells = mesh_ptr->
n_cells();
648 size_t nedges = mesh_ptr->
n_edges();
649 Eigen::VectorXd Xh = Eigen::VectorXd::Zero(
DimPoly<Cell>(1)*ncells + nedges);
653 for (
size_t iF = 0; iF < nedges; iF++) {
656 Xh(offset_edges + iF) += quadrule.w * f(quadrule.x, quadrule.y);
658 Xh(offset_edges + iF) /= mesh_ptr->
edge(iF)->
measure();
664 for (
size_t iT = 0; iT < mesh_ptr->
n_cells(); iT++) {
665 for (
size_t i = 0; i < DimPoly<Cell>(1);
i++){
681 Eigen::VectorXd XTF = Eigen::VectorXd::Zero(
DimPoly<Cell>(1)+nedgesT);
686 for (
size_t ilE = 0; ilE < nedgesT; ilE++){
700 for (
size_t iT = 0; iT < ncells; iT++) {
704 size_t nedgesT = cell->
n_edges();
708 std::vector<Eigen::ArrayXd> nc_phiT_quadT =
nc_basis_quad(iT, quadT);
710 Eigen::MatrixXd MTT =
gram_matrix(nc_phiT_quadT, nc_phiT_quadT, nlocal_dofs, nlocal_dofs, quadT,
true);
711 Eigen::VectorXd XTF =
nc_restr(Xh, iT);
713 value += XTF.dot(MTT*XTF);
725 for (
size_t iT = 0; iT < ncells; iT++) {
730 for (
size_t i = 0; i < DimPoly<Cell>(1);
i++){
744 for (
size_t iT = 0; iT < ncells; iT++) {
750 Eigen::MatrixXd StiffT =
gram_matrix(Dnc_phiT_quad, Dnc_phiT_quad, nlocal_dofs, nlocal_dofs, quadT,
true);
751 Eigen::VectorXd XTF =
nc_restr(Xh, iT);
752 value += XTF.dot(StiffT * XTF);
766 for (
size_t i = 0; i < DimPoly<Cell>(1);
i++) {
769 value += Xh(index) * phi_i(x,y);
774 for (
size_t ilE = 0; ilE < nedgesT; ilE++) {
776 const size_t index = offset_edges + mesh_ptr->
cell(iT)->
edge(ilE)->global_index();
777 value += Xh(index) * phi_i(x,y);
787 Eigen::VectorXd function_vertex_cells = Eigen::VectorXd::Zero(mesh_ptr->
n_vertices());
788 for (
size_t iV = 0; iV < mesh_ptr->
n_vertices(); iV++){
791 auto nb_cells = cList.size();
792 for (
size_t ilT = 0; ilT < nb_cells; ilT++){
794 function_vertex_cells(iV) += temp;
796 function_vertex_cells(iV) /= nb_cells;
801 Eigen::VectorXd function_vertex_edges = Eigen::VectorXd::Zero(mesh_ptr->
n_vertices());
802 for (
size_t iV = 0; iV < mesh_ptr->
n_vertices(); iV++){
804 auto nb_edges = eList.size();
805 for (Edge* edge : eList){
806 auto cList_edge = edge->get_cells();
809 auto nb_cells_edges = cList_edge.size();
810 for (Cell* cell : cList_edge){
811 function_vertex_edges(iV) +=
nc_evaluate_in_cell(Xh, cell->global_index(), xE.x(), xE.y()) / nb_cells_edges;
814 function_vertex_edges(iV) /= nb_edges;
817 return (1-weight)*function_vertex_cells + weight*function_vertex_edges;
822double LEPNCCore::sign(
const double s)
const {
Definition hybridcore.hpp:179
Definition lepnccore.hpp:33
Compute max and min eigenvalues of all matrices for i
Definition compute_eigs.m:5
GradientValue gradient(size_t i, const VectorRd &x) const
Evaluate the gradient of the i-th function at point x.
Definition basis.hpp:378
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
@ Function
Definition basis.hpp:1673
size_t L
Definition HHO_DiffAdvecReac.hpp:46
size_t K
Definition HHO_DiffAdvecReac.hpp:46
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 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
Eigen::VectorXd nc_VertexValues(const Eigen::VectorXd Xh, const double weight=0)
From a non-conforming discrete function, computes a vector of values at the vertices of the mesh.
Definition lepnccore.hpp:783
Eigen::MatrixXd gram_matrix(const std::vector< Eigen::ArrayXd > &f_quad, const std::vector< Eigen::ArrayXd > &g_quad, const size_t &nrows, const size_t &ncols, const QuadratureRule &quad, const bool &sym, std::vector< double > L2weight={}) const
Definition lepnccore.hpp:517
double nc_L2norm(const Eigen::VectorXd &Xh) const
Compute L2 norm of a discrete function (given by coefficients on the basis functions)
Definition lepnccore.hpp:695
LEPNCCore(const Mesh *mesh_ptr, const size_t K, const size_t L, std::ostream &output=std::cout)
Class constructor: initialise the LEPNCCore class, and creates non-conforming basis functions (and gr...
Definition lepnccore.hpp:167
const std::vector< Eigen::ArrayXd > nc_basis_quad(const size_t iT, const QuadratureRule quad) const
Computes non-conforming basis functions at the given quadrature nodes.
Definition lepnccore.hpp:432
Eigen::VectorXd nc_restr(const Eigen::VectorXd &Xh, size_t iT) const
Extract from a global vector Xh of unknowns the non-conforming unknowns corresponding to cell iT.
Definition lepnccore.hpp:678
const std::vector< Eigen::ArrayXXd > grad_nc_basis_quad(const size_t iT, const QuadratureRule quad) const
Compute at the quadrature nodes, where are the cell basis functions.
Definition lepnccore.hpp:471
std::function< VectorRd(double, double)> cell_gradient_type
type for gradients of cell basis
Definition lepnccore.hpp:46
const cell_gradient_type & nc_gradient(size_t iT, size_t i) const
Return a reference to the gradient of the i'th non-conforming basis function of the cell iT.
Definition lepnccore.hpp:416
double nc_evaluate_in_cell(const Eigen::VectorXd XTF, size_t iT, double x, double y) const
Evaluates a non-conforming discrete function in the cell iT at point (x,y)
Definition lepnccore.hpp:763
std::function< double(double, double)> cell_basis_type
type for cell basis
Definition lepnccore.hpp:45
double nc_L2norm_ml(const Eigen::VectorXd &Xh) const
Compute L2 norm of the mass-lumped discrete function (given by coefficients on the basis functions)
Definition lepnccore.hpp:720
const VectorRd ml_node(size_t iT, size_t i) const
Return the i'th nodal point in cell iT (for mass lumping)
Definition lepnccore.hpp:422
Eigen::VectorXd nc_interpolate_ml(const Function &f, size_t doe) const
Interpolates a continuous function on the degrees of freedom, using the moments on the basis function...
Definition lepnccore.hpp:645
Eigen::VectorXd nc_interpolate_moments(const Function &f, size_t doe) const
Interpolates a continuous function on the degrees of freedom, using the moments on the basis function...
Definition lepnccore.hpp:587
const cell_basis_type & nc_basis(size_t iT, size_t i) const
Return a reference to the i'th non-conforming basis function of the cell iT.
Definition lepnccore.hpp:410
double nc_H1norm(const Eigen::VectorXd &Xh) const
Compute broken H1 norm of a discrete function (given by coefficients on the basis functions)
Definition lepnccore.hpp:739
double measure() const
Return the Lebesgue measure of the Polytope.
Definition Polytope2D.hpp:76
Polytope< DIMENSION > Cell
Definition Polytope2D.hpp:151
std::vector< Polytope< DIMENSION > * > get_cells() const
Return the cells of the Polytope.
Definition Polytope2D.hpp:85
std::size_t n_vertices() const
number of vertices in the mesh.
Definition Mesh2D.hpp:60
std::size_t dim() const
dimension of the mesh
Definition Mesh2D.hpp:58
Cell * cell(std::size_t index) const
get a constant pointer to a cell using its global index
Definition Mesh2D.hpp:178
size_t n_edges() const
Return the number of edges of the Polytope.
Definition Polytope2D.hpp:88
Edge * edge(std::size_t index) const
get a constant pointer to a edge using its global index
Definition Mesh2D.hpp:168
Polytope< 1 > Edge
A Face is a Polytope with object_dim = DIMENSION - 1.
Definition Polytope2D.hpp:147
Polytope< 1 > * edge(const size_t i) const
Return the i-th edge of the Polytope.
Definition Polytope2D.hpp:303
std::size_t n_cells() const
number of cells in the mesh.
Definition Mesh2D.hpp:63
std::vector< Polytope< 1 > * > get_edges() const
Return the edges of the Polytope.
Definition Polytope2D.hpp:83
Vertex * vertex(std::size_t index) const
get a constant pointer to a vertex using its global index
Definition Mesh2D.hpp:163
std::size_t n_edges() const
number of edges in the mesh.
Definition Mesh2D.hpp:61
VectorRd coords() const
Return the coordinates of a Vertex.
Definition Polytope2D.hpp:371
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
for j
Definition mmread.m:174
Definition ddr-klplate.hpp:27
Description of one node and one weight from a quadrature rule.
Definition quadraturerule.hpp:41