63 {
65
66 constexpr bool calculate_diff = false;
67 constexpr bool debug =
false;
68
69
72 "Wrong base, should be USER_BASE");
73 }
74
75 EntitiesFieldData &data = this->cTx->dAta;
76
77
78 const int order = data.dataOnEntities[MBTET][0].getOrder();
79
80 const int nb_gauss_pts = pts.size2();
81
82 auto check_cache = [
this](
int order,
int nb_gauss_pts) ->
bool {
86 } else {
87 return false;
88 }
89 };
90
92 auto &
phi = data.dataOnEntities[MBTET][0].getN(
USER_BASE);
94 phi.resize(nb_gauss_pts, 9 * nb_base_functions,
false);
95 std::fill(
phi.data().begin(),
phi.data().end(), 0.0);
97 }
98
99 if (check_cache(
order, nb_gauss_pts)) {
101 auto &
phi = data.dataOnEntities[MBTET][0].getN(
USER_BASE);
102 phi.resize(mat.size1(), mat.size2(),
false);
104 if constexpr (calculate_diff) {
105 auto &diff_phi = data.dataOnEntities[MBTET][0].getDiffN(
USER_BASE);
107 diff_phi.resize(diff_mat.size1(), diff_mat.size2(), false);
108 noalias(diff_phi) = diff_mat;
109 }
110 } else {
111
112 shapeFun.resize(nb_gauss_pts, 4,
false);
114 &pts(2, 0), nb_gauss_pts);
115
116 double diff_shape_fun[12];
118
120
122 phi.resize(nb_gauss_pts, 9 * nb_base_functions,
false);
123
126
128
131 nb_gauss_pts);
132
133 auto imagingray_fd_directive = [&](auto &diff_phi) {
135
137 temp_phi.resize(nb_gauss_pts, 9 * nb_base_functions, false);
138
140 diff_shape_fun.resize(4, 3, false);
153
155 shape_fun.resize(nb_gauss_pts, 4, false);
156 for (
int dd = 0;
dd < 3; ++
dd) {
157 constexpr double eps = 1e-16;
158
159 for (auto gg = 0; gg < nb_gauss_pts; ++gg) {
160 std::array<std::complex<double>, 3> ksi{pts(0, gg), pts(1, gg),
161 pts(2, gg)};
162
163 ksi[
dd] += std::complex<double>(0,
eps);
164
165 shape_fun(gg, 0) =
N_MBTET0(ksi[0], ksi[1], ksi[2]);
166 shape_fun(gg, 1) =
N_MBTET1(ksi[0], ksi[1], ksi[2]);
167 shape_fun(gg, 2) =
N_MBTET2(ksi[0], ksi[1], ksi[2]);
168 shape_fun(gg, 3) =
N_MBTET3(ksi[0], ksi[1], ksi[2]);
169 }
170
171 auto t_complex_phi_in =
173 &temp_phi(0, 0), &temp_phi(0, 1), &temp_phi(0, 2),
174 &temp_phi(0, 3), &temp_phi(0, 4), &temp_phi(0, 5),
175 &temp_phi(0, 6), &temp_phi(0, 7), &temp_phi(0, 8)};
176
178 diff_shape_fun.data().data(),
179 t_complex_phi_in, nb_gauss_pts);
180
181 auto t_complex_phi_out =
183 &temp_phi(0, 0), &temp_phi(0, 1), &temp_phi(0, 2),
184 &temp_phi(0, 3), &temp_phi(0, 4), &temp_phi(0, 5),
185 &temp_phi(0, 6), &temp_phi(0, 7), &temp_phi(0, 8)};
186 auto t_diff_phi = getFTensor3FromPtr<3, 3, 3>(diff_phi.data().data());
187 for (auto gg = 0; gg < nb_gauss_pts; ++gg) {
188 for (auto bb = 0; bb << nb_base_functions; ++bb) {
189 t_diff_phi(0, 0, dd) = std::imag(t_complex_phi_out(0, 0)) /
eps;
190 t_diff_phi(0, 1, dd) = std::imag(t_complex_phi_out(0, 1)) /
eps;
191 t_diff_phi(0, 2, dd) = std::imag(t_complex_phi_out(0, 2)) /
eps;
192 t_diff_phi(1, 0, dd) = std::imag(t_complex_phi_out(1, 0)) /
eps;
193 t_diff_phi(1, 1, dd) = std::imag(t_complex_phi_out(1, 1)) /
eps;
194 t_diff_phi(1, 2, dd) = std::imag(t_complex_phi_out(1, 2)) /
eps;
195 t_diff_phi(2, 0, dd) = std::imag(t_complex_phi_out(2, 0)) /
eps;
196 t_diff_phi(2, 1, dd) = std::imag(t_complex_phi_out(2, 1)) /
eps;
197 t_diff_phi(2, 2, dd) = std::imag(t_complex_phi_out(2, 2)) /
eps;
200 <<
"Gauss pt " << gg <<
" direction " <<
dd
201 << " diff_phi: " << t_diff_phi(0, 0, dd) << ", "
202 << t_diff_phi(0, 1, dd) << ", " << t_diff_phi(0, 2, dd)
203 << "; " << t_diff_phi(1, 0, dd) << ", "
204 << t_diff_phi(1, 1, dd) << ", " << t_diff_phi(1, 2, dd)
205 << "; " << t_diff_phi(2, 0, dd) << ", "
206 << t_diff_phi(2, 1, dd) << ", " << t_diff_phi(2, 2, dd);
207 }
208 ++t_complex_phi_out;
209 ++t_diff_phi;
210 }
211 }
212
215 &
phi(0, 0), &
phi(0, 1), &
phi(0, 2), &
phi(0, 3), &
phi(0, 4),
217 auto t_complex_phi_out =
219 3>{
220 &temp_phi(0, 0), &temp_phi(0, 1), &temp_phi(0, 2),
221 &temp_phi(0, 3), &temp_phi(0, 4), &temp_phi(0, 5),
222 &temp_phi(0, 6), &temp_phi(0, 7), &temp_phi(0, 8)};
223
224 for (auto gg = 0; gg < nb_gauss_pts; ++gg) {
228 for (auto bb = 0; bb << nb_base_functions; ++bb) {
229 t_diff(
i,
j) = t_complex_phi_out(
i,
j) - t_phi(
i,
j);
230 auto nrm2_complex = t_diff(
i,
j) * t_diff(
i,
j);
231 if (std::abs(nrm2_complex) > 1e-12) {
233 << "Difference detected at gauss pt " << gg
234 <<
" for direction " <<
dd
235 << " nrm2 = " << std::abs(nrm2_complex);
237 "Difference detected between complex step "
238 "differentiation and real valued differentiation");
239 }
240 ++t_phi;
241 ++t_complex_phi_out;
242 }
243 }
244 }
245
246
247
248 }
249
251 };
252
254 if constexpr (calculate_diff) {
255 diff_phi.resize(nb_gauss_pts, 27 * nb_base_functions, false);
256 CHKERR imagingray_fd_directive(diff_phi);
257 }
258
264 if constexpr (calculate_diff) {
265 cachePhiPtr->get<3>().resize(diff_phi.size1(), diff_phi.size2(),
false);
267 }
268 }
269 }
270
272}
#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()
#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