PolyDiM
C++ library for POLYtopal DIscretization Methods
Loading...
Searching...
No Matches
FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp
Go to the documentation of this file.
1// _LICENSE_HEADER_
2//
3// Copyright (C) 2019 - 2025.
4// Terms register on the GPL-3.0 license.
5//
6// This file can be redistributed and/or modified under the license terms.
7//
8// See top level LICENSE file for more details.
9//
10// This file can be used citing references in CITATION.cff file.
11
12#ifndef __FEM_Quadrilateral_PCC_2D_ReferenceElement_HPP
13#define __FEM_Quadrilateral_PCC_2D_ReferenceElement_HPP
14
15#include "Eigen/Eigen"
17#include "QuadratureData.hpp"
19#include "VEM_Quadrature_2D.hpp"
20
21namespace Polydim
22{
23namespace FEM
24{
25namespace PCC
26{
28{
29 unsigned int Dimension;
30 unsigned int Order;
31 unsigned int NumDofs0D;
32 unsigned int NumDofs1D;
33 unsigned int NumDofs2D;
34
35 unsigned int NumBasisFunctions;
36 Eigen::MatrixXd DofPositions;
37 std::vector<std::array<unsigned int, 2>> DofTypes;
38
39 std::map<std::pair<unsigned int, unsigned int>, std::pair<unsigned int, bool>> Edges_by_vertices;
40
43
45 std::vector<Eigen::MatrixXd> ReferenceBasisFunctionDerivativeValues;
46 std::array<Eigen::MatrixXd, 4> ReferenceBasisFunctionSecondDerivativeValues;
47
49};
50
52{
53
54 Eigen::MatrixXd Vertices;
55
57 {
58 Vertices = Eigen::MatrixXd::Zero(3, 4);
59 Vertices << 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0;
60 }
62
64 {
65
66 if (order <= 0)
67 throw std::runtime_error("not valid order");
68
70
71 result.Dimension = 2;
72 result.Order = order;
73 result.NumBasisFunctions = (order + 1) * (order + 1);
74 result.NumDofs0D = 1;
75 result.NumDofs1D = order - 1;
76 result.NumDofs2D = (order - 1) * (order - 1);
77
78 Polydim::FEM::PCC::FEM_PCC_1D_ReferenceElement boundary_reference_element;
80 boundary_reference_element.Create(order, Polydim::FEM::PCC::FEM_PCC_1D_Types::Equispaced);
81 const Eigen::VectorXd reference_edge_dofs_poisitions = result.BoundaryReferenceElement_Data.DofPositions.row(0);
82
83 // Edge directions
84 result.Edges_by_vertices = {{{0, 1}, {0, true}},
85 {{1, 0}, {0, false}},
86 {{1, 2}, {1, true}},
87 {{2, 1}, {1, false}},
88 {{2, 3}, {2, false}},
89 {{3, 2}, {2, true}},
90 {{3, 0}, {3, false}},
91 {{0, 3}, {3, true}}};
92
93 // Reordering Dofs using convention [point, edge, cell]
94 result.DofPositions.setZero(3, result.NumBasisFunctions);
95 result.DofTypes.resize(result.NumBasisFunctions);
96
97 for (unsigned int d1 = 0; d1 < 2; d1++)
98 {
99 if (d1 == 0)
100 {
101 for (unsigned int d2 = 0; d2 < 2; d2++)
102 {
103 result.DofPositions.col(2 * d1 + d2) << reference_edge_dofs_poisitions(d2),
104 reference_edge_dofs_poisitions(d1), 0.0;
105 result.DofTypes[2 * d1 + d2] = {d2, d1};
106 }
107 }
108 else
109 {
110 for (unsigned int d2 = 0; d2 < 2; d2++)
111 {
112 const unsigned int index = (d2 == 0) ? 1 : 0;
113 result.DofPositions.col(2 * d1 + d2) << reference_edge_dofs_poisitions(index),
114 reference_edge_dofs_poisitions(d1), 0.0;
115 result.DofTypes[2 * d1 + d2] = {index, d1};
116 }
117 }
118 }
119
120 if (order > 1)
121 {
122
123 for (unsigned int d1 = 0; d1 < 2; d1++)
124 {
125 result.DofPositions.row(0).segment(4 * result.NumDofs0D + 2 * d1 * result.NumDofs1D, result.NumDofs1D) =
126 reference_edge_dofs_poisitions.segment(2, result.NumDofs1D);
127 result.DofPositions.row(1).segment(4 * result.NumDofs0D + 2 * d1 * result.NumDofs1D, result.NumDofs1D) =
128 Eigen::VectorXd::Ones(result.NumDofs1D) * reference_edge_dofs_poisitions(d1);
129
130 for (unsigned int d2 = 2; d2 < result.BoundaryReferenceElement_Data.NumBasisFunctions; d2++)
131 result.DofTypes[4 * result.NumDofs0D + 2 * d1 * result.NumDofs1D + d2 - 2] = {d2, d1};
132 }
133
134 for (int d1 = 0; d1 < 2; d1++)
135 {
136 const unsigned index = (d1 == 1) ? 0 : 1;
137 result.DofPositions.row(0).segment(4 * result.NumDofs0D + (2 * d1 + 1) * result.NumDofs1D, result.NumDofs1D) =
138 Eigen::VectorXd::Ones(result.NumDofs1D) * reference_edge_dofs_poisitions(index);
139 result.DofPositions.row(1).segment(4 * result.NumDofs0D + (2 * d1 + 1) * result.NumDofs1D, result.NumDofs1D) =
140 reference_edge_dofs_poisitions.segment(2, result.NumDofs1D);
141
142 for (unsigned int d2 = 2; d2 < result.BoundaryReferenceElement_Data.NumBasisFunctions; d2++)
143 result.DofTypes[4 * result.NumDofs0D + (2 * d1 + 1) * result.NumDofs1D + d2 - 2] = {index, d2};
144 }
145
146 unsigned int dof = 4 + 4 * result.NumDofs1D;
147 for (unsigned int d1 = 2; d1 < result.BoundaryReferenceElement_Data.NumBasisFunctions; d1++)
148 {
149 for (unsigned int d2 = 2; d2 < result.BoundaryReferenceElement_Data.NumBasisFunctions; d2++)
150 {
151 result.DofPositions.col(dof) << reference_edge_dofs_poisitions(d2), reference_edge_dofs_poisitions(d1), 0.0;
152
153 result.DofTypes[dof] = {d2, d1};
154
155 dof++;
156 }
157 }
158 }
159
160 std::vector<Eigen::Matrix3d> polygonTriangulationVertices(2);
161 polygonTriangulationVertices[0] = Vertices.leftCols(3);
162 polygonTriangulationVertices[1] << Vertices.rightCols(2), Vertices.col(0);
163 result.ReferenceTriangleQuadrature =
166 result.ReferenceSquareQuadrature =
167 quadrature.PolygonInternalQuadrature(result.ReferenceTriangleQuadrature, polygonTriangulationVertices);
168
169 result.ReferenceBasisFunctionValues = EvaluateBasisFunctions(result.ReferenceSquareQuadrature.Points, result);
170 result.ReferenceBasisFunctionDerivativeValues =
171 EvaluateBasisFunctionDerivatives(result.ReferenceSquareQuadrature.Points, result);
172 // result.ReferenceBasisFunctionSecondDerivativeValues =
173 // EvaluateBasisFunctionSecondDerivatives(result.ReferenceSquareQuadrature.Points, result);
174
175 return result;
176 }
177
178 // ***************************************************************************
179 Eigen::MatrixXd EvaluateBasisFunctions(const Eigen::MatrixXd &points,
181 {
182
183 const unsigned int num_points = points.cols();
184 Eigen::MatrixXd x = Eigen::MatrixXd::Zero(3, num_points);
185 x.row(0) = points.row(0);
186 Eigen::MatrixXd y = Eigen::MatrixXd::Zero(3, num_points);
187 y.row(0) = points.row(1);
188
189 Polydim::FEM::PCC::FEM_PCC_1D_ReferenceElement boundary_reference_element;
190 const Eigen::MatrixXd values_x =
191 boundary_reference_element.EvaluateBasisFunctions(x, reference_element_data.BoundaryReferenceElement_Data);
192 const Eigen::MatrixXd values_y =
193 boundary_reference_element.EvaluateBasisFunctions(y, reference_element_data.BoundaryReferenceElement_Data);
194
195 Eigen::MatrixXd values = Eigen::MatrixXd::Ones(num_points, reference_element_data.NumBasisFunctions);
196
197 for (unsigned int d = 0; d < reference_element_data.NumBasisFunctions; d++)
198 {
199 const auto &dofType = reference_element_data.DofTypes[d];
200 values.col(d) = values_x.col(dofType[0]).array() * values_y.col(dofType[1]).array();
201 }
202
203 return values;
204 }
205 // ***************************************************************************
206 std::vector<Eigen::MatrixXd> EvaluateBasisFunctionDerivatives(
207 const Eigen::MatrixXd &points,
209 {
210 const unsigned int num_points = points.cols();
211 Eigen::MatrixXd x = Eigen::MatrixXd::Zero(3, num_points);
212 x.row(0) = points.row(0);
213 Eigen::MatrixXd y = Eigen::MatrixXd::Zero(3, num_points);
214 y.row(0) = points.row(1);
215
216 Polydim::FEM::PCC::FEM_PCC_1D_ReferenceElement boundary_reference_element;
217 const Eigen::MatrixXd values_x =
218 boundary_reference_element.EvaluateBasisFunctions(x, reference_element_data.BoundaryReferenceElement_Data);
219 const std::vector<Eigen::MatrixXd> values_x_dx =
220 boundary_reference_element.EvaluateBasisFunctionDerivatives(x, reference_element_data.BoundaryReferenceElement_Data);
221 const Eigen::MatrixXd values_y =
222 boundary_reference_element.EvaluateBasisFunctions(y, reference_element_data.BoundaryReferenceElement_Data);
223 const std::vector<Eigen::MatrixXd> values_y_dy =
224 boundary_reference_element.EvaluateBasisFunctionDerivatives(y, reference_element_data.BoundaryReferenceElement_Data);
225
226 std::vector<Eigen::MatrixXd> grad_values(reference_element_data.Dimension,
227 Eigen::MatrixXd::Ones(num_points, reference_element_data.NumBasisFunctions));
228
229 for (unsigned int d = 0; d < reference_element_data.NumBasisFunctions; d++)
230 {
231 const auto &dofType = reference_element_data.DofTypes[d];
232 grad_values[0].col(d) = values_x_dx[0].col(dofType[0]).array() * values_y.col(dofType[1]).array();
233 grad_values[1].col(d) = values_x.col(dofType[0]).array() * values_y_dy[0].col(dofType[1]).array();
234 }
235
236 return grad_values;
237 }
238 // ***************************************************************************
239 std::array<Eigen::MatrixXd, 4> EvaluateBasisFunctionSecondDerivatives(const Eigen::MatrixXd &,
241 {
242 throw std::runtime_error("not implemented method");
243 }
244};
245} // namespace PCC
246} // namespace FEM
247} // namespace Polydim
248
249#endif
static QuadratureData FillPointsAndWeights(const unsigned int &order)
Definition Quadrature_Gauss2D_Triangle.cpp:18
Factory that builds the reference element data for a 1D PCC finite element.
Definition FEM_PCC_1D_ReferenceElement.hpp:67
Polydim::FEM::PCC::FEM_PCC_1D_ReferenceElement_Data Create(const unsigned int order, const Polydim::FEM::PCC::FEM_PCC_1D_Types type=Polydim::FEM::PCC::FEM_PCC_1D_Types::Equispaced, const unsigned int quadrature_order=0) const
Definition FEM_PCC_1D_ReferenceElement.hpp:69
Eigen::MatrixXd EvaluateBasisFunctions(const Eigen::MatrixXd &points, const Polydim::FEM::PCC::FEM_PCC_1D_ReferenceElement_Data &reference_element_data) const
Definition FEM_PCC_1D_ReferenceElement.hpp:199
std::vector< Eigen::MatrixXd > EvaluateBasisFunctionDerivatives(const Eigen::MatrixXd &points, const Polydim::FEM::PCC::FEM_PCC_1D_ReferenceElement_Data &reference_element_data) const
Definition FEM_PCC_1D_ReferenceElement.hpp:207
Definition VEM_Quadrature_2D.hpp:40
Gedim::Quadrature::QuadratureData PolygonInternalQuadrature(const Gedim::Quadrature::QuadratureData &data, const std::vector< Eigen::Matrix3d > &polygonTriangulationVertices) const
Definition VEM_Quadrature_2D.cpp:139
Definition FEM_MCC_2D_LocalSpace.cpp:17
Definition QuadratureData.hpp:22
Reference element data for a 1D PCC finite element.
Definition FEM_PCC_1D_ReferenceElement.hpp:46
Eigen::MatrixXd DofPositions
Definition FEM_PCC_1D_ReferenceElement.hpp:53
unsigned int NumBasisFunctions
Definition FEM_PCC_1D_ReferenceElement.hpp:52
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:28
Eigen::MatrixXd ReferenceBasisFunctionValues
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:44
std::map< std::pair< unsigned int, unsigned int >, std::pair< unsigned int, bool > > Edges_by_vertices
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:39
Eigen::MatrixXd DofPositions
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:36
std::vector< std::array< unsigned int, 2 > > DofTypes
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:37
unsigned int Dimension
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:29
std::array< Eigen::MatrixXd, 4 > ReferenceBasisFunctionSecondDerivativeValues
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:46
Gedim::Quadrature::QuadratureData ReferenceSquareQuadrature
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:42
unsigned int Order
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:30
std::vector< Eigen::MatrixXd > ReferenceBasisFunctionDerivativeValues
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:45
unsigned int NumDofs2D
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:33
unsigned int NumDofs1D
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:32
Gedim::Quadrature::QuadratureData ReferenceTriangleQuadrature
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:41
unsigned int NumDofs0D
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:31
Polydim::FEM::PCC::FEM_PCC_1D_ReferenceElement_Data BoundaryReferenceElement_Data
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:48
unsigned int NumBasisFunctions
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:35
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:52
FEM_Quadrilateral_PCC_2D_ReferenceElement()
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:56
Eigen::MatrixXd Vertices
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:54
std::vector< Eigen::MatrixXd > EvaluateBasisFunctionDerivatives(const Eigen::MatrixXd &points, const Polydim::FEM::PCC::FEM_Quadrilateral_PCC_2D_ReferenceElement_Data &reference_element_data) const
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:206
std::array< Eigen::MatrixXd, 4 > EvaluateBasisFunctionSecondDerivatives(const Eigen::MatrixXd &, const Polydim::FEM::PCC::FEM_Quadrilateral_PCC_2D_ReferenceElement_Data &) const
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:239
Eigen::MatrixXd EvaluateBasisFunctions(const Eigen::MatrixXd &points, const Polydim::FEM::PCC::FEM_Quadrilateral_PCC_2D_ReferenceElement_Data &reference_element_data) const
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:179
~FEM_Quadrilateral_PCC_2D_ReferenceElement()
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:61
Polydim::FEM::PCC::FEM_Quadrilateral_PCC_2D_ReferenceElement_Data Create(const unsigned int order) const
Definition FEM_Quadrilateral_PCC_2D_ReferenceElement.hpp:63