v0.15.0
Loading...
Searching...
No Matches
CGGUserPolynomialBase.cpp
Go to the documentation of this file.
1/**
2 * @file CGGUserPolynomialBase.cpp
3 * @brief Implementation of CGGUserPolynomialBase class
4 *
5 */
6
8 boost::shared_ptr<CachePhi> cache_phi_otr)
9 : TetPolynomialBase(), cachePhiPtr(cache_phi_otr) {}
10
12 boost::typeindex::type_index type_index,
13 BaseFunctionUnknownInterface **iface) const {
14 *iface = const_cast<CGGUserPolynomialBase *>(this);
15 return 0;
16}
17
18MoFEMErrorCode
20 boost::shared_ptr<BaseFunctionCtx> ctx_ptr) {
22
23 this->cTx = ctx_ptr->getInterface<EntPolynomialBaseCtx>();
24
25 int nb_gauss_pts = pts.size2();
26 if (!nb_gauss_pts) {
28 }
29
30 if (pts.size1() < 3) {
31 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
32 "Wrong dimension of pts, should be at least 3 rows with "
33 "coordinates");
34 }
35
36 const auto base = this->cTx->bAse;
37 EntitiesFieldData &data = this->cTx->dAta;
38
39 switch (this->cTx->sPace) {
40 case HDIV:
42 break;
43 case L2:
44 data.dataOnEntities[MBVERTEX][0].getN(base).resize(nb_gauss_pts, 4, false);
45 CHKERR Tools::shapeFunMBTET(
46 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
47 &pts(0, 0), &pts(1, 0), &pts(2, 0), nb_gauss_pts);
48 data.dataOnEntities[MBVERTEX][0].getDiffN(base).resize(4, 3, false);
49 std::copy(Tools::diffShapeFunMBTET.begin(), Tools::diffShapeFunMBTET.end(),
50 data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin());
51 this->cTx->basePolynomialsType0 = Legendre_polynomials;
52 CHKERR getValueL2AinsworthBase(pts);
53 break;
54 default:
55 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not yet implemented");
56 }
57
59}
60
61MoFEMErrorCode
64
65 constexpr bool calculate_diff = false;
66 constexpr bool debug = false;
67
68 // This should be used only in case USER_BASE is selected
69 if (this->cTx->bAse != USER_BASE) {
70 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
71 "Wrong base, should be USER_BASE");
72 }
73 // get access to data structures on element
74 EntitiesFieldData &data = this->cTx->dAta;
75 // Get approximation order on element. Note that bubble functions are only
76 // on tetrahedron.
77 const int order = data.dataOnEntities[MBTET][0].getOrder();
78 /// number of integration points
79 const int nb_gauss_pts = pts.size2();
80
81 auto check_cache = [this](int order, int nb_gauss_pts) -> bool {
82 if (cachePhiPtr) {
83 return cachePhiPtr->get<0>() == order &&
84 cachePhiPtr->get<1>() == nb_gauss_pts;
85 } else {
86 return false;
87 }
88 };
89
90 if (check_cache(order, nb_gauss_pts)) {
91 auto &mat = cachePhiPtr->get<2>();
92 auto &phi = data.dataOnEntities[MBTET][0].getN(USER_BASE);
93 phi.resize(mat.size1(), mat.size2(), false);
94 noalias(phi) = mat;
95 if constexpr (calculate_diff) {
96 auto &diff_phi = data.dataOnEntities[MBTET][0].getDiffN(USER_BASE);
97 auto &diff_mat = cachePhiPtr->get<3>();
98 diff_phi.resize(diff_mat.size1(), diff_mat.size2(), false);
99 noalias(diff_phi) = diff_mat;
100 }
101 } else {
102 // calculate shape functions, i.e. barycentric coordinates
103 shapeFun.resize(nb_gauss_pts, 4, false);
104 CHKERR ShapeMBTET(&*shapeFun.data().begin(), &pts(0, 0), &pts(1, 0),
105 &pts(2, 0), nb_gauss_pts);
106 // derivatives of shape functions
107 double diff_shape_fun[12];
108 CHKERR ShapeDiffMBTET(diff_shape_fun);
109
110 const int nb_base_functions = NBVOLUMETET_CCG_BUBBLE(order);
111 // get base functions and set size
112 MatrixDouble &phi = data.dataOnEntities[MBTET][0].getN(USER_BASE);
113 phi.resize(nb_gauss_pts, 9 * nb_base_functions, false);
114 // finally calculate base functions
116 &phi(0, 0), &phi(0, 1), &phi(0, 2),
117
118 &phi(0, 3), &phi(0, 4), &phi(0, 5),
119
120 &phi(0, 6), &phi(0, 7), &phi(0, 8));
121 CHKERR CGG_BubbleBase_MBTET(order, &shapeFun(0, 0), diff_shape_fun, t_phi,
122 nb_gauss_pts);
123
124 auto imagingray_fd_directive = [&](auto &diff_phi) {
126
127 MatrixComplexDouble temp_phi;
128 temp_phi.resize(nb_gauss_pts, 9 * nb_base_functions, false);
129
130 MatrixComplexDouble diff_shape_fun;
131 diff_shape_fun.resize(4, 3, false);
132 diff_shape_fun(0, 0) = diffN_MBTET0x;
133 diff_shape_fun(0, 1) = diffN_MBTET0y;
134 diff_shape_fun(0, 2) = diffN_MBTET0z;
135 diff_shape_fun(1, 0) = diffN_MBTET1x;
136 diff_shape_fun(1, 1) = diffN_MBTET1y;
137 diff_shape_fun(1, 2) = diffN_MBTET1z;
138 diff_shape_fun(2, 0) = diffN_MBTET2x;
139 diff_shape_fun(2, 1) = diffN_MBTET2y;
140 diff_shape_fun(2, 2) = diffN_MBTET2z;
141 diff_shape_fun(3, 0) = diffN_MBTET3x;
142 diff_shape_fun(3, 1) = diffN_MBTET3y;
143 diff_shape_fun(3, 2) = diffN_MBTET3z;
144
145 MatrixComplexDouble shape_fun;
146 shape_fun.resize(nb_gauss_pts, 4, false);
147 for (int dd = 0; dd < 3; ++dd) {
148 constexpr double eps = 1e-16;
149
150 for (auto gg = 0; gg < nb_gauss_pts; ++gg) {
151 std::array<std::complex<double>, 3> ksi{pts(0, gg), pts(1, gg),
152 pts(2, gg)};
153
154 ksi[dd] += std::complex<double>(0, eps);
155
156 shape_fun(gg, 0) = N_MBTET0(ksi[0], ksi[1], ksi[2]);
157 shape_fun(gg, 1) = N_MBTET1(ksi[0], ksi[1], ksi[2]);
158 shape_fun(gg, 2) = N_MBTET2(ksi[0], ksi[1], ksi[2]);
159 shape_fun(gg, 3) = N_MBTET3(ksi[0], ksi[1], ksi[2]);
160 }
161
162 auto t_complex_phi_in =
164 &temp_phi(0, 0), &temp_phi(0, 1), &temp_phi(0, 2),
165 &temp_phi(0, 3), &temp_phi(0, 4), &temp_phi(0, 5),
166 &temp_phi(0, 6), &temp_phi(0, 7), &temp_phi(0, 8)};
167
168 CHKERR CGG_BubbleBase_MBTET(order, shape_fun.data().data(),
169 diff_shape_fun.data().data(),
170 t_complex_phi_in, nb_gauss_pts);
171
172 auto t_complex_phi_out =
174 &temp_phi(0, 0), &temp_phi(0, 1), &temp_phi(0, 2),
175 &temp_phi(0, 3), &temp_phi(0, 4), &temp_phi(0, 5),
176 &temp_phi(0, 6), &temp_phi(0, 7), &temp_phi(0, 8)};
177 auto t_diff_phi = getFTensor3FromPtr<3, 3, 3>(diff_phi.data().data());
178 for (auto gg = 0; gg < nb_gauss_pts; ++gg) {
179 for (auto bb = 0; bb << nb_base_functions; ++bb) {
180 t_diff_phi(0, 0, dd) = std::imag(t_complex_phi_out(0, 0)) / eps;
181 t_diff_phi(0, 1, dd) = std::imag(t_complex_phi_out(0, 1)) / eps;
182 t_diff_phi(0, 2, dd) = std::imag(t_complex_phi_out(0, 2)) / eps;
183 t_diff_phi(1, 0, dd) = std::imag(t_complex_phi_out(1, 0)) / eps;
184 t_diff_phi(1, 1, dd) = std::imag(t_complex_phi_out(1, 1)) / eps;
185 t_diff_phi(1, 2, dd) = std::imag(t_complex_phi_out(1, 2)) / eps;
186 t_diff_phi(2, 0, dd) = std::imag(t_complex_phi_out(2, 0)) / eps;
187 t_diff_phi(2, 1, dd) = std::imag(t_complex_phi_out(2, 1)) / eps;
188 t_diff_phi(2, 2, dd) = std::imag(t_complex_phi_out(2, 2)) / eps;
189 if (debug) {
190 MOFEM_LOG("SELF", Sev::noisy)
191 << "Gauss pt " << gg << " direction " << dd
192 << " diff_phi: " << t_diff_phi(0, 0, dd) << ", "
193 << t_diff_phi(0, 1, dd) << ", " << t_diff_phi(0, 2, dd)
194 << "; " << t_diff_phi(1, 0, dd) << ", "
195 << t_diff_phi(1, 1, dd) << ", " << t_diff_phi(1, 2, dd)
196 << "; " << t_diff_phi(2, 0, dd) << ", "
197 << t_diff_phi(2, 1, dd) << ", " << t_diff_phi(2, 2, dd);
198 }
199 ++t_complex_phi_out;
200 ++t_diff_phi;
201 }
202 }
203
204 if (debug) {
206 &phi(0, 0), &phi(0, 1), &phi(0, 2), &phi(0, 3), &phi(0, 4),
207 &phi(0, 5), &phi(0, 6), &phi(0, 7), &phi(0, 8)};
208 auto t_complex_phi_out =
210 3>{
211 &temp_phi(0, 0), &temp_phi(0, 1), &temp_phi(0, 2),
212 &temp_phi(0, 3), &temp_phi(0, 4), &temp_phi(0, 5),
213 &temp_phi(0, 6), &temp_phi(0, 7), &temp_phi(0, 8)};
214
215 for (auto gg = 0; gg < nb_gauss_pts; ++gg) {
216 FTensor::Index<'i', 3> i;
217 FTensor::Index<'j', 3> j;
219 for (auto bb = 0; bb << nb_base_functions; ++bb) {
220 t_diff(i, j) = t_complex_phi_out(i, j) - t_phi(i, j);
221 auto nrm2_complex = t_diff(i, j) * t_diff(i, j);
222 if (std::abs(nrm2_complex) > 1e-12) {
223 MOFEM_LOG("SELF", Sev::warning)
224 << "Difference detected at gauss pt " << gg
225 << " for direction " << dd
226 << " nrm2 = " << std::abs(nrm2_complex);
227 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
228 "Difference detected between complex step "
229 "differentiation and real valued differentiation");
230 }
231 ++t_phi;
232 ++t_complex_phi_out;
233 }
234 }
235 }
236
237
238
239 }
240
242 };
243
244 MatrixDouble &diff_phi = data.dataOnEntities[MBTET][0].getDiffN(USER_BASE);
245 if constexpr (calculate_diff) {
246 diff_phi.resize(nb_gauss_pts, 27 * nb_base_functions, false);
247 CHKERR imagingray_fd_directive(diff_phi);
248 }
249
250 if (cachePhiPtr) {
251 cachePhiPtr->get<0>() = order;
252 cachePhiPtr->get<1>() = nb_gauss_pts;
253 cachePhiPtr->get<2>().resize(phi.size1(), phi.size2(), false);
254 noalias(cachePhiPtr->get<2>()) = phi;
255 if constexpr (calculate_diff) {
256 cachePhiPtr->get<3>().resize(diff_phi.size1(), diff_phi.size2(), false);
257 noalias(cachePhiPtr->get<3>()) = diff_phi;
258 }
259 }
260 }
261
263}
#define NBVOLUMETET_CCG_BUBBLE(P)
Bubble function for CGG H div space.
static const double eps
@ USER_BASE
user implemented approximation base
Definition definitions.h:68
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ L2
field with C-1 continuity
Definition definitions.h:88
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
constexpr int order
static const bool debug
#define diffN_MBTET0z
derivative of tetrahedral shape function
Definition fem_tools.h:34
#define N_MBTET0(x, y, z)
tetrahedral shape function
Definition fem_tools.h:28
PetscErrorCode ShapeDiffMBTET(double *diffN)
calculate derivatives of shape functions
Definition fem_tools.c:319
#define N_MBTET1(x, y, z)
tetrahedral shape function
Definition fem_tools.h:29
#define diffN_MBTET2z
derivative of tetrahedral shape function
Definition fem_tools.h:40
#define diffN_MBTET3y
derivative of tetrahedral shape function
Definition fem_tools.h:42
#define diffN_MBTET0y
derivative of tetrahedral shape function
Definition fem_tools.h:33
#define diffN_MBTET1z
derivative of tetrahedral shape function
Definition fem_tools.h:37
#define diffN_MBTET3z
derivative of tetrahedral shape function
Definition fem_tools.h:43
PetscErrorCode ShapeMBTET(double *N, const double *G_X, const double *G_Y, const double *G_Z, int DIM)
calculate shape functions
Definition fem_tools.c:306
#define diffN_MBTET1y
derivative of tetrahedral shape function
Definition fem_tools.h:36
#define diffN_MBTET2y
derivative of tetrahedral shape function
Definition fem_tools.h:39
#define diffN_MBTET2x
derivative of tetrahedral shape function
Definition fem_tools.h:38
#define N_MBTET2(x, y, z)
tetrahedral shape function
Definition fem_tools.h:30
#define diffN_MBTET3x
derivative of tetrahedral shape function
Definition fem_tools.h:41
#define diffN_MBTET1x
derivative of tetrahedral shape function
Definition fem_tools.h:35
#define diffN_MBTET0x
derivative of tetrahedral shape function
Definition fem_tools.h:32
#define N_MBTET3(x, y, z)
tetrahedral shape function
Definition fem_tools.h:31
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
static double phi
CGG User Polynomial Base.
MoFEMErrorCode getValueHdivForCGGBubble(MatrixDouble &pts)
CGGUserPolynomialBase(boost::shared_ptr< CachePhi > cache_phi=nullptr)
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, BaseFunctionUnknownInterface **iface) const
boost::shared_ptr< CachePhi > cachePhiPtr
MoFEMErrorCode getValue(MatrixDouble &pts, boost::shared_ptr< BaseFunctionCtx > ctx_ptr)