PolyDiM
C++ library for POLYtopal DIscretization Methods
Loading...
Searching...
No Matches
VEM_MCC_Utilities.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 __VEM_MCC_Utilities_HPP
13#define __VEM_MCC_Utilities_HPP
14
15#include "CommonUtilities.hpp"
16#include "Eigen/Eigen"
17
18namespace Polydim
19{
20namespace VEM
21{
22namespace MCC
23{
24enum struct ProjectionTypes
25{
26 Pi0k = 1,
27};
28
30{
31 Eigen::MatrixXd ComputePolynomialBasisDofs(const unsigned int dimension,
32 const double &polytopeMeasure,
33 const unsigned int &order,
34 const unsigned int &Nk,
35 const unsigned int &NumBoundaryBasisFunctions,
36 const unsigned int &NumNablaInternalBasisFunctions,
37 const unsigned int &NumBigOPlusInternalBasisFunctions,
38 const unsigned int &NumBasisFunctions,
39 const Eigen::MatrixXd &GkVanderBoundaryTimesNormal,
40 const Eigen::MatrixXd &Gmatrix) const
41 {
42 Eigen::MatrixXd polynomialBasisDofs = Eigen::MatrixXd::Zero(NumBasisFunctions, dimension * Nk);
43
44 polynomialBasisDofs.topRows(NumBoundaryBasisFunctions) = GkVanderBoundaryTimesNormal;
45
46 if (order > 0)
47 {
48 polynomialBasisDofs.block(NumBoundaryBasisFunctions, 0, NumNablaInternalBasisFunctions, dimension * Nk) =
49 (1.0 / polytopeMeasure) * Gmatrix.topRows(NumNablaInternalBasisFunctions);
50
51 polynomialBasisDofs.bottomRows(NumBigOPlusInternalBasisFunctions) =
52 (1.0 / polytopeMeasure) * Gmatrix.bottomRows(NumBigOPlusInternalBasisFunctions);
53 }
54 return polynomialBasisDofs;
55 }
56
57 Eigen::MatrixXd ComputeDofiDofiStabilizationMatrix(const Eigen::MatrixXd &projector,
58 const double &coefficient,
59 const Eigen::MatrixXd &DMatrix) const
60 {
61 Eigen::MatrixXd stabMatrixPi0k = DMatrix * projector;
62 stabMatrixPi0k.diagonal().array() -= 1;
63 // stabMatrix = (\Pi^{0,dofs}_order - I)^T * (\Pi^{0,dofs}_order - I).
64 stabMatrixPi0k = coefficient * stabMatrixPi0k.transpose() * stabMatrixPi0k;
65
66 return stabMatrixPi0k;
67 }
68
69 void MonomialTraceOnEdges(const unsigned int &polynomialDegree,
70 const Eigen::MatrixXd &polygonVertices,
71 const double &polygonDiameter,
72 const Eigen::Vector3d &polygonCentroid,
73 const std::vector<bool> &edgeDirections,
74 const Eigen::MatrixXd &edgeTangents,
75 std::vector<Eigen::MatrixXd> &Cmatrixkp1) const
76 {
77 std::vector<Eigen::VectorXd> BinomialCoefficients(polynomialDegree + 2);
78
79 for (unsigned int n = 0; n <= (polynomialDegree + 1); n++)
80 {
81 BinomialCoefficients[n].resize(n + 2);
82 for (unsigned int k = 0; k <= n; k++)
83 {
84 BinomialCoefficients[n][k] = Gedim::Utilities::BinomialCoefficient(n, k);
85 }
86 }
87
88 const unsigned int numVertices = polygonVertices.cols();
89 const unsigned int numEdges = numVertices;
90
91 const unsigned int order_1D = (polynomialDegree + 2);
92 const unsigned int nkp1 = (polynomialDegree + 2) * (polynomialDegree + 3) / 2;
93
94 Cmatrixkp1.resize(numEdges);
95
96 for (unsigned int e = 0; e < numEdges; ++e)
97 {
98 Cmatrixkp1[e] = Eigen::MatrixXd::Zero(nkp1, order_1D);
99
100 const Eigen::Vector3d &edgeStart = edgeDirections[e] ? polygonVertices.col(e)
101 : polygonVertices.col((e + 1) % numVertices);
102 const Eigen::Vector3d &edgeTangent = edgeTangents.col(e);
103 const double direction = edgeDirections[e] ? 1.0 : -1.0;
104
105 double invDiameter = 1.0 / polygonDiameter;
106 double XAminusXC = edgeStart(0) - polygonCentroid(0);
107 double YAminusYC = edgeStart(1) - polygonCentroid(1);
108 double X = XAminusXC * invDiameter;
109 double Y = YAminusYC * invDiameter;
110 double diffX = direction * edgeTangent(0) / XAminusXC;
111 double diffY = direction * edgeTangent(1) / YAminusYC;
112
113 if (abs(XAminusXC) > 1.0e-12 && abs(YAminusYC) > 1.0e-12)
114 {
115 Eigen::VectorXd vettX = Eigen::VectorXd::Ones(polynomialDegree + 2); // ((xa - xc)/diam)^{alphax}
116 Eigen::VectorXd vettY = Eigen::VectorXd::Ones(polynomialDegree + 2); // ((ya - yc)/diam)^{alphay}
117 Eigen::VectorXd vettDiffX = Eigen::VectorXd::Ones(polynomialDegree + 2);
118 Eigen::VectorXd vettDiffY = Eigen::VectorXd::Ones(polynomialDegree + 2);
119
120 for (unsigned int i = 0; i < (polynomialDegree + 1); i++)
121 {
122 vettX[i + 1] = vettX[i] * X;
123 vettY[i + 1] = vettY[i] * Y;
124 vettDiffX[i + 1] = vettDiffX[i] * diffX;
125 vettDiffY[i + 1] = vettDiffY[i] * diffY;
126 }
127
128 Cmatrixkp1[e](0, 0) = 1.0;
129 unsigned int offsetRow = 1;
130
131 for (unsigned int N = 1; N <= (polynomialDegree + 1); N++)
132 {
133 for (unsigned int alphay = 0; alphay <= N; alphay++)
134 {
135 for (unsigned int j = 0; j <= alphay; j++)
136 {
137 for (unsigned int i = 0; i <= (N - alphay); i++)
138 {
139 Cmatrixkp1[e](offsetRow, (j + i)) = Cmatrixkp1[e](offsetRow, (j + i)) +
140 BinomialCoefficients[N - alphay][i] * vettDiffX[i] *
141 BinomialCoefficients[alphay][j] * vettDiffY[j];
142 }
143 }
144 Cmatrixkp1[e].block(offsetRow, 0, 1, order_1D) =
145 Cmatrixkp1[e].block(offsetRow, 0, 1, order_1D) * vettX[N - alphay] * vettY[alphay];
146 offsetRow++;
147 }
148 }
149 }
150 else if (abs(XAminusXC) > 1.0e-12 && abs(YAminusYC) <= 1.0e-12)
151 {
152 Eigen::VectorXd vettX = Eigen::VectorXd::Ones(polynomialDegree + 2); // ((xa - xc)/diam)^{alphax}
153 Eigen::VectorXd vettY = Eigen::VectorXd::Ones(polynomialDegree + 2); // ((yB - yA)/diam)^{alphay}
154 Eigen::VectorXd vettDiffX = Eigen::VectorXd::Ones(polynomialDegree + 2);
155
156 double YBminusYAForInvDiameter = direction * edgeTangent(1) * invDiameter;
157
158 for (unsigned int i = 0; i < (polynomialDegree + 1); i++)
159 {
160 vettX[i + 1] = vettX[i] * X;
161 vettY[i + 1] = vettY[i] * YBminusYAForInvDiameter;
162 vettDiffX[i + 1] = vettDiffX[i] * diffX;
163 }
164
165 Cmatrixkp1[e](0, 0) = 1.0;
166 unsigned int offsetRow = 1;
167
168 for (unsigned int N = 1; N <= (polynomialDegree + 1); N++)
169 {
170 for (unsigned int alphay = 0; alphay <= N; alphay++)
171 {
172 unsigned int j = alphay;
173 for (unsigned int i = 0; i <= (N - alphay); i++)
174 {
175 Cmatrixkp1[e](offsetRow, (j + i)) =
176 Cmatrixkp1[e](offsetRow, (j + i)) + BinomialCoefficients[N - alphay][i] * vettDiffX[i];
177 }
178
179 Cmatrixkp1[e].block(offsetRow, 0, 1, order_1D) =
180 Cmatrixkp1[e].block(offsetRow, 0, 1, order_1D) * vettX[N - alphay] * vettY[alphay];
181 offsetRow++;
182 }
183 }
184 }
185 else if (abs(XAminusXC) <= 1.0e-12 && abs(YAminusYC) > 1.0e-12)
186 {
187 Eigen::VectorXd vettX = Eigen::VectorXd::Ones(polynomialDegree + 2); // ((xB - xA)/diam)^{alphax}
188 Eigen::VectorXd vettY = Eigen::VectorXd::Ones(polynomialDegree + 2); // ((ya - yc)/diam)^{alphay}
189 Eigen::VectorXd vettDiffY = Eigen::VectorXd::Ones(polynomialDegree + 2);
190
191 double XBminusXAForInvDiameter = direction * edgeTangent(0) * invDiameter;
192
193 for (unsigned int i = 0; i < (polynomialDegree + 1); i++)
194 {
195 vettX[i + 1] = vettX[i] * XBminusXAForInvDiameter;
196 vettY[i + 1] = vettY[i] * Y;
197 vettDiffY[i + 1] = vettDiffY[i] * diffY;
198 }
199
200 Cmatrixkp1[e](0, 0) = 1.0;
201 unsigned int offsetRow = 1;
202
203 for (unsigned int N = 1; N <= (polynomialDegree + 1); N++)
204 {
205 for (unsigned int alphay = 0; alphay <= N; alphay++)
206 {
207 for (unsigned int j = 0; j <= alphay; j++)
208 {
209 unsigned int i = N - alphay;
210 Cmatrixkp1[e](offsetRow, (j + i)) =
211 Cmatrixkp1[e](offsetRow, (j + i)) + BinomialCoefficients[alphay][j] * vettDiffY[j];
212 }
213 Cmatrixkp1[e].block(offsetRow, 0, 1, order_1D) =
214 Cmatrixkp1[e].block(offsetRow, 0, 1, order_1D) * vettX[N - alphay] * vettY[alphay];
215 offsetRow++;
216 }
217 }
218 }
219 else
220 {
221 throw std::runtime_error("Cmatrix is wrong");
222 }
223 }
224 }
225
226 std::vector<Eigen::MatrixXd> ComputeBasisFunctionsValues(const unsigned int dimension,
227 const Eigen::MatrixXd &projector,
228 const Eigen::MatrixXd &GVander) const
229 {
230 const unsigned int numQuadrature = GVander.cols() / dimension;
231 const Eigen::MatrixXd temp = GVander.transpose() * projector;
232 std::vector<Eigen::MatrixXd> result(dimension, Eigen::MatrixXd::Zero(dimension, projector.cols()));
233
234 for (unsigned int d = 0; d < dimension; d++)
235 result[d] = temp.middleRows(numQuadrature * d, numQuadrature);
236
237 return result;
238 }
239};
240} // namespace MCC
241} // namespace VEM
242} // namespace Polydim
243
244#endif
static double BinomialCoefficient(const unsigned int &n, const unsigned int &k)
Compute the binomial coefficient (n k)
Definition CommonUtilities.hpp:84
ProjectionTypes
Definition VEM_MCC_Utilities.hpp:25
Definition FEM_MCC_2D_LocalSpace.cpp:17
Definition VEM_MCC_Utilities.hpp:30
void MonomialTraceOnEdges(const unsigned int &polynomialDegree, const Eigen::MatrixXd &polygonVertices, const double &polygonDiameter, const Eigen::Vector3d &polygonCentroid, const std::vector< bool > &edgeDirections, const Eigen::MatrixXd &edgeTangents, std::vector< Eigen::MatrixXd > &Cmatrixkp1) const
Definition VEM_MCC_Utilities.hpp:69
Eigen::MatrixXd ComputePolynomialBasisDofs(const unsigned int dimension, const double &polytopeMeasure, const unsigned int &order, const unsigned int &Nk, const unsigned int &NumBoundaryBasisFunctions, const unsigned int &NumNablaInternalBasisFunctions, const unsigned int &NumBigOPlusInternalBasisFunctions, const unsigned int &NumBasisFunctions, const Eigen::MatrixXd &GkVanderBoundaryTimesNormal, const Eigen::MatrixXd &Gmatrix) const
Definition VEM_MCC_Utilities.hpp:31
std::vector< Eigen::MatrixXd > ComputeBasisFunctionsValues(const unsigned int dimension, const Eigen::MatrixXd &projector, const Eigen::MatrixXd &GVander) const
Definition VEM_MCC_Utilities.hpp:226
Eigen::MatrixXd ComputeDofiDofiStabilizationMatrix(const Eigen::MatrixXd &projector, const double &coefficient, const Eigen::MatrixXd &DMatrix) const
Definition VEM_MCC_Utilities.hpp:57