62 {
64
65 constexpr bool calculate_diff = false;
66 constexpr bool debug =
false;
67
68
71 "Wrong base, should be USER_BASE");
72 }
73
74 EntitiesFieldData &data = this->cTx->dAta;
75
76
77 const int order = data.dataOnEntities[MBTET][0].getOrder();
78
79 const int nb_gauss_pts = pts.size2();
80
81 auto check_cache = [
this](
int order,
int nb_gauss_pts) ->
bool {
85 } else {
86 return false;
87 }
88 };
89
90 if (check_cache(
order, nb_gauss_pts)) {
92 auto &
phi = data.dataOnEntities[MBTET][0].getN(
USER_BASE);
93 phi.resize(mat.size1(), mat.size2(),
false);
95 if constexpr (calculate_diff) {
96 auto &diff_phi = data.dataOnEntities[MBTET][0].getDiffN(
USER_BASE);
98 diff_phi.resize(diff_mat.size1(), diff_mat.size2(), false);
99 noalias(diff_phi) = diff_mat;
100 }
101 } else {
102
103 shapeFun.resize(nb_gauss_pts, 4,
false);
105 &pts(2, 0), nb_gauss_pts);
106
107 double diff_shape_fun[12];
109
111
113 phi.resize(nb_gauss_pts, 9 * nb_base_functions,
false);
114
117
119
122 nb_gauss_pts);
123
124 auto imagingray_fd_directive = [&](auto &diff_phi) {
126
128 temp_phi.resize(nb_gauss_pts, 9 * nb_base_functions, false);
129
131 diff_shape_fun.resize(4, 3, false);
144
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
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;
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
206 &
phi(0, 0), &
phi(0, 1), &
phi(0, 2), &
phi(0, 3), &
phi(0, 4),
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) {
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) {
224 << "Difference detected at gauss pt " << gg
225 <<
" for direction " <<
dd
226 << " nrm2 = " << std::abs(nrm2_complex);
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
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
255 if constexpr (calculate_diff) {
256 cachePhiPtr->get<3>().resize(diff_phi.size1(), diff_phi.size2(),
false);
258 }
259 }
260 }
261
263}
#define NBVOLUMETET_CCG_BUBBLE(P)
Bubble function for CGG H div space.
@ USER_BASE
user implemented approximation base
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
constexpr int order
Order displacement.
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
MoFEMErrorCode CGG_BubbleBase_MBTET(const int p, const double *N, const double *diffN, FTensor::Tensor2< FTensor::PackPtr< double *, 9 >, 3, 3 > &phi, const int gdim)
Calculate CGGT tonsorial bubble base.
const Tensor2_symmetric_Expr< const ddTensor0< T, Dim, i, j >, typename promote< T, double >::V, Dim, i, j > dd(const Tensor0< T * > &a, const Index< i, Dim > index1, const Index< j, Dim > index2, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
UBlasMatrix< std::complex< double > > MatrixComplexDouble
UBlasMatrix< double > MatrixDouble