v0.15.5
Loading...
Searching...
No Matches
EshelbianOperators.cpp
Go to the documentation of this file.
1/**
2 * \file EshelbianOperators.cpp
3 * \example mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianOperators.cpp
4 *
5 * \brief Implementation of operators
6 */
7
8#include <MoFEM.hpp>
9using namespace MoFEM;
10
12
13#include <boost/math/constants/constants.hpp>
14
15#include <EshelbianAux.hpp>
16
17#include <lapack_wrap.h>
18
19#include <Lie.hpp>
20#include <MatrixFunction.hpp>
21
22#ifdef ENABLE_PYTHON_BINDING
23#include <boost/python.hpp>
24#include <boost/python/def.hpp>
25#include <boost/python/numpy.hpp>
26namespace bp = boost::python;
27namespace np = boost::python::numpy;
28#endif
29
30namespace EshelbianPlasticity {
31
32MoFEMErrorCode OpCalculateEshelbyStress::doWork(int side, EntityType type,
33 EntData &data) {
38
39 int nb_integration_pts = getGaussPts().size2();
40
41 auto t_P = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->approxPAtPts);
42 auto t_F = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->hAtPts);
43 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
44
45 dataAtPts->SigmaAtPts.resize(SPACE_DIM * SPACE_DIM, nb_integration_pts,
46 false);
47 auto t_eshelby_stress =
48 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->SigmaAtPts);
49
51
52 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
53 t_eshelby_stress(i, j) = t_energy * t_kd(i, j) - t_F(m, i) * t_P(m, j);
54 ++t_energy;
55 ++t_P;
56 ++t_F;
57 ++t_eshelby_stress;
58 }
59
61}
62
64 EntityType type,
65 EntData &data) {
67
68 auto ts_ctx = getTSCtx();
69 int nb_integration_pts = getGaussPts().size2();
70
71 // space size indices
79
80 // sym size indices
82
83 auto t_L = symm_L_tensor();
84
85 dataAtPts->hAtPts.resize(9, nb_integration_pts, false);
86 dataAtPts->hdOmegaAtPts.resize(9 * 3, nb_integration_pts, false);
87 dataAtPts->hdLogStretchAtPts.resize(9 * 6, nb_integration_pts, false);
88
89 dataAtPts->leviKirchhoffAtPts.resize(3, nb_integration_pts, false);
90 dataAtPts->leviKirchhoffdOmegaAtPts.resize(9, nb_integration_pts, false);
91 dataAtPts->leviKirchhoffdLogStreatchAtPts.resize(3 * size_symm,
92 nb_integration_pts, false);
93 dataAtPts->leviKirchhoffPAtPts.resize(9 * 3, nb_integration_pts, false);
94
95 dataAtPts->adjointPdstretchAtPts.resize(9, nb_integration_pts, false);
96 dataAtPts->adjointPdUAtPts.resize(size_symm, nb_integration_pts, false);
97 dataAtPts->adjointPdUdPAtPts.resize(9 * size_symm, nb_integration_pts, false);
98 dataAtPts->adjointPdUdOmegaAtPts.resize(3 * size_symm, nb_integration_pts,
99 false);
100 dataAtPts->rotMatAtPts.resize(9, nb_integration_pts, false);
101 dataAtPts->stretchTensorAtPts.resize(6, nb_integration_pts, false);
102 dataAtPts->diffStretchTensorAtPts.resize(36, nb_integration_pts, false);
103 dataAtPts->eigenVals.resize(3, nb_integration_pts, false);
104 dataAtPts->eigenVecs.resize(9, nb_integration_pts, false);
105 dataAtPts->nbUniq.resize(nb_integration_pts, false);
106 dataAtPts->eigenValsC.resize(3, nb_integration_pts, false);
107 dataAtPts->eigenVecsC.resize(9, nb_integration_pts, false);
108 dataAtPts->nbUniqC.resize(nb_integration_pts, false);
109
110 dataAtPts->logStretch2H1AtPts.resize(6, nb_integration_pts, false);
111 dataAtPts->logStretchTotalTensorAtPts.resize(6, nb_integration_pts, false);
112
113 dataAtPts->internalStressAtPts.resize(9, nb_integration_pts, false);
114 dataAtPts->internalStressAtPts.clear();
115
116 // Calculated values
117 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
118 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
119 auto t_h_dlog_u =
120 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->hdLogStretchAtPts);
121 auto t_levi_kirchhoff = getFTensor1FromMat<3>(dataAtPts->leviKirchhoffAtPts);
122 auto t_levi_kirchhoff_domega =
123 getFTensor2FromMat<3, 3>(dataAtPts->leviKirchhoffdOmegaAtPts);
124 auto t_levi_kirchhoff_dstreach = getFTensor2FromMat<3, size_symm>(
125 dataAtPts->leviKirchhoffdLogStreatchAtPts);
126 auto t_levi_kirchhoff_dP =
127 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
128 auto t_approx_P_adjoint__dstretch =
129 getFTensor2FromMat<3, 3>(dataAtPts->adjointPdstretchAtPts);
130 auto t_approx_P_adjoint_log_du =
131 getFTensor1FromMat<size_symm>(dataAtPts->adjointPdUAtPts);
132 auto t_approx_P_adjoint_log_du_dP =
133 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
134 auto t_approx_P_adjoint_log_du_domega =
135 getFTensor2FromMat<3, size_symm>(dataAtPts->adjointPdUdOmegaAtPts);
136 auto t_R = getFTensor2FromMat<3, 3>(dataAtPts->rotMatAtPts);
137 auto t_u = getFTensor2SymmetricFromMat<3>(dataAtPts->stretchTensorAtPts);
138 auto t_diff_u =
139 getFTensor4DdgFromMat<3, 3, 1>(dataAtPts->diffStretchTensorAtPts);
140 auto t_eigen_vals = getFTensor1FromMat<3>(dataAtPts->eigenVals);
141 auto t_eigen_vecs = getFTensor2FromMat<3, 3>(dataAtPts->eigenVecs);
142 auto &nbUniq = dataAtPts->nbUniq;
143 auto t_nb_uniq =
144 FTensor::Tensor0<FTensor::PackPtr<int *, 1>>(nbUniq.data().data());
145 auto t_eigen_vals_C = getFTensor1FromMat<3>(dataAtPts->eigenValsC);
146 auto t_eigen_vecs_C = getFTensor2FromMat<3, 3>(dataAtPts->eigenVecsC);
147 auto &nbUniqC = dataAtPts->nbUniqC;
148 auto t_nb_uniq_C =
149 FTensor::Tensor0<FTensor::PackPtr<int *, 1>>(nbUniqC.data().data());
150
151 auto t_log_stretch_total =
152 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchTotalTensorAtPts);
153 auto t_log_u2_h1 =
154 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretch2H1AtPts);
155
156 // Field values
157 auto t_grad_h1 = getFTensor2FromMat<3, 3>(dataAtPts->wGradH1AtPts);
158 auto t_omega = getFTensor1FromMat<3>(dataAtPts->rotAxisAtPts);
159 auto t_approx_P = getFTensor2FromMat<3, 3>(dataAtPts->approxPAtPts);
160 auto t_log_u =
161 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchTensorAtPts);
162
163 auto next = [&]() {
164 // calculated values
165 ++t_h;
166 ++t_h_domega;
167 ++t_h_dlog_u;
168 ++t_levi_kirchhoff;
169 ++t_levi_kirchhoff_domega;
170 ++t_levi_kirchhoff_dstreach;
171 ++t_levi_kirchhoff_dP;
172 ++t_approx_P_adjoint__dstretch;
173 ++t_approx_P_adjoint_log_du;
174 ++t_approx_P_adjoint_log_du_dP;
175 ++t_approx_P_adjoint_log_du_domega;
176 ++t_R;
177 ++t_u;
178 ++t_diff_u;
179 ++t_eigen_vals;
180 ++t_eigen_vecs;
181 ++t_nb_uniq;
182 ++t_eigen_vals_C;
183 ++t_eigen_vecs_C;
184 ++t_nb_uniq_C;
185 ++t_log_u2_h1;
186 ++t_log_stretch_total;
187 // field values
188 ++t_omega;
189 ++t_grad_h1;
190 ++t_approx_P;
191 ++t_log_u;
192 };
193
196
197 auto bound_eig = [&](auto &eig) {
199 const auto zero = std::exp(std::numeric_limits<double>::min_exponent);
200 const auto large = std::exp(std::numeric_limits<double>::max_exponent);
201 for (int ii = 0; ii != 3; ++ii) {
202 eig(ii) = std::min(std::max(zero, eig(ii)), large);
203 }
205 };
206
207 auto calculate_log_stretch = [&]() {
210 eigen_vec(i, j) = t_log_u(i, j);
211 if (computeEigenValuesSymmetric(eigen_vec, eig) != MB_SUCCESS) {
212 MOFEM_LOG("SELF", Sev::error) << "Failed to compute eigen values";
213 }
214 // CHKERR bound_eig(eig);
215 // rare case when two eigen values are equal
216 t_nb_uniq = get_uniq_nb<3>(&eig(0));
217 if (t_nb_uniq < 3) {
218 sort_eigen_vals(eig, eigen_vec);
219 }
220 t_eigen_vals(i) = eig(i);
221 t_eigen_vecs(i, j) = eigen_vec(i, j);
222 t_u(i, j) =
223 EigenMatrix::getMat(t_eigen_vals, t_eigen_vecs, EshelbianCore::f)(i, j);
224 auto get_t_diff_u = [&]() {
225 return EigenMatrix::getDiffMat(t_eigen_vals, t_eigen_vecs,
227 t_nb_uniq);
228 };
229 t_diff_u(i, j, k, l) = get_t_diff_u()(i, j, k, l);
231 t_Ldiff_u(i, j, L) = t_diff_u(i, j, m, n) * t_L(m, n, L);
232 return t_Ldiff_u;
233 };
234
235 auto calculate_total_stretch = [&](auto &t_h1) {
237
238 t_log_u2_h1(i, j) = 0;
239 t_log_stretch_total(i, j) = t_log_u(i, j);
240
243 t_R_h1(i, j) = t_kd(i, j);
244 t_inv_u_h1(i, j) = t_symm_kd(i, j);
245
246 return std::make_pair(t_R_h1, t_inv_u_h1);
247
248 } else {
249
252
254 t_C_h1(i, j) = t_h1(k, i) * t_h1(k, j);
255 eigen_vec(i, j) = t_C_h1(i, j);
256 if (computeEigenValuesSymmetric(eigen_vec, eig) != MB_SUCCESS) {
257 MOFEM_LOG("SELF", Sev::error) << "Failed to compute eigen values";
258 }
259 // rare case when two eigen values are equal
260 t_nb_uniq_C = get_uniq_nb<3>(&eig(0));
261 if (t_nb_uniq_C < 3) {
262 sort_eigen_vals(eig, eigen_vec);
263 }
265 CHKERR bound_eig(eig);
266 }
267 t_eigen_vals_C(i) = eig(i);
268 t_eigen_vecs_C(i, j) = eigen_vec(i, j);
269
270 t_log_u2_h1(i, j) =
271 EigenMatrix::getMat(eig, eigen_vec, EshelbianCore::inv_f)(i, j);
272 t_log_stretch_total(i, j) = t_log_u2_h1(i, j) / 2 + t_log_u(i, j);
273
274 auto f_inv_sqrt = [](auto e) { return 1. / std::sqrt(e); };
276 t_inv_u_h1(i, j) = EigenMatrix::getMat(eig, eigen_vec, f_inv_sqrt)(i, j);
278 t_R_h1(i, j) = t_h1(i, o) * t_inv_u_h1(o, j);
279
280 return std::make_pair(t_R_h1, t_inv_u_h1);
281 }
282 };
283
284 auto no_h1_loop = [&]() {
286
288 case LARGE_ROT:
289 break;
290 case SMALL_ROT:
291 break;
292 default:
293 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
294 "rotSelector should be large");
295 };
296
297 for (int gg = 0; gg != nb_integration_pts; ++gg) {
298
300
302 t_h1(i, j) = t_kd(i, j);
303
304 // calculate streach
305 auto t_Ldiff_u = calculate_log_stretch();
306
307 // calculate total stretch
308 auto [t_R_h1, t_inv_u_h1] = calculate_total_stretch(t_h1);
309
314
316
317 // rotation
319 case LARGE_ROT:
320 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
321 t_diff_R(i, j, k) =
322 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
323 // left
324 t_diff_Rr(i, j, l) = t_R(i, k) * levi_civita(k, j, l);
325 t_diff_diff_Rr(i, j, l, m) = t_diff_R(i, k, m) * levi_civita(k, j, l);
326 // right
327 t_diff_Rl(i, j, l) = levi_civita(i, k, l) * t_R(k, j);
328 t_diff_diff_Rl(i, j, l, m) = levi_civita(i, k, l) * t_diff_R(k, j, m);
329 break;
330
331 default:
332 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
333 "rotationSelector not handled");
334 }
335
336 constexpr double half_r = 1 / 2.;
337 constexpr double half_l = 1 / 2.;
338
339 // calculate gradient
340 t_h(i, k) = t_R(i, l) * t_u(l, k);
341
342 // Adjoint stress
343 t_approx_P_adjoint__dstretch(l, k) =
344 (t_R(i, l) * t_approx_P(i, k) + t_R(i, k) * t_approx_P(i, l));
345 t_approx_P_adjoint__dstretch(l, k) /= 2.;
346
347 t_approx_P_adjoint_log_du(L) =
348 (t_approx_P_adjoint__dstretch(l, k) * t_Ldiff_u(l, k, L) +
349 t_approx_P_adjoint__dstretch(k, l) * t_Ldiff_u(l, k, L) +
350 t_approx_P_adjoint__dstretch(l, k) * t_Ldiff_u(k, l, L) +
351 t_approx_P_adjoint__dstretch(k, l) * t_Ldiff_u(k, l, L)) /
352 4.;
353
354 // Kirchhoff stress
355 t_levi_kirchhoff(m) =
356
357 half_r * (t_diff_Rr(i, l, m) * (t_u(l, k) * t_approx_P(i, k)) +
358 t_diff_Rr(i, k, m) * (t_u(l, k) * t_approx_P(i, l)))
359
360 +
361
362 half_l * (t_diff_Rl(i, l, m) * (t_u(l, k) * t_approx_P(i, k)) +
363 t_diff_Rl(i, k, m) * (t_u(l, k) * t_approx_P(i, l)));
364 t_levi_kirchhoff(m) /= 2.;
365
367
369 t_h_domega(i, k, m) = half_r * (t_diff_Rr(i, l, m) * t_u(l, k))
370
371 +
372
373 half_l * (t_diff_Rl(i, l, m) * t_u(l, k));
374 } else {
375 t_h_domega(i, k, m) = t_diff_R(i, l, m) * t_u(l, k);
376 }
377
378 t_h_dlog_u(i, k, L) = t_R(i, l) * t_Ldiff_u(l, k, L);
379
380 t_approx_P_adjoint_log_du_dP(i, k, L) =
381 t_R(i, l) * (t_Ldiff_u(l, k, L) + t_Ldiff_u(k, l, L)) / 2.;
382
385 t_A(k, l, m) = t_diff_Rr(i, l, m) * t_approx_P(i, k) +
386 t_diff_Rr(i, k, m) * t_approx_P(i, l);
387 t_A(k, l, m) /= 2.;
389 t_B(k, l, m) = t_diff_Rl(i, l, m) * t_approx_P(i, k) +
390 t_diff_Rl(i, k, m) * t_approx_P(i, l);
391 t_B(k, l, m) /= 2.;
392
393 t_approx_P_adjoint_log_du_domega(m, L) =
394 half_r * (t_A(k, l, m) *
395 (t_Ldiff_u(k, l, L) + t_Ldiff_u(k, l, L)) / 2) +
396 half_l * (t_B(k, l, m) *
397 (t_Ldiff_u(k, l, L) + t_Ldiff_u(k, l, L)) / 2);
398 } else {
400 t_A(k, l, m) = t_diff_R(i, l, m) * t_approx_P(i, k);
401 t_approx_P_adjoint_log_du_domega(m, L) =
402 t_A(k, l, m) * t_Ldiff_u(k, l, L);
403 }
404
405 t_levi_kirchhoff_dstreach(m, L) =
406 half_r *
407 (t_diff_Rr(i, l, m) * (t_Ldiff_u(l, k, L) * t_approx_P(i, k)))
408
409 +
410
411 half_l *
412 (t_diff_Rl(i, l, m) * (t_Ldiff_u(l, k, L) * t_approx_P(i, k)));
413
414 t_levi_kirchhoff_dP(m, i, k) =
415 half_r * t_diff_Rr(i, l, m) * (t_u(l, k))
416
417 +
418
419 half_l * t_diff_Rl(i, l, m) * (t_u(l, k));
420
421 t_levi_kirchhoff_domega(m, n) =
422 half_r *
423 (t_diff_diff_Rr(i, l, m, n) * (t_u(l, k) * t_approx_P(i, k)) +
424 t_diff_diff_Rr(i, k, m, n) * (t_u(l, k) * t_approx_P(i, l)))
425
426 +
427
428 half_l *
429 (t_diff_diff_Rl(i, l, m, n) * (t_u(l, k) * t_approx_P(i, k)) +
430 t_diff_diff_Rl(i, k, m, n) * (t_u(l, k) * t_approx_P(i, l)));
431 t_levi_kirchhoff_domega(m, n) /= 2.;
432 }
433
434 next();
435 }
436
438 };
439
440 auto large_loop = [&]() {
442
444 case LARGE_ROT:
445 break;
446 case SMALL_ROT:
447 break;
448 default:
449 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
450 "rotSelector should be large");
451 };
452
453 for (int gg = 0; gg != nb_integration_pts; ++gg) {
454
456
460 t_h1(i, j) = t_kd(i, j);
461 break;
462 case LARGE_ROT:
463 t_h1(i, j) = t_grad_h1(i, j) + t_kd(i, j);
464 break;
465 default:
466 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
467 "gradApproximator not handled");
468 };
469
470 // calculate streach
471 auto t_Ldiff_u = calculate_log_stretch();
472 // calculate total stretch
473 auto [t_R_h1, t_inv_u_h1] = calculate_total_stretch(t_h1);
474
476 t_h_u(l, k) = t_u(l, o) * t_h1(o, k);
478 t_Ldiff_h_u(l, k, L) = t_Ldiff_u(l, o, L) * t_h1(o, k);
479
484
486
487 // rotation
489 case LARGE_ROT:
490 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
491 t_diff_R(i, j, k) =
492 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
493 // left
494 t_diff_Rr(i, j, l) = t_R(i, k) * levi_civita(k, j, l);
495 t_diff_diff_Rr(i, j, l, m) = t_diff_R(i, k, m) * levi_civita(k, j, l);
496 // right
497 t_diff_Rl(i, j, l) = levi_civita(i, k, l) * t_R(k, j);
498 t_diff_diff_Rl(i, j, l, m) = levi_civita(i, k, l) * t_diff_R(k, j, m);
499 break;
500 case SMALL_ROT:
501 t_R(i, k) = t_kd(i, k) + levi_civita(i, k, l) * t_omega(l);
502 t_diff_R(i, j, k) = levi_civita(i, j, k);
503 // left
504 t_diff_Rr(i, j, l) = levi_civita(i, j, l);
505 t_diff_diff_Rr(i, j, l, m) = 0;
506 // right
507 t_diff_Rl(i, j, l) = levi_civita(i, j, l);
508 t_diff_diff_Rl(i, j, l, m) = 0;
509 break;
510
511 default:
512 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
513 "rotationSelector not handled");
514 }
515
516 constexpr double half_r = 1 / 2.;
517 constexpr double half_l = 1 / 2.;
518
519 // calculate gradient
520 t_h(i, k) = t_R(i, l) * t_h_u(l, k);
521
522 // Adjoint stress
523 t_approx_P_adjoint__dstretch(l, o) =
524 (t_R(i, l) * t_approx_P(i, k)) * t_h1(o, k);
525 t_approx_P_adjoint_log_du(L) =
526 t_approx_P_adjoint__dstretch(l, o) * t_Ldiff_u(l, o, L);
527
528 // Kirchhoff stress
529 t_levi_kirchhoff(m) =
530
531 half_r * ((t_diff_Rr(i, l, m) * (t_h_u(l, k)) * t_approx_P(i, k)))
532
533 +
534
535 half_l * ((t_diff_Rl(i, l, m) * (t_h_u(l, k)) * t_approx_P(i, k)));
536
538
540 t_h_domega(i, k, m) = half_r * (t_diff_Rr(i, l, m) * t_h_u(l, k))
541
542 +
543
544 half_l * (t_diff_Rl(i, l, m) * t_h_u(l, k));
545 } else {
546 t_h_domega(i, k, m) = t_diff_R(i, l, m) * t_h_u(l, k);
547 }
548
549 t_h_dlog_u(i, k, L) = t_R(i, l) * t_Ldiff_h_u(l, k, L);
550
551 t_approx_P_adjoint_log_du_dP(i, k, L) =
552 t_R(i, l) * t_Ldiff_h_u(l, k, L);
553
556 t_A(m, L, i, k) = t_diff_Rr(i, l, m) * t_Ldiff_h_u(l, k, L);
558 t_B(m, L, i, k) = t_diff_Rl(i, l, m) * t_Ldiff_h_u(l, k, L);
559
560 t_approx_P_adjoint_log_du_domega(m, L) =
561 half_r * (t_A(m, L, i, k) * t_approx_P(i, k))
562
563 +
564
565 half_l * (t_B(m, L, i, k) * t_approx_P(i, k));
566 } else {
568 t_A(m, L, i, k) = t_diff_R(i, l, m) * t_Ldiff_h_u(l, k, L);
569 t_approx_P_adjoint_log_du_domega(m, L) =
570 t_A(m, L, i, k) * t_approx_P(i, k);
571 }
572
573 t_levi_kirchhoff_dstreach(m, L) =
574 half_r *
575 (t_diff_Rr(i, l, m) * (t_Ldiff_h_u(l, k, L) * t_approx_P(i, k)))
576
577 +
578
579 half_l * (t_diff_Rl(i, l, m) *
580 (t_Ldiff_h_u(l, k, L) * t_approx_P(i, k)));
581
582 t_levi_kirchhoff_dP(m, i, k) =
583
584 half_r * (t_diff_Rr(i, l, m) * t_h_u(l, k))
585
586 +
587
588 half_l * (t_diff_Rl(i, l, m) * t_h_u(l, k));
589
590 t_levi_kirchhoff_domega(m, n) =
591 half_r *
592 (t_diff_diff_Rr(i, l, m, n) * (t_h_u(l, k) * t_approx_P(i, k)))
593
594 +
595
596 half_l *
597 (t_diff_diff_Rl(i, l, m, n) * (t_h_u(l, k) * t_approx_P(i, k)));
598 }
599
600 next();
601 }
602
604 };
605
606 auto moderate_loop = [&]() {
608
610 case LARGE_ROT:
611 break;
612 case SMALL_ROT:
613 break;
614 default:
615 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
616 "rotSelector should be large");
617 };
618
619 for (int gg = 0; gg != nb_integration_pts; ++gg) {
620
622
625 case MODERATE_ROT:
626 t_h1(i, j) = t_grad_h1(i, j) + t_kd(i, j);
627 break;
628 default:
629 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
630 "gradApproximator not handled");
631 };
632
633 // calculate streach
634 auto t_Ldiff_u = calculate_log_stretch();
635 // calculate total stretch
636 auto [t_R_h1, t_inv_u_h1] = calculate_total_stretch(t_h1);
637
639 t_h_u(l, k) = (t_symm_kd(l, o) + t_log_u(l, o)) * t_h1(o, k);
641 t_L_h(l, k, L) = t_L(l, o, L) * t_h1(o, k);
642
647
649
650 // rotation
652 case LARGE_ROT:
653 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
654 t_diff_R(i, j, k) =
655 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
656 // left
657 t_diff_Rr(i, j, l) = t_R(i, k) * levi_civita(k, j, l);
658 t_diff_diff_Rr(i, j, l, m) = t_diff_R(i, k, m) * levi_civita(k, j, l);
659 // right
660 t_diff_Rl(i, j, l) = levi_civita(i, k, l) * t_R(k, j);
661 t_diff_diff_Rl(i, j, l, m) = levi_civita(i, k, l) * t_diff_R(k, j, m);
662 break;
663 case SMALL_ROT:
664 t_R(i, k) = t_kd(i, k) + levi_civita(i, k, l) * t_omega(l);
665 t_diff_R(i, j, l) = levi_civita(i, j, l);
666 // left
667 t_diff_Rr(i, j, l) = levi_civita(i, j, l);
668 t_diff_diff_Rr(i, j, l, m) = 0;
669 // right
670 t_diff_Rl(i, j, l) = levi_civita(i, j, l);
671 t_diff_diff_Rl(i, j, l, m) = 0;
672 break;
673
674 default:
675 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
676 "rotationSelector not handled");
677 }
678
679 constexpr double half_r = 1 / 2.;
680 constexpr double half_l = 1 / 2.;
681
682 // calculate gradient
683 t_h(i, k) = t_R(i, l) * t_h_u(l, k);
684
685 // Adjoint stress
686 t_approx_P_adjoint__dstretch(l, o) =
687 (t_R(i, l) * t_approx_P(i, k)) * t_h1(o, k);
688
689 t_approx_P_adjoint_log_du(L) =
690 t_approx_P_adjoint__dstretch(l, o) * t_L(l, o, L);
691
692 // Kirchhoff stress
693 t_levi_kirchhoff(m) =
694
695 half_r * ((t_diff_Rr(i, l, m) * (t_h_u(l, k)) * t_approx_P(i, k)))
696
697 +
698
699 half_l * ((t_diff_Rl(i, l, m) * (t_h_u(l, k)) * t_approx_P(i, k)));
700
702
704 t_h_domega(i, k, m) = half_r * (t_diff_Rr(i, l, m) * t_h_u(l, k))
705
706 +
707
708 half_l * (t_diff_Rl(i, l, m) * t_h_u(l, k));
709 } else {
710 t_h_domega(i, k, m) = t_diff_R(i, l, m) * t_h_u(l, k);
711 }
712
713 t_h_dlog_u(i, k, L) = t_R(i, l) * t_L_h(l, k, L);
714
715 t_approx_P_adjoint_log_du_dP(i, k, L) = t_R(i, l) * t_L_h(l, k, L);
716
719 t_A(m, L, i, k) = t_diff_Rr(i, l, m) * t_L_h(l, k, L);
721 t_B(m, L, i, k) = t_diff_Rl(i, l, m) * t_L_h(l, k, L);
722 t_approx_P_adjoint_log_du_domega(m, L) =
723 half_r * (t_A(m, L, i, k) * t_approx_P(i, k))
724
725 +
726
727 half_l * (t_B(m, L, i, k) * t_approx_P(i, k));
728 } else {
730 t_A(m, L, i, k) = t_diff_R(i, l, m) * t_L_h(l, k, L);
731 t_approx_P_adjoint_log_du_domega(m, L) =
732 t_A(m, L, i, k) * t_approx_P(i, k);
733 }
734
735 t_levi_kirchhoff_dstreach(m, L) =
736 half_r * (t_diff_Rr(i, l, m) * (t_L_h(l, k, L) * t_approx_P(i, k)))
737
738 +
739
740 half_l * (t_diff_Rl(i, l, m) * (t_L_h(l, k, L) * t_approx_P(i, k)));
741
742 t_levi_kirchhoff_dP(m, i, k) =
743
744 half_r * (t_diff_Rr(i, l, m) * t_h_u(l, k))
745
746 +
747
748 half_l * (t_diff_Rl(i, l, m) * t_h_u(l, k));
749
750 t_levi_kirchhoff_domega(m, n) =
751 half_r *
752 (t_diff_diff_Rr(i, l, m, n) * (t_h_u(l, k) * t_approx_P(i, k)))
753
754 +
755
756 half_l *
757 (t_diff_diff_Rl(i, l, m, n) * (t_h_u(l, k) * t_approx_P(i, k)));
758 }
759
760 next();
761 }
762
764 };
765
766 auto small_loop = [&]() {
769 case SMALL_ROT:
770 break;
771 default:
772 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
773 "rotSelector should be small");
774 };
775
776 for (int gg = 0; gg != nb_integration_pts; ++gg) {
777
780 case SMALL_ROT:
781 t_h1(i, j) = t_kd(i, j);
782 break;
783 default:
784 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
785 "gradApproximator not handled");
786 };
787
788 // calculate streach
790
792 t_Ldiff_u(i, j, L) = calculate_log_stretch()(i, j, L);
793 } else {
794 t_u(i, j) = t_symm_kd(i, j) + t_log_u(i, j);
795 t_Ldiff_u(i, j, L) = t_L(i, j, L);
796 }
797 t_log_u2_h1(i, j) = 0;
798 t_log_stretch_total(i, j) = t_log_u(i, j);
799
801 t_h(i, j) = levi_civita(i, j, k) * t_omega(k) + t_u(i, j);
802
803 t_h_domega(i, j, k) = levi_civita(i, j, k);
804 t_h_dlog_u(i, j, L) = t_Ldiff_u(i, j, L);
805
806 // Adjoint stress
807 t_approx_P_adjoint__dstretch(i, j) = t_approx_P(i, j);
808 t_approx_P_adjoint_log_du(L) =
809 t_approx_P_adjoint__dstretch(i, j) * t_Ldiff_u(i, j, L);
810 t_approx_P_adjoint_log_du_dP(i, j, L) = t_Ldiff_u(i, j, L);
811 t_approx_P_adjoint_log_du_domega(m, L) = 0;
812
813 // Kirchhoff stress
814 t_levi_kirchhoff(k) = levi_civita(i, j, k) * t_approx_P(i, j);
815 t_levi_kirchhoff_dstreach(m, L) = 0;
816 t_levi_kirchhoff_dP(k, i, j) = levi_civita(i, j, k);
817 t_levi_kirchhoff_domega(m, n) = 0;
818
819 next();
820 }
821
823 };
824
827 CHKERR no_h1_loop();
828 break;
829 case LARGE_ROT:
830 CHKERR large_loop();
832 break;
833 case MODERATE_ROT:
834 CHKERR moderate_loop();
836 break;
837 case SMALL_ROT:
838 CHKERR small_loop();
840 break;
841 default:
842 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
843 "gradApproximator not handled");
844 break;
845 };
846
848}
849
851 EntData &data) {
855
856 auto N_InLoop = getNinTheLoop();
857 auto sensee = getSkeletonSense();
858 auto nb_gauss_pts = getGaussPts().size2();
859 auto t_normal = getFTensor1NormalsAtGaussPts();
860
861 auto t_sigma_ptr =
862 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->approxPAtPts);
863 if (N_InLoop == 0) {
864 dataAtPts->tractionAtPts.resize(SPACE_DIM, nb_gauss_pts, false);
865 dataAtPts->tractionAtPts.clear();
866 }
867 auto t_traction = getFTensor1FromMat<SPACE_DIM>(dataAtPts->tractionAtPts);
868
869 for (int gg = 0; gg != nb_gauss_pts; gg++) {
870 t_traction(i) = t_sigma_ptr(i, j) * sensee * (t_normal(j) / t_normal.l2());
871 ++t_traction;
872 ++t_sigma_ptr;
873 ++t_normal;
874 }
875
877}
878
880 EntData &data) {
882 if (blockEntities.find(getFEEntityHandle()) == blockEntities.end()) {
884 };
888 int nb_integration_pts = getGaussPts().size2();
889 auto t_w = getFTensor0IntegrationWeight();
890 auto t_traction = getFTensor1FromMat<SPACE_DIM>(dataAtPts->tractionAtPts);
891 auto t_coords = getFTensor1CoordsAtGaussPts();
892 auto t_spatial_disp = getFTensor1FromMat<SPACE_DIM>(dataAtPts->wL2AtPts);
893
894 FTensor::Tensor1<double, 3> t_coords_spatial{0., 0., 0.};
895 // Offset for center of mass. Can be added in the future.
896 FTensor::Tensor1<double, 3> t_off{0.0, 0.0, 0.0};
897 FTensor::Tensor1<double, 3> loc_reaction_forces{0., 0., 0.};
898 FTensor::Tensor1<double, 3> loc_moment_forces{0., 0., 0.};
899
900 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
901 loc_reaction_forces(i) += (t_traction(i)) * t_w * getMeasure();
902 t_coords_spatial(i) = t_coords(i) + t_spatial_disp(i);
903 // t_coords_spatial(i) -= t_off(i);
904 loc_moment_forces(i) +=
905 (FTensor::levi_civita<double>(i, j, k) * t_coords_spatial(j)) *
906 t_traction(k) * t_w * getMeasure();
907 ++t_coords;
908 ++t_spatial_disp;
909 ++t_w;
910 ++t_traction;
911 }
912
913 reactionVec[0] += loc_reaction_forces(0);
914 reactionVec[1] += loc_reaction_forces(1);
915 reactionVec[2] += loc_reaction_forces(2);
916 reactionVec[3] += loc_moment_forces(0);
917 reactionVec[4] += loc_moment_forces(1);
918 reactionVec[5] += loc_moment_forces(2);
919
921}
922
925 int nb_dofs = data.getIndices().size();
926 int nb_integration_pts = data.getN().size1();
927 auto v = getVolume();
928 auto t_w = getFTensor0IntegrationWeight();
929 auto t_div_P = getFTensor1FromMat<3>(dataAtPts->divPAtPts);
930 auto t_s_dot_w = getFTensor1FromMat<3>(dataAtPts->wL2DotAtPts);
931 if (dataAtPts->wL2DotDotAtPts.size1() == 0 &&
932 dataAtPts->wL2DotDotAtPts.size2() != nb_integration_pts) {
933 dataAtPts->wL2DotDotAtPts.resize(3, nb_integration_pts);
934 dataAtPts->wL2DotDotAtPts.clear();
935 }
936 auto t_s_dot_dot_w = getFTensor1FromMat<3>(dataAtPts->wL2DotDotAtPts);
937
938 auto piola_scale = dataAtPts->piolaScale;
939 auto alpha_w = alphaW / piola_scale;
940 auto alpha_rho = alphaRho / piola_scale;
941
942 int nb_base_functions = data.getN().size2();
943 auto t_row_base_fun = data.getFTensor0N();
944
945 FTensor::Index<'i', 3> i;
946 auto get_ftensor1 = [](auto &v) {
948 &v[2]);
949 };
950
951 auto next = [&]() {
952 ++t_w;
953 ++t_div_P;
954 ++t_s_dot_w;
955 ++t_s_dot_dot_w;
956 };
957
958 for (int gg = 0; gg != nb_integration_pts; ++gg) {
959 double a = v * t_w;
960 auto t_nf = get_ftensor1(nF);
961 int bb = 0;
962 for (; bb != nb_dofs / 3; ++bb) {
963 t_nf(i) -= a * t_row_base_fun * t_div_P(i);
964 t_nf(i) += a * t_row_base_fun * alpha_w * t_s_dot_w(i);
965 t_nf(i) += a * t_row_base_fun * alpha_rho * t_s_dot_dot_w(i);
966 ++t_nf;
967 ++t_row_base_fun;
968 }
969 for (; bb != nb_base_functions; ++bb)
970 ++t_row_base_fun;
971 next();
972 }
973
975}
976
979 int nb_dofs = data.getIndices().size();
980 int nb_integration_pts = getGaussPts().size2();
981 auto v = getVolume();
982 auto t_w = getFTensor0IntegrationWeight();
983 auto t_levi_kirchhoff = getFTensor1FromMat<3>(dataAtPts->leviKirchhoffAtPts);
984 auto t_omega_grad_dot =
985 getFTensor2FromMat<3, 3>(dataAtPts->rotAxisGradDotAtPts);
986 int nb_base_functions = data.getN().size2();
987 auto t_row_base_fun = data.getFTensor0N();
988 auto t_row_grad_fun = data.getFTensor1DiffN<3>();
989 FTensor::Index<'i', 3> i;
990 FTensor::Index<'j', 3> j;
991 FTensor::Index<'k', 3> k;
992 auto get_ftensor1 = [](auto &v) {
994 &v[2]);
995 };
996 // auto time_step = getTStimeStep();
997
998 for (int gg = 0; gg != nb_integration_pts; ++gg) {
999
1000 double a = v * t_w;
1001 auto t_nf = get_ftensor1(nF);
1002 int bb = 0;
1003 for (; bb != nb_dofs / 3; ++bb) {
1004 t_nf(k) -= (a * t_row_base_fun) * t_levi_kirchhoff(k);
1005 t_nf(k) += (a * alphaOmega /*/ time_step*/) *
1006 (t_row_grad_fun(i) * t_omega_grad_dot(k, i));
1007 ++t_nf;
1008 ++t_row_base_fun;
1009 ++t_row_grad_fun;
1010 }
1011 for (; bb != nb_base_functions; ++bb) {
1012 ++t_row_base_fun;
1013 ++t_row_grad_fun;
1014 }
1015 ++t_w;
1016 ++t_levi_kirchhoff;
1017 ++t_omega_grad_dot;
1018 }
1020}
1021
1024 int nb_dofs = data.getIndices().size();
1025 int nb_integration_pts = data.getN().size1();
1026 auto v = getVolume();
1027 auto t_w = getFTensor0IntegrationWeight();
1028
1029 int nb_base_functions = data.getN().size2() / 3;
1030 auto t_row_base_fun = data.getFTensor1N<3>();
1031 FTENSOR_INDEX(3, i);
1032 FTENSOR_INDEX(3, j);
1033 FTENSOR_INDEX(3, k);
1034 FTENSOR_INDEX(3, m);
1035 FTENSOR_INDEX(3, l);
1036
1037 auto get_ftensor1 = [](auto &v) {
1039 &v[2]);
1040 };
1041
1043
1044 auto t_R = getFTensor2FromMat<3, 3>(dataAtPts->rotMatAtPts);
1045 auto t_u = getFTensor2SymmetricFromMat<3>(dataAtPts->stretchTensorAtPts);
1046
1047 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1048 double a = v * t_w;
1049 auto t_nf = get_ftensor1(nF);
1050
1051 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1052
1053 int bb = 0;
1054 for (; bb != nb_dofs / 3; ++bb) {
1055 t_nf(i) -= a * (t_row_base_fun(k) * (t_R(i, l) * t_u(l, k)) / 2);
1056 t_nf(i) -= a * (t_row_base_fun(l) * (t_R(i, k) * t_u(l, k)) / 2);
1057 t_nf(i) += a * (t_row_base_fun(j) * t_kd(i, j));
1058 ++t_nf;
1059 ++t_row_base_fun;
1060 }
1061
1062 for (; bb != nb_base_functions; ++bb)
1063 ++t_row_base_fun;
1064
1065 ++t_w;
1066 ++t_R;
1067 ++t_u;
1068 }
1069
1070 } else {
1071
1072 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
1073
1074 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1075 double a = v * t_w;
1076 auto t_nf = get_ftensor1(nF);
1077
1078 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1080
1081 t_residuum(i, j) = t_h(i, j) - t_kd(i, j);
1082
1083 int bb = 0;
1084 for (; bb != nb_dofs / 3; ++bb) {
1085 t_nf(i) -= a * t_row_base_fun(j) * t_residuum(i, j);
1086 ++t_nf;
1087 ++t_row_base_fun;
1088 }
1089
1090 for (; bb != nb_base_functions; ++bb)
1091 ++t_row_base_fun;
1092
1093 ++t_w;
1094 ++t_h;
1095 }
1096 }
1097
1099}
1100
1103 int nb_dofs = data.getIndices().size();
1104 int nb_integration_pts = data.getN().size1();
1105 auto v = getVolume();
1106 auto t_w = getFTensor0IntegrationWeight();
1107
1108 int nb_base_functions = data.getN().size2() / 9;
1109 auto t_row_base_fun = data.getFTensor2N<3, 3>();
1110 FTENSOR_INDEX(3, i);
1111 FTENSOR_INDEX(3, j);
1112 FTENSOR_INDEX(3, k);
1113 FTENSOR_INDEX(3, m);
1114 FTENSOR_INDEX(3, l);
1115
1116 auto get_ftensor0 = [](auto &v) {
1118 };
1119
1121
1122 auto t_R = getFTensor2FromMat<3, 3>(dataAtPts->rotMatAtPts);
1123 auto t_u = getFTensor2SymmetricFromMat<3>(dataAtPts->stretchTensorAtPts);
1124
1125 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1126 double a = v * t_w;
1127 auto t_nf = get_ftensor0(nF);
1128
1129 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1130
1131 int bb = 0;
1132 for (; bb != nb_dofs; ++bb) {
1133 t_nf -= a * t_row_base_fun(i, k) * (t_R(i, l) * t_u(l, k)) / 2;
1134 t_nf -= a * t_row_base_fun(i, l) * (t_R(i, k) * t_u(l, k)) / 2;
1135 ++t_nf;
1136 ++t_row_base_fun;
1137 }
1138 for (; bb != nb_base_functions; ++bb) {
1139 ++t_row_base_fun;
1140 }
1141 ++t_w;
1142 ++t_R;
1143 ++t_u;
1144 }
1145
1146 } else {
1147
1148 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
1149
1150 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1151 double a = v * t_w;
1152 auto t_nf = get_ftensor0(nF);
1153
1154 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1156 t_residuum(i, j) = t_h(i, j);
1157
1158 int bb = 0;
1159 for (; bb != nb_dofs; ++bb) {
1160 t_nf -= a * t_row_base_fun(i, j) * t_residuum(i, j);
1161 ++t_nf;
1162 ++t_row_base_fun;
1163 }
1164 for (; bb != nb_base_functions; ++bb) {
1165 ++t_row_base_fun;
1166 }
1167 ++t_w;
1168 ++t_h;
1169 }
1170 }
1171
1173}
1174
1177 int nb_dofs = data.getIndices().size();
1178 int nb_integration_pts = data.getN().size1();
1179 auto v = getVolume();
1180 auto t_w = getFTensor0IntegrationWeight();
1181 auto t_w_l2 = getFTensor1FromMat<3>(dataAtPts->wL2AtPts);
1182 int nb_base_functions = data.getN().size2() / 3;
1183 auto t_row_diff_base_fun = data.getFTensor2DiffN<3, 3>();
1184 FTensor::Index<'i', 3> i;
1185 auto get_ftensor1 = [](auto &v) {
1187 &v[2]);
1188 };
1189
1190 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1191 double a = v * t_w;
1192 auto t_nf = get_ftensor1(nF);
1193 int bb = 0;
1194 for (; bb != nb_dofs / 3; ++bb) {
1195 double div_row_base = t_row_diff_base_fun(i, i);
1196 t_nf(i) -= a * div_row_base * t_w_l2(i);
1197 ++t_nf;
1198 ++t_row_diff_base_fun;
1199 }
1200 for (; bb != nb_base_functions; ++bb) {
1201 ++t_row_diff_base_fun;
1202 }
1203 ++t_w;
1204 ++t_w_l2;
1205 }
1206
1208}
1209
1210template <>
1212 EntData &data) {
1214
1215 int nb_integration_pts = getGaussPts().size2();
1216
1217 Tag tag;
1218 CHKERR getPtrFE() -> mField.get_moab().tag_get_handle(tagName.c_str(), tag);
1219 int tag_length;
1220 CHKERR getPtrFE() -> mField.get_moab().tag_get_length(tag, tag_length);
1221 if (tag_length != 9) {
1222 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1223 "Number of internal stress components should be 9 but is %d",
1224 tag_length);
1225 }
1226
1227 VectorDouble const_stress_vec(9);
1228 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1229 CHKERR getPtrFE() -> mField.get_moab().tag_get_data(
1230 tag, &fe_ent, 1, &*const_stress_vec.data().begin());
1231 auto t_const_stress = getFTensor1FromArray<9, 9>(const_stress_vec);
1232
1233 dataAtPts->internalStressAtPts.resize(tag_length, nb_integration_pts, false);
1234 dataAtPts->internalStressAtPts.clear();
1235 auto t_internal_stress =
1236 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1237
1238 FTensor::Index<'L', 9> L;
1239 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1240 t_internal_stress(L) = t_const_stress(L);
1241 ++t_internal_stress;
1242 }
1243
1245}
1246
1247template <>
1249 EntityType type,
1250 EntData &data) {
1252
1253 int nb_integration_pts = getGaussPts().size2();
1254
1255 Tag tag;
1256 CHKERR getPtrFE() -> mField.get_moab().tag_get_handle(tagName.c_str(), tag);
1257 int tag_length;
1258 CHKERR getPtrFE() -> mField.get_moab().tag_get_length(tag, tag_length);
1259 if (tag_length != 9) {
1260 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1261 "Number of internal stress components should be 9 but is %d",
1262 tag_length);
1263 }
1264
1265 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1266 const EntityHandle *vert_conn;
1267 int vert_num;
1268 CHKERR getPtrFE() -> mField.get_moab().get_connectivity(fe_ent, vert_conn,
1269 vert_num, true);
1270 VectorDouble vert_data(vert_num * tag_length);
1271 CHKERR getPtrFE() -> mField.get_moab().tag_get_data(tag, vert_conn, vert_num,
1272 &vert_data[0]);
1273
1274 dataAtPts->internalStressAtPts.resize(tag_length, nb_integration_pts, false);
1275 dataAtPts->internalStressAtPts.clear();
1276 auto t_internal_stress =
1277 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1278
1279 auto t_shape_n = data.getFTensor0N();
1280 int nb_shape_fn = data.getN(NOBASE).size2();
1281 FTensor::Index<'L', 9> L;
1282 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1283 auto t_vert_data = getFTensor1FromArray<9, 9>(vert_data);
1284 for (int bb = 0; bb != nb_shape_fn; ++bb) {
1285 t_internal_stress(L) += t_vert_data(L) * t_shape_n;
1286 ++t_vert_data;
1287 ++t_shape_n;
1288 }
1289 ++t_internal_stress;
1290 }
1291
1293}
1294
1295template <>
1298
1299 int nb_dofs = data.getIndices().size();
1300 int nb_integration_pts = data.getN().size1();
1301 auto v = getVolume();
1302 auto t_w = getFTensor0IntegrationWeight();
1303
1304 FTensor::Index<'i', 3> i;
1305 FTensor::Index<'j', 3> j;
1306
1307 auto get_ftensor2 = [](auto &v) {
1309 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1310 };
1311
1312 auto t_internal_stress =
1313 getFTensor2FromMat<3, 3>(dataAtPts->internalStressAtPts);
1314
1315 const double time = EshelbianCore::dynamicRelaxation
1317 : getFEMethod()->ts_t;
1318
1319 // default scaling is constant
1320 double scale = scalingMethodPtr->getScale(time);
1321
1323 auto t_L = symm_L_tensor();
1324
1325 int nb_base_functions = data.getN().size2();
1326 auto t_row_base_fun = data.getFTensor0N();
1327 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1328 double a = v * t_w;
1329 auto t_nf = get_ftensor2(nF);
1330
1331 FTensor::Tensor2<double, 3, 3> t_symm_stress;
1332 t_symm_stress(i, j) =
1333 (t_internal_stress(i, j) + t_internal_stress(j, i)) / 2;
1334
1336 t_residual(L) = t_L(i, j, L) * (scale * t_symm_stress(i, j));
1337
1338 int bb = 0;
1339 for (; bb != nb_dofs / 6; ++bb) {
1340 t_nf(L) += a * t_row_base_fun * t_residual(L);
1341 ++t_nf;
1342 ++t_row_base_fun;
1343 }
1344 for (; bb != nb_base_functions; ++bb)
1345 ++t_row_base_fun;
1346
1347 ++t_w;
1348 ++t_internal_stress;
1349 }
1351}
1352
1353template <>
1356
1357 int nb_dofs = data.getIndices().size();
1358 int nb_integration_pts = data.getN().size1();
1359 auto v = getVolume();
1360 auto t_w = getFTensor0IntegrationWeight();
1361
1362 auto get_ftensor2 = [](auto &v) {
1364 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1365 };
1366
1367 auto t_internal_stress =
1368 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1369
1371 FTensor::Index<'M', size_symm> M;
1373 t_L = voigt_to_symm();
1374
1375 const double time = EshelbianCore::dynamicRelaxation
1377 : getFEMethod()->ts_t;
1378
1379 // default is constant
1380 double scale = scalingMethodPtr->getScale(time);
1381
1382 int nb_base_functions = data.getN().size2();
1383 auto t_row_base_fun = data.getFTensor0N();
1384 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1385 double a = v * t_w;
1386 auto t_nf = get_ftensor2(nF);
1387
1389 t_residual(L) = t_L(M, L) * (scale * t_internal_stress(M));
1390
1391 int bb = 0;
1392 for (; bb != nb_dofs / 6; ++bb) {
1393 t_nf(L) += a * t_row_base_fun * t_residual(L);
1394 ++t_nf;
1395 ++t_row_base_fun;
1396 }
1397 for (; bb != nb_base_functions; ++bb)
1398 ++t_row_base_fun;
1399
1400 ++t_w;
1401 ++t_internal_stress;
1402 }
1404}
1405
1406template <AssemblyType A>
1409 // get entity of face
1410 EntityHandle fe_ent = OP::getFEEntityHandle();
1411 // iterate over all boundary data
1412 for (auto &bc : (*bcDispPtr)) {
1413 // check if finite element entity is part of boundary condition
1414 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1415 int nb_dofs = data.getIndices().size();
1416
1417 int nb_integration_pts = OP::getGaussPts().size2();
1418 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1419 auto t_w = OP::getFTensor0IntegrationWeight();
1420 int nb_base_functions = data.getN().size2() / 3;
1421 auto t_row_base_fun = data.getFTensor1N<3>();
1422
1425
1426 double scale = 1;
1427 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1429 scale *= scalingMethodsMap.at(bc.blockName)
1430 ->getScale(EshelbianCore::dynamicTime);
1431 } else {
1432 scale *= scalingMethodsMap.at(bc.blockName)
1433 ->getScale(OP::getFEMethod()->ts_t);
1434 }
1435 } else {
1436 MOFEM_LOG("SELF", Sev::warning)
1437 << "No scaling method found for " << bc.blockName;
1438 }
1439
1440 // get bc data
1441 FTensor::Tensor1<double, 3> t_bc_disp(bc.vals[0], bc.vals[1], bc.vals[2]);
1442 t_bc_disp(i) *= scale;
1443
1444 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1445 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1446 int bb = 0;
1447 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1448 t_nf(i) +=
1449 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1450 ++t_nf;
1451 ++t_row_base_fun;
1452 }
1453 for (; bb != nb_base_functions; ++bb)
1454 ++t_row_base_fun;
1455
1456 ++t_w;
1457 ++t_normal;
1458 }
1459 }
1460 }
1462}
1463
1465 return OP::iNtegrate(data);
1466}
1467
1468template <AssemblyType A>
1471
1472 FTENSOR_INDEX(3, i);
1473 FTENSOR_INDEX(3, j);
1474 FTENSOR_INDEX(3, k);
1475
1476 double time = OP::getFEMethod()->ts_t;
1479 }
1480
1481 // get entity of face
1482 EntityHandle fe_ent = OP::getFEEntityHandle();
1483 // interate over all boundary data
1484 for (auto &bc : (*bcRotPtr)) {
1485 // check if finite element entity is part of boundary condition
1486 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1487 int nb_dofs = data.getIndices().size();
1488 int nb_integration_pts = OP::getGaussPts().size2();
1489 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1490 auto t_w = OP::getFTensor0IntegrationWeight();
1491
1492 int nb_base_functions = data.getN().size2() / 3;
1493 auto t_row_base_fun = data.getFTensor1N<3>();
1494
1495 auto get_ftensor1 = [](auto &v) {
1497 &v[2]);
1498 };
1499
1500 // Note: First three values of bc.vals are the center of rotation
1501 // 4th is rotation angle in radians, and remaining values are axis of
1502 // rotation. Also, if rotation axis is not provided, it defaults to the
1503 // normal vector of the face.
1504
1505 // get bc data
1506 FTensor::Tensor1<double, 3> t_center(bc.vals[0], bc.vals[1], bc.vals[2]);
1507
1508 auto get_rotation_angle = [&]() {
1509 double theta = bc.theta;
1510 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1511 theta *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1512 }
1513 return theta;
1514 };
1515
1516 auto get_rotation = [&](auto theta) {
1518 if (bc.vals.size() == 7) {
1519 t_omega(0) = bc.vals[4];
1520 t_omega(1) = bc.vals[5];
1521 t_omega(2) = bc.vals[6];
1522 } else {
1523 // Use gemetric face normal as rotation axis
1524 t_omega(i) = OP::getFTensor1Normal()(i);
1525 }
1526 t_omega.normalize();
1527 t_omega(i) *= theta;
1530 ? 0.
1531 : t_omega.l2());
1532 };
1533
1534 auto t_R = get_rotation(get_rotation_angle());
1535 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1536
1537 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1539 t_delta(i) = t_center(i) - t_coords(i);
1541 t_disp(i) = t_delta(i) - t_R(i, j) * t_delta(j);
1542
1543 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1544 int bb = 0;
1545 for (; bb != nb_dofs / 3; ++bb) {
1546 t_nf(i) += t_w * (t_row_base_fun(j) * t_normal(j)) * t_disp(i) * 0.5;
1547 ++t_nf;
1548 ++t_row_base_fun;
1549 }
1550 for (; bb != nb_base_functions; ++bb)
1551 ++t_row_base_fun;
1552
1553 ++t_w;
1554 ++t_normal;
1555 ++t_coords;
1556 }
1557 }
1558 }
1560}
1561
1563 return OP::iNtegrate(data);
1564}
1565
1566template <AssemblyType A>
1569
1570 double time = OP::getFEMethod()->ts_t;
1573 }
1574
1575 // get entity of face
1576 EntityHandle fe_ent = OP::getFEEntityHandle();
1577 // iterate over all boundary data
1578 for (auto &bc : (*bcDispPtr)) {
1579 // check if finite element entity is part of boundary condition
1580 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1581
1582 for (auto &bd : (*brokenBaseSideDataPtr)) {
1583
1584 auto t_approx_P = getFTensor2FromMat<3, 3>(bd.getFlux());
1585 auto t_u = getFTensor1FromMat<3>(*hybridDispPtr);
1586 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1587 auto t_w = OP::getFTensor0IntegrationWeight();
1588
1591
1593
1594 double scale = 1;
1595 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1596 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1597 } else {
1598 MOFEM_LOG("SELF", Sev::warning)
1599 << "No scaling method found for " << bc.blockName;
1600 }
1601
1602 // get bc data
1603 double val = scale * bc.val;
1604
1605 int nb_dofs = data.getIndices().size();
1606 int nb_integration_pts = OP::getGaussPts().size2();
1607 int nb_base_functions = data.getN().size2();
1608 auto t_row_base = data.getFTensor0N();
1609 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1610
1612 t_N(i) = t_normal(i);
1613 t_N.normalize();
1614
1616 t_P(i, j) = t_N(i) * t_N(j);
1618 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
1619
1620 FTensor::Tensor1<double, 3> t_traction;
1621 t_traction(i) = t_approx_P(i, j) * t_N(j);
1622
1624 t_res(i) =
1625 t_Q(i, j) * t_traction(j) + t_P(i, j) * 2 * t_u(j) - t_N(i) * val;
1626
1627 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1628 int bb = 0;
1629 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1630 t_nf(i) += (t_w * t_row_base * OP::getMeasure()) * t_res(i);
1631 ++t_nf;
1632 ++t_row_base;
1633 }
1634 for (; bb != nb_base_functions; ++bb)
1635 ++t_row_base;
1636
1637 ++t_w;
1638 ++t_normal;
1639 ++t_u;
1640 ++t_approx_P;
1641 }
1642 }
1643 }
1644 }
1646}
1647
1648template <AssemblyType A>
1651 EntData &col_data) {
1653
1654 double time = OP::getFEMethod()->ts_t;
1657 }
1658
1659 int row_nb_dofs = row_data.getIndices().size();
1660 int col_nb_dofs = col_data.getIndices().size();
1661 auto &locMat = OP::locMat;
1662 locMat.resize(row_nb_dofs, col_nb_dofs, false);
1663 locMat.clear();
1664
1665 // get entity of face
1666 EntityHandle fe_ent = OP::getFEEntityHandle();
1667 // iterate over all boundary data
1668 for (auto &bc : (*bcDispPtr)) {
1669 // check if finite element entity is part of boundary condition
1670 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1671
1672 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1673 auto t_w = OP::getFTensor0IntegrationWeight();
1674
1677
1678 double scale = 1;
1679 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1680 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1681 } else {
1682 MOFEM_LOG("SELF", Sev::warning)
1683 << "No scaling method found for " << bc.blockName;
1684 }
1685
1686 int nb_integration_pts = OP::getGaussPts().size2();
1687 int row_nb_dofs = row_data.getIndices().size();
1688 int col_nb_dofs = col_data.getIndices().size();
1689 int nb_base_functions = row_data.getN().size2();
1690 auto t_row_base = row_data.getFTensor0N();
1691
1693
1694 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1695
1697 t_N(i) = t_normal(i);
1698 t_N.normalize();
1699
1701 t_P(i, j) = t_N(i) * t_N(j);
1702
1704 t_d_res(i, j) = 2.0 * t_P(i, j);
1705
1706 int rr = 0;
1707 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
1708 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
1709 locMat, SPACE_DIM * rr);
1710 auto t_col_base = col_data.getFTensor0N(gg, 0);
1711 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
1712 t_mat(i, j) += (t_w * t_row_base * t_col_base) * t_d_res(i, j);
1713 ++t_mat;
1714 ++t_col_base;
1715 }
1716 ++t_row_base;
1717 }
1718
1719 for (; rr != nb_base_functions; ++rr)
1720 ++t_row_base;
1721
1722 ++t_w;
1723 ++t_normal;
1724 }
1725
1726 locMat *= OP::getMeasure();
1727
1728 }
1729 }
1731}
1732
1733template <AssemblyType A>
1736 EntData &col_data) {
1738
1739 double time = OP::getFEMethod()->ts_t;
1742 }
1743
1744 int row_nb_dofs = row_data.getIndices().size();
1745 int col_nb_dofs = col_data.getIndices().size();
1746 auto &locMat = OP::locMat;
1747 locMat.resize(row_nb_dofs, col_nb_dofs, false);
1748 locMat.clear();
1749
1750 // get entity of face
1751 EntityHandle fe_ent = OP::getFEEntityHandle();
1752 // iterate over all boundary data
1753 for (auto &bc : (*bcDispPtr)) {
1754 // check if finite element entity is part of boundary condition
1755 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1756
1757 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1758 auto t_w = OP::getFTensor0IntegrationWeight();
1759
1763
1765
1766 double scale = 1;
1767 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1768 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1769 } else {
1770 MOFEM_LOG("SELF", Sev::warning)
1771 << "No scaling method found for " << bc.blockName;
1772 }
1773
1774 int nb_integration_pts = OP::getGaussPts().size2();
1775 int nb_base_functions = row_data.getN().size2();
1776 auto t_row_base = row_data.getFTensor0N();
1777
1778 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1779
1781 t_N(i) = t_normal(i);
1782 t_N.normalize();
1783
1785 t_P(i, j) = t_N(i) * t_N(j);
1787 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
1788
1790 t_d_res(i, j) = t_Q(i, j);
1791
1792 int rr = 0;
1793 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
1794 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
1795 OP::locMat, SPACE_DIM * rr);
1796 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1797 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
1798 t_mat(i, j) +=
1799 ((t_w * t_row_base) * (t_N(k) * t_col_base(k))) * t_d_res(i, j);
1800 ++t_mat;
1801 ++t_col_base;
1802 }
1803 ++t_row_base;
1804 }
1805
1806 for (; rr != nb_base_functions; ++rr)
1807 ++t_row_base;
1808
1809 ++t_w;
1810 ++t_normal;
1811 }
1812
1813 locMat *= OP::getMeasure();
1814 }
1815 }
1817}
1818
1820 return OP::iNtegrate(data);
1821}
1822
1824 EntData &col_data) {
1825 return OP::iNtegrate(row_data, col_data);
1826}
1827
1829 EntData &col_data) {
1830 return OP::iNtegrate(row_data, col_data);
1831}
1832
1833template <AssemblyType A>
1836
1837 double time = OP::getFEMethod()->ts_t;
1840 }
1841
1842 // get entity of face
1843 EntityHandle fe_ent = OP::getFEEntityHandle();
1844 // iterate over all boundary data
1845 for (auto &bc : (*bcDispPtr)) {
1846 // check if finite element entity is part of boundary condition
1847 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1848
1849 MatrixDouble analytical_expr;
1850 // placeholder to pass boundary block id to python
1851
1852 auto [block_name, v_analytical_expr] =
1853 getAnalyticalExpr(this, analytical_expr, bc.blockName);
1854
1855 int nb_dofs = data.getIndices().size();
1856
1857 int nb_integration_pts = OP::getGaussPts().size2();
1858 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1859 auto t_w = OP::getFTensor0IntegrationWeight();
1860 int nb_base_functions = data.getN().size2() / 3;
1861 auto t_row_base_fun = data.getFTensor1N<3>();
1862 auto t_coord = OP::getFTensor1CoordsAtGaussPts();
1863
1866
1867 // get bc data
1868 auto t_bc_disp = getFTensor1FromMat<3>(v_analytical_expr);
1869
1870 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1871 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1872
1873 int bb = 0;
1874 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1875 t_nf(i) +=
1876 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1877 ++t_nf;
1878 ++t_row_base_fun;
1879 }
1880 for (; bb != nb_base_functions; ++bb)
1881 ++t_row_base_fun;
1882
1883 ++t_bc_disp;
1884 ++t_coord;
1885 ++t_w;
1886 ++t_normal;
1887 }
1888 }
1889 }
1891}
1892
1894 return OP::iNtegrate(data);
1895}
1896
1899
1900 FTENSOR_INDEX(3, i);
1901
1902 int nb_dofs = data.getFieldData().size();
1903 int nb_integration_pts = getGaussPts().size2();
1904 int nb_base_functions = data.getN().size2();
1905
1906 double time = getFEMethod()->ts_t;
1909 }
1910
1911#ifndef NDEBUG
1912 if (this->locF.size() != nb_dofs)
1913 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1914 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
1915#endif // NDEBUG
1916
1917 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1919
1920 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
1921 auto t_row_base = data.getFTensor0N();
1922 auto t_w = getFTensor0IntegrationWeight();
1923 auto t_coords = getFTensor1CoordsAtGaussPts();
1924
1925 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
1926
1927 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1928
1929 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
1930 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
1931 int rr = 0;
1932 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1933 t_f(i) -= (time_scale * t_w * t_row_base * tau) * (t_val(i) * scale);
1934 ++t_row_base;
1935 ++t_f;
1936 }
1937
1938 for (; rr != nb_base_functions; ++rr)
1939 ++t_row_base;
1940 ++t_w;
1941 ++t_coords;
1942 }
1943 this->locF *= getMeasure();
1945 };
1946
1947 // get entity of face
1948 EntityHandle fe_ent = getFEEntityHandle();
1949 for (auto &bc : *(bcData)) {
1950 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1951
1952 double time_scale = 1;
1953 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1954 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1955 }
1956
1957 int nb_dofs = data.getFieldData().size();
1958 if (nb_dofs) {
1959
1960 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
1961 auto calc_tau = [](double, double y, double) {
1962 y -= 44;
1963 y /= (60 - 44);
1964 return -y * (y - 1) / 0.25;
1965 };
1966 CHKERR integrate_rhs(bc, calc_tau, time_scale);
1967 } else {
1968 CHKERR integrate_rhs(
1969 bc, [](double, double, double) { return 1; }, time_scale);
1970 }
1971 }
1972 }
1973 }
1975}
1976
1979
1980 FTENSOR_INDEX(3, i);
1981
1982 int nb_dofs = data.getFieldData().size();
1983 int nb_integration_pts = getGaussPts().size2();
1984 int nb_base_functions = data.getN().size2();
1985
1986 double time = getFEMethod()->ts_t;
1989 }
1990
1991#ifndef NDEBUG
1992 if (this->locF.size() != nb_dofs)
1993 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1994 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
1995#endif // NDEBUG
1996
1997 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1999
2000 auto val = bc.val;
2001 auto t_row_base = data.getFTensor0N();
2002 auto t_w = getFTensor0IntegrationWeight();
2003 auto t_coords = getFTensor1CoordsAtGaussPts();
2004 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
2005 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
2006
2007 auto t_grad_gamma_u = getFTensor2FromMat<3, 2>(*hybridGradDispPtr);
2008
2009 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2010
2011 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2012
2018
2022
2023 t_normal(i) = (FTensor::levi_civita<double>(i, j, k) * t_tangent1(j)) *
2024 t_tangent2(k);
2025 } else {
2026 t_normal(i) = (FTensor::levi_civita<double>(i, j, k) *
2027 (t_tangent1(j) + t_grad_gamma_u(j, N0))) *
2028 (t_tangent2(k) + t_grad_gamma_u(k, N1));
2029 }
2030 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2031 auto t_val = FTensor::Tensor1<double, 3>();
2032 t_val(i) = (time_scale * t_w * tau * scale * val) * t_normal(i);
2033
2034 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2035 int rr = 0;
2036 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2037 t_f(i) += t_row_base * t_val(i);
2038 ++t_row_base;
2039 ++t_f;
2040 }
2041
2042 for (; rr != nb_base_functions; ++rr)
2043 ++t_row_base;
2044 ++t_w;
2045 ++t_coords;
2046 ++t_tangent1;
2047 ++t_tangent2;
2048 ++t_grad_gamma_u;
2049 }
2050 this->locF /= 2.;
2051
2053 };
2054
2055 // get entity of face
2056 EntityHandle fe_ent = getFEEntityHandle();
2057 for (auto &bc : *(bcData)) {
2058 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2059
2060 double time_scale = 1;
2061 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2062 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2063 }
2064
2065 int nb_dofs = data.getFieldData().size();
2066 if (nb_dofs) {
2067 CHKERR integrate_rhs(
2068 bc, [](double, double, double) { return 1; }, time_scale);
2069 }
2070 }
2071 }
2073}
2074
2075template <AssemblyType A>
2078 EntData &col_data) {
2080
2084 }
2085
2086 double time = OP::getFEMethod()->ts_t;
2089 }
2090
2091 int nb_base_functions = row_data.getN().size2();
2092 int row_nb_dofs = row_data.getIndices().size();
2093 int col_nb_dofs = col_data.getIndices().size();
2094 int nb_integration_pts = OP::getGaussPts().size2();
2095 auto &locMat = OP::locMat;
2096 locMat.resize(row_nb_dofs, col_nb_dofs, false);
2097 locMat.clear();
2098
2099auto integrate_lhs = [&](auto &bc, auto calc_tau, double time_scale) {
2101
2102 auto val = bc.val;
2103 auto t_row_base = row_data.getFTensor0N();
2104 auto t_w = OP::getFTensor0IntegrationWeight();
2105 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
2106 auto t_tangent1 = OP::getFTensor1Tangent1AtGaussPts();
2107 auto t_tangent2 = OP::getFTensor1Tangent2AtGaussPts();
2108
2109 auto t_grad_gamma_u = getFTensor2FromMat<3, 2>(*hybridGradDispPtr);
2111
2112 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2113
2118
2121
2122 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2123 auto t_val = time_scale * t_w * tau * val;
2124
2125 int rr = 0;
2126 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
2127 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
2128 locMat, SPACE_DIM * rr);
2129 auto t_diff_col_base = col_data.getFTensor1DiffN<2>(gg, 0);
2130 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
2132 t_normal_du(i, l) = (FTensor::levi_civita<double>(i, j, k) *
2133 (t_tangent2(k) + t_grad_gamma_u(k, N1))) *
2134 t_kd(j, l) * t_diff_col_base(N0)
2135
2136 +
2137
2138 (FTensor::levi_civita<double>(i, j, k) *
2139 (t_tangent1(j) + t_grad_gamma_u(j, N0))) *
2140 t_kd(k, l) * t_diff_col_base(N1);
2141
2142 t_mat(i, j) += (t_w * t_row_base) * t_val * t_normal_du(i, j);
2143 ++t_mat;
2144 ++t_diff_col_base;
2145 }
2146 ++t_row_base;
2147 }
2148
2149 for (; rr != nb_base_functions; ++rr)
2150 ++t_row_base;
2151 ++t_w;
2152 ++t_coords;
2153 ++t_tangent1;
2154 ++t_tangent2;
2155 ++t_grad_gamma_u;
2156 }
2157
2158 OP::locMat /= 2.;
2159
2161 };
2162
2163 // get entity of face
2164 EntityHandle fe_ent = OP::getFEEntityHandle();
2165 for (auto &bc : *(bcData)) {
2166 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2167
2168 double time_scale = 1;
2169 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2170 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2171 }
2172
2173 int nb_dofs = row_data.getFieldData().size();
2174 if (nb_dofs) {
2175 CHKERR integrate_lhs(
2176 bc, [](double, double, double) { return 1; }, time_scale);
2177 }
2178 }
2179 }
2180
2182
2183}
2184
2186 EntData &col_data) {
2187 return OP::iNtegrate(row_data, col_data);
2188}
2189
2190
2193
2194 FTENSOR_INDEX(3, i);
2195
2196 int nb_dofs = data.getFieldData().size();
2197 int nb_integration_pts = getGaussPts().size2();
2198 int nb_base_functions = data.getN().size2();
2199
2200 double time = getFEMethod()->ts_t;
2203 }
2204
2205#ifndef NDEBUG
2206 if (this->locF.size() != nb_dofs)
2207 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2208 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
2209#endif // NDEBUG
2210
2211 // get entity of face
2212 EntityHandle fe_ent = getFEEntityHandle();
2213 for (auto &bc : *(bcData)) {
2214 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2215
2216 MatrixDouble analytical_expr;
2217 // placeholder to pass boundary block id to python
2218 auto [block_name, v_analytical_expr] =
2219 getAnalyticalExpr(this, analytical_expr, bc.blockName);
2220 auto t_val =
2221 getFTensor1FromMat<3>(v_analytical_expr);
2222 auto t_row_base = data.getFTensor0N();
2223 auto t_w = getFTensor0IntegrationWeight();
2224 auto t_coords = getFTensor1CoordsAtGaussPts();
2225
2226 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2227
2228 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2229
2230 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2231 int rr = 0;
2232 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2233 t_f(i) -= t_w * t_row_base * (t_val(i) * scale);
2234 ++t_row_base;
2235 ++t_f;
2236 }
2237
2238 for (; rr != nb_base_functions; ++rr)
2239 ++t_row_base;
2240 ++t_w;
2241 ++t_coords;
2242 ++t_val;
2243 }
2244 this->locF *= getMeasure();
2245 }
2246 }
2248}
2249
2251 EntData &col_data) {
2253 int nb_integration_pts = row_data.getN().size1();
2254 int row_nb_dofs = row_data.getIndices().size();
2255 int col_nb_dofs = col_data.getIndices().size();
2256 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2258 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2));
2259 };
2260 FTensor::Index<'i', 3> i;
2261 auto v = getVolume();
2262 auto t_w = getFTensor0IntegrationWeight();
2263 int row_nb_base_functions = row_data.getN().size2();
2264 auto t_row_base_fun = row_data.getFTensor0N();
2265 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2266 double a = v * t_w;
2267 int rr = 0;
2268 for (; rr != row_nb_dofs / 3; ++rr) {
2269 auto t_col_diff_base_fun = col_data.getFTensor2DiffN<3, 3>(gg, 0);
2270 auto t_m = get_ftensor1(K, 3 * rr, 0);
2271 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2272 double div_col_base = t_col_diff_base_fun(i, i);
2273 t_m(i) -= a * t_row_base_fun * div_col_base;
2274 ++t_m;
2275 ++t_col_diff_base_fun;
2276 }
2277 ++t_row_base_fun;
2278 }
2279 for (; rr != row_nb_base_functions; ++rr)
2280 ++t_row_base_fun;
2281 ++t_w;
2282 }
2284}
2285
2287 EntData &col_data) {
2289
2290 if (alphaW < std::numeric_limits<double>::epsilon() &&
2291 alphaRho < std::numeric_limits<double>::epsilon())
2293
2294 const int nb_integration_pts = row_data.getN().size1();
2295 const int row_nb_dofs = row_data.getIndices().size();
2296 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2298 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2)
2299
2300 );
2301 };
2302 FTensor::Index<'i', 3> i;
2303
2304 auto v = getVolume();
2305 auto t_w = getFTensor0IntegrationWeight();
2306
2307 auto piola_scale = dataAtPts->piolaScale;
2308 auto alpha_w = alphaW / piola_scale;
2309 auto alpha_rho = alphaRho / piola_scale;
2310
2311 int row_nb_base_functions = row_data.getN().size2();
2312 auto t_row_base_fun = row_data.getFTensor0N();
2313
2314 double ts_scale = alpha_w * getTSa();
2315 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon())
2316 ts_scale += alpha_rho * getTSaa();
2317
2318 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2319 double a = v * t_w * ts_scale;
2320
2321 int rr = 0;
2322 for (; rr != row_nb_dofs / 3; ++rr) {
2323
2324 auto t_col_base_fun = row_data.getFTensor0N(gg, 0);
2325 auto t_m = get_ftensor1(K, 3 * rr, 0);
2326 for (int cc = 0; cc != row_nb_dofs / 3; ++cc) {
2327 const double b = a * t_row_base_fun * t_col_base_fun;
2328 t_m(i) += b;
2329 ++t_m;
2330 ++t_col_base_fun;
2331 }
2332
2333 ++t_row_base_fun;
2334 }
2335
2336 for (; rr != row_nb_base_functions; ++rr)
2337 ++t_row_base_fun;
2338
2339 ++t_w;
2340 }
2341
2343}
2344
2346 EntData &col_data) {
2348
2354
2355 int nb_integration_pts = row_data.getN().size1();
2356 int row_nb_dofs = row_data.getIndices().size();
2357 int col_nb_dofs = col_data.getIndices().size();
2358 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
2360
2361 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2362
2363 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2364
2365 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
2366
2367 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
2368
2369 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
2370
2371 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2));
2372 };
2373
2374 auto v = getVolume();
2375 auto t_w = getFTensor0IntegrationWeight();
2376
2377 int row_nb_base_functions = row_data.getN().size2();
2378 auto t_row_base_fun = row_data.getFTensor0N();
2379
2380 auto t_approx_P_adjoint_log_du_dP =
2381 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
2382
2383 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2384 double a = v * t_w;
2385 int rr = 0;
2386 for (; rr != row_nb_dofs / 6; ++rr) {
2387
2388 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
2389 auto t_m = get_ftensor3(K, 6 * rr, 0);
2390
2391 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2392 t_m(L, i) -=
2393 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(j)) *
2394 t_row_base_fun;
2395 ++t_col_base_fun;
2396 ++t_m;
2397 }
2398
2399 ++t_row_base_fun;
2400 }
2401 for (; rr != row_nb_base_functions; ++rr)
2402 ++t_row_base_fun;
2403 ++t_w;
2404 ++t_approx_P_adjoint_log_du_dP;
2405 }
2406
2408}
2409
2411 EntData &col_data) {
2413
2419
2420 int nb_integration_pts = row_data.getN().size1();
2421 int row_nb_dofs = row_data.getIndices().size();
2422 int col_nb_dofs = col_data.getIndices().size();
2423 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2425 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c), &m(r + 3, c), &m(r + 4, c),
2426 &m(r + 5, c));
2427 };
2428
2429 auto v = getVolume();
2430 auto t_w = getFTensor0IntegrationWeight();
2431 auto t_row_base_fun = row_data.getFTensor0N();
2432
2433 int row_nb_base_functions = row_data.getN().size2();
2434
2435 auto t_approx_P_adjoint_log_du_dP =
2436 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
2437
2438 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2439 double a = v * t_w;
2440 int rr = 0;
2441 for (; rr != row_nb_dofs / 6; ++rr) {
2442 auto t_m = get_ftensor2(K, 6 * rr, 0);
2443 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
2444 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2445 t_m(L) -=
2446 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(i, j)) *
2447 t_row_base_fun;
2448 ++t_m;
2449 ++t_col_base_fun;
2450 }
2451 ++t_row_base_fun;
2452 }
2453 for (; rr != row_nb_base_functions; ++rr)
2454 ++t_row_base_fun;
2455 ++t_w;
2456 ++t_approx_P_adjoint_log_du_dP;
2457 }
2459}
2460
2462 EntData &col_data) {
2464
2466 auto t_L = symm_L_tensor();
2467
2468 int row_nb_dofs = row_data.getIndices().size();
2469 int col_nb_dofs = col_data.getIndices().size();
2470 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
2472
2473 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2474
2475 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2476
2477 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
2478
2479 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
2480
2481 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
2482
2483 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2)
2484
2485 );
2486 };
2487 FTensor::Index<'i', 3> i;
2488 FTensor::Index<'j', 3> j;
2489 FTensor::Index<'k', 3> k;
2490 FTensor::Index<'m', 3> m;
2491 FTensor::Index<'n', 3> n;
2492
2493 auto v = getVolume();
2494 auto t_w = getFTensor0IntegrationWeight();
2495 auto t_approx_P_adjoint_log_du_domega =
2496 getFTensor2FromMat<3, size_symm>(dataAtPts->adjointPdUdOmegaAtPts);
2497
2498 int row_nb_base_functions = row_data.getN().size2();
2499 auto t_row_base_fun = row_data.getFTensor0N();
2500
2501 int nb_integration_pts = row_data.getN().size1();
2502
2503 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2504 double a = v * t_w;
2505
2506 int rr = 0;
2507 for (; rr != row_nb_dofs / 6; ++rr) {
2508 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2509 auto t_m = get_ftensor3(K, 6 * rr, 0);
2510 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2511 double v = a * t_row_base_fun * t_col_base_fun;
2512 t_m(L, k) -= v * t_approx_P_adjoint_log_du_domega(k, L);
2513 ++t_m;
2514 ++t_col_base_fun;
2515 }
2516 ++t_row_base_fun;
2517 }
2518
2519 for (; rr != row_nb_base_functions; ++rr)
2520 ++t_row_base_fun;
2521
2522 ++t_w;
2523 ++t_approx_P_adjoint_log_du_domega;
2524 }
2525
2527}
2528
2530 EntData &col_data) {
2532 int nb_integration_pts = getGaussPts().size2();
2533 int row_nb_dofs = row_data.getIndices().size();
2534 int col_nb_dofs = col_data.getIndices().size();
2535 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2537 size_symm>{
2538
2539 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2), &m(r + 0, c + 3),
2540 &m(r + 0, c + 4), &m(r + 0, c + 5),
2541
2542 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2), &m(r + 1, c + 3),
2543 &m(r + 1, c + 4), &m(r + 1, c + 5),
2544
2545 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2), &m(r + 2, c + 3),
2546 &m(r + 2, c + 4), &m(r + 2, c + 5)
2547
2548 };
2549 };
2550
2553
2554 auto v = getVolume();
2555 auto t_w = getFTensor0IntegrationWeight();
2556 auto t_levi_kirchhoff_du = getFTensor2FromMat<3, size_symm>(
2557 dataAtPts->leviKirchhoffdLogStreatchAtPts);
2558 int row_nb_base_functions = row_data.getN().size2();
2559 auto t_row_base_fun = row_data.getFTensor0N();
2560 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2561 double a = v * t_w;
2562 int rr = 0;
2563 for (; rr != row_nb_dofs / 3; ++rr) {
2564 auto t_m = get_ftensor2(K, 3 * rr, 0);
2565 const double b = a * t_row_base_fun;
2566 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2567 for (int cc = 0; cc != col_nb_dofs / size_symm; ++cc) {
2568 t_m(k, L) -= (b * t_col_base_fun) * t_levi_kirchhoff_du(k, L);
2569 ++t_m;
2570 ++t_col_base_fun;
2571 }
2572 ++t_row_base_fun;
2573 }
2574 for (; rr != row_nb_base_functions; ++rr) {
2575 ++t_row_base_fun;
2576 }
2577 ++t_w;
2578 ++t_levi_kirchhoff_du;
2579 }
2581}
2582
2584 EntData &col_data) {
2586
2593
2594 int nb_integration_pts = getGaussPts().size2();
2595 int row_nb_dofs = row_data.getIndices().size();
2596 int col_nb_dofs = col_data.getIndices().size();
2597 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2599
2600 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2601
2602 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2603
2604 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2605
2606 );
2607 };
2608
2609 auto v = getVolume();
2610 auto t_w = getFTensor0IntegrationWeight();
2611
2612 int row_nb_base_functions = row_data.getN().size2();
2613 auto t_row_base_fun = row_data.getFTensor0N();
2614 auto t_levi_kirchhoff_dP =
2615 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
2616
2617 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2618 double a = v * t_w;
2619 int rr = 0;
2620 for (; rr != row_nb_dofs / 3; ++rr) {
2621 double b = a * t_row_base_fun;
2622 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
2623 auto t_m = get_ftensor2(K, 3 * rr, 0);
2624 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2625 t_m(m, i) -= b * (t_levi_kirchhoff_dP(m, i, k) * t_col_base_fun(k));
2626 ++t_m;
2627 ++t_col_base_fun;
2628 }
2629 ++t_row_base_fun;
2630 }
2631 for (; rr != row_nb_base_functions; ++rr) {
2632 ++t_row_base_fun;
2633 }
2634
2635 ++t_w;
2636 ++t_levi_kirchhoff_dP;
2637 }
2639}
2640
2642 EntData &col_data) {
2644 int nb_integration_pts = getGaussPts().size2();
2645 int row_nb_dofs = row_data.getIndices().size();
2646 int col_nb_dofs = col_data.getIndices().size();
2647
2648 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2650 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c));
2651 };
2652
2653 FTENSOR_INDEX(3, i);
2654 FTENSOR_INDEX(3, k);
2655 FTENSOR_INDEX(3, m);
2656
2657 auto v = getVolume();
2658 auto t_w = getFTensor0IntegrationWeight();
2659 auto t_levi_kirchoff_dP =
2660 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
2661
2662 int row_nb_base_functions = row_data.getN().size2();
2663 auto t_row_base_fun = row_data.getFTensor0N();
2664
2665 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2666 double a = v * t_w;
2667 int rr = 0;
2668 for (; rr != row_nb_dofs / 3; ++rr) {
2669 double b = a * t_row_base_fun;
2670 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
2671 auto t_m = get_ftensor1(K, 3 * rr, 0);
2672 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2673 t_m(m) -= b * (t_levi_kirchoff_dP(m, i, k) * t_col_base_fun(i, k));
2674 ++t_m;
2675 ++t_col_base_fun;
2676 }
2677 ++t_row_base_fun;
2678 }
2679
2680 for (; rr != row_nb_base_functions; ++rr) {
2681 ++t_row_base_fun;
2682 }
2683 ++t_w;
2684 ++t_levi_kirchoff_dP;
2685 }
2687}
2688
2690 EntData &col_data) {
2692 int nb_integration_pts = getGaussPts().size2();
2693 int row_nb_dofs = row_data.getIndices().size();
2694 int col_nb_dofs = col_data.getIndices().size();
2695 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2697
2698 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2699
2700 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2701
2702 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2703
2704 );
2705 };
2706 FTensor::Index<'i', 3> i;
2707 FTensor::Index<'j', 3> j;
2708 FTensor::Index<'k', 3> k;
2709 FTensor::Index<'l', 3> l;
2710 FTensor::Index<'m', 3> m;
2711 FTensor::Index<'n', 3> n;
2712
2714
2715 auto v = getVolume();
2716 auto ts_a = getTSa();
2717 auto t_w = getFTensor0IntegrationWeight();
2718 auto t_levi_kirchhoff_domega =
2719 getFTensor2FromMat<3, 3>(dataAtPts->leviKirchhoffdOmegaAtPts);
2720 int row_nb_base_functions = row_data.getN().size2();
2721 auto t_row_base_fun = row_data.getFTensor0N();
2722 auto t_row_grad_fun = row_data.getFTensor1DiffN<3>();
2723
2724 // auto time_step = getTStimeStep();
2725 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2726 double a = v * t_w;
2727 double c = (a * alphaOmega) * (ts_a /*/ time_step*/);
2728
2729 int rr = 0;
2730 for (; rr != row_nb_dofs / 3; ++rr) {
2731 auto t_m = get_ftensor2(K, 3 * rr, 0);
2732 const double b = a * t_row_base_fun;
2733 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2734 auto t_col_grad_fun = col_data.getFTensor1DiffN<3>(gg, 0);
2735 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2736 t_m(k, l) -= (b * t_col_base_fun) * t_levi_kirchhoff_domega(k, l);
2737 t_m(k, l) += t_kd(k, l) * (c * (t_row_grad_fun(i) * t_col_grad_fun(i)));
2738 ++t_m;
2739 ++t_col_base_fun;
2740 ++t_col_grad_fun;
2741 }
2742 ++t_row_base_fun;
2743 ++t_row_grad_fun;
2744 }
2745 for (; rr != row_nb_base_functions; ++rr) {
2746 ++t_row_base_fun;
2747 ++t_row_grad_fun;
2748 }
2749 ++t_w;
2750 ++t_levi_kirchhoff_domega;
2751 }
2753}
2754
2756 EntData &col_data) {
2758 if (dataAtPts->matInvD.size1() == size_symm &&
2759 dataAtPts->matInvD.size2() == size_symm) {
2760 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2761 } else {
2762 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2763 }
2765};
2766
2767template <int S>
2769 EntData &col_data) {
2771
2772 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2774
2775 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2776
2777 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2778
2779 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2780
2781 );
2782 };
2783
2784 int nb_integration_pts = getGaussPts().size2();
2785 int row_nb_dofs = row_data.getIndices().size();
2786 int col_nb_dofs = col_data.getIndices().size();
2787
2788 auto v = getVolume();
2789 auto t_w = getFTensor0IntegrationWeight();
2790 int row_nb_base_functions = row_data.getN().size2() / 3;
2791
2796
2797 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2798 &*dataAtPts->matInvD.data().begin());
2799
2800 auto t_row_base = row_data.getFTensor1N<3>();
2801 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2802 double a = v * t_w;
2803
2804 int rr = 0;
2805 for (; rr != row_nb_dofs / 3; ++rr) {
2806 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2807 auto t_m = get_ftensor2(K, 3 * rr, 0);
2808 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2809 t_m(i, k) -= a * t_row_base(j) * (t_inv_D(i, j, k, l) * t_col_base(l));
2810 ++t_m;
2811 ++t_col_base;
2812 }
2813
2814 ++t_row_base;
2815 }
2816
2817 for (; rr != row_nb_base_functions; ++rr)
2818 ++t_row_base;
2819
2820 ++t_w;
2821 ++t_inv_D;
2822 }
2824}
2825
2828 EntData &col_data) {
2830 if (dataAtPts->matInvD.size1() == size_symm &&
2831 dataAtPts->matInvD.size2() == size_symm) {
2832 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2833 } else {
2834 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2835 }
2837};
2838
2839template <int S>
2842 EntData &col_data) {
2844
2845 int nb_integration_pts = getGaussPts().size2();
2846 int row_nb_dofs = row_data.getIndices().size();
2847 int col_nb_dofs = col_data.getIndices().size();
2848
2849 auto v = getVolume();
2850 auto t_w = getFTensor0IntegrationWeight();
2851 int row_nb_base_functions = row_data.getN().size2() / 9;
2852
2857
2858 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2859 &*dataAtPts->matInvD.data().begin());
2860
2861 auto t_row_base = row_data.getFTensor2N<3, 3>();
2862 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2863 double a = v * t_w;
2864
2865 int rr = 0;
2866 for (; rr != row_nb_dofs; ++rr) {
2867 auto t_col_base = col_data.getFTensor2N<3, 3>(gg, 0);
2868 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2869 K(rr, cc) -=
2870 a * (t_row_base(i, j) * (t_inv_D(i, j, k, l) * t_col_base(k, l)));
2871 ++t_col_base;
2872 }
2873
2874 ++t_row_base;
2875 }
2876
2877 for (; rr != row_nb_base_functions; ++rr)
2878 ++t_row_base;
2879 ++t_w;
2880 ++t_inv_D;
2881 }
2883}
2884
2886 EntData &col_data) {
2888 if (dataAtPts->matInvD.size1() == size_symm &&
2889 dataAtPts->matInvD.size2() == size_symm) {
2890 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2891 } else {
2892 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2893 }
2895};
2896
2897template <int S>
2900 EntData &col_data) {
2902
2903 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2905
2906 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2)
2907
2908 );
2909 };
2910
2911 int nb_integration_pts = getGaussPts().size2();
2912 int row_nb_dofs = row_data.getIndices().size();
2913 int col_nb_dofs = col_data.getIndices().size();
2914
2915 auto v = getVolume();
2916 auto t_w = getFTensor0IntegrationWeight();
2917 int row_nb_base_functions = row_data.getN().size2() / 9;
2918
2925
2926 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2927 &*dataAtPts->matInvD.data().begin());
2928
2929 auto t_row_base = row_data.getFTensor2N<3, 3>();
2930 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2931 double a = v * t_w;
2932
2933 auto t_m = get_ftensor1(K, 0, 0);
2934
2935 int rr = 0;
2936 for (; rr != row_nb_dofs; ++rr) {
2937 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2938 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2939 t_m(k) -= a * (t_row_base(i, j) * t_inv_D(i, j, k, l)) * t_col_base(l);
2940 ++t_col_base;
2941 ++t_m;
2942 }
2943
2944 ++t_row_base;
2945 }
2946
2947 for (; rr != row_nb_base_functions; ++rr)
2948 ++t_row_base;
2949 ++t_w;
2950 ++t_inv_D;
2951 }
2953}
2954
2956 EntData &col_data) {
2958
2965
2966 int nb_integration_pts = row_data.getN().size1();
2967 int row_nb_dofs = row_data.getIndices().size();
2968 int col_nb_dofs = col_data.getIndices().size();
2969
2970 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2972
2973 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2974
2975 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2976
2977 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2978
2979 );
2980 };
2981
2982 auto v = getVolume();
2983 auto t_w = getFTensor0IntegrationWeight();
2984 int row_nb_base_functions = row_data.getN().size2() / 3;
2985 auto t_row_base_fun = row_data.getFTensor1N<3>();
2986
2987 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
2988
2989 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2990 double a = v * t_w;
2991
2992 int rr = 0;
2993 for (; rr != row_nb_dofs / 3; ++rr) {
2994
2996 t_PRT(i, k) = t_row_base_fun(j) * t_h_domega(i, j, k);
2997
2998 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2999 auto t_m = get_ftensor2(K, 3 * rr, 0);
3000 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3001 t_m(i, j) -= (a * t_col_base_fun) * t_PRT(i, j);
3002 ++t_m;
3003 ++t_col_base_fun;
3004 }
3005
3006 ++t_row_base_fun;
3007 }
3008
3009 for (; rr != row_nb_base_functions; ++rr)
3010 ++t_row_base_fun;
3011 ++t_w;
3012 ++t_h_domega;
3013 }
3015}
3016
3019 EntData &col_data) {
3021
3028
3029 int nb_integration_pts = row_data.getN().size1();
3030 int row_nb_dofs = row_data.getIndices().size();
3031 int col_nb_dofs = col_data.getIndices().size();
3032
3033 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3035 &m(r, c + 0), &m(r, c + 1), &m(r, c + 2));
3036 };
3037
3038 auto v = getVolume();
3039 auto t_w = getFTensor0IntegrationWeight();
3040 int row_nb_base_functions = row_data.getN().size2() / 9;
3041 auto t_row_base_fun = row_data.getFTensor2N<3, 3>();
3042
3043 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
3044 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3045 double a = v * t_w;
3046
3047 int rr = 0;
3048 for (; rr != row_nb_dofs; ++rr) {
3049
3051 t_PRT(k) = t_row_base_fun(i, j) * t_h_domega(i, j, k);
3052
3053 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
3054 auto t_m = get_ftensor2(K, rr, 0);
3055 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3056 t_m(j) -= (a * t_col_base_fun) * t_PRT(j);
3057 ++t_m;
3058 ++t_col_base_fun;
3059 }
3060
3061 ++t_row_base_fun;
3062 }
3063
3064 for (; rr != row_nb_base_functions; ++rr)
3065 ++t_row_base_fun;
3066
3067 ++t_w;
3068 ++t_h_domega;
3069 }
3071}
3072
3074 EntData &data) {
3076
3077 if (tagSense != getSkeletonSense())
3079
3080 auto get_tag = [&](auto name) {
3081 auto &mob = getPtrFE()->mField.get_moab();
3082 Tag tag;
3083 CHK_MOAB_THROW(mob.tag_get_handle(name, tag), "get tag");
3084 return tag;
3085 };
3086
3087 auto get_tag_value = [&](auto &&tag, int dim) {
3088 auto &mob = getPtrFE()->mField.get_moab();
3089 auto face = getSidePtrFE()->getFEEntityHandle();
3090 std::vector<double> value(dim);
3091 CHK_MOAB_THROW(mob.tag_get_data(tag, &face, 1, value.data()), "set tag");
3092 return value;
3093 };
3094
3095 auto create_tag = [this](const std::string tag_name, const int size) {
3096 double def_VAL[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
3097 Tag th;
3098 CHKERR postProcMesh.tag_get_handle(tag_name.c_str(), size, MB_TYPE_DOUBLE,
3099 th, MB_TAG_CREAT | MB_TAG_SPARSE,
3100 def_VAL);
3101 return th;
3102 };
3103
3104 Tag th_cauchy_streess = create_tag("CauchyStress", 9);
3105 Tag th_detF = create_tag("detF", 1);
3106 Tag th_traction = create_tag("traction", 3);
3107 Tag th_disp_error = create_tag("DisplacementError", 1);
3108
3109 Tag th_energy = create_tag("Energy", 1);
3110
3111 auto t_w = getFTensor1FromMat<3>(dataAtPts->wL2AtPts);
3112 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
3113 auto t_approx_P = getFTensor2FromMat<3, 3>(dataAtPts->approxPAtPts);
3114
3115 auto t_normal = getFTensor1NormalsAtGaussPts();
3116 auto t_disp = getFTensor1FromMat<3>(dataAtPts->wH1AtPts);
3117
3118 // auto sense = getSkeletonSense();
3119
3120 auto next = [&]() {
3121 ++t_w;
3122 ++t_h;
3123 ++t_approx_P;
3124 ++t_normal;
3125 ++t_disp;
3126 };
3127
3128 if (dataAtPts->energyAtPts.size() == 0) {
3129 // that is for case that energy is not calculated
3130 dataAtPts->energyAtPts.resize(getGaussPts().size2());
3131 dataAtPts->energyAtPts.clear();
3132 }
3133 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
3134
3135 FTensor::Index<'i', 3> i;
3136 FTensor::Index<'j', 3> j;
3137 FTensor::Index<'k', 3> k;
3138 FTensor::Index<'l', 3> l;
3139
3140 auto set_float_precision = [](const double x) {
3141 if (std::abs(x) < std::numeric_limits<float>::epsilon())
3142 return 0.;
3143 else
3144 return x;
3145 };
3146
3147 // scalars
3148 auto save_scal_tag = [&](auto &th, auto v, const int gg) {
3150 v = set_float_precision(v);
3151 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1, &v);
3153 };
3154
3155 // vectors
3156 VectorDouble3 v(3);
3157 FTensor::Tensor1<FTensor::PackPtr<double *, 0>, 3> t_v(&v[0], &v[1], &v[2]);
3158 auto save_vec_tag = [&](auto &th, auto &t_d, const int gg) {
3160 t_v(i) = t_d(i);
3161 for (auto &a : v.data())
3162 a = set_float_precision(a);
3163 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
3164 &*v.data().begin());
3166 };
3167
3168 // tensors
3169
3170 MatrixDouble3by3 m(3, 3);
3172 &m(0, 0), &m(0, 1), &m(0, 2),
3173
3174 &m(1, 0), &m(1, 1), &m(1, 2),
3175
3176 &m(2, 0), &m(2, 1), &m(2, 2));
3177
3178 auto save_mat_tag = [&](auto &th, auto &t_d, const int gg) {
3180 t_m(i, j) = t_d(i, j);
3181 for (auto &v : m.data())
3182 v = set_float_precision(v);
3183 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
3184 &*m.data().begin());
3186 };
3187
3188 const auto nb_gauss_pts = getGaussPts().size2();
3189 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
3190
3191 FTensor::Tensor1<double, 3> t_traction;
3192 t_traction(i) = t_approx_P(i, j) * t_normal(j) / t_normal.l2();
3193 // vectors
3194 t_traction(i) *= tagSense;
3195 CHKERR save_vec_tag(th_traction, t_traction, gg);
3196
3197 double u_error = sqrt((t_disp(i) - t_w(i)) * (t_disp(i) - t_w(i)));
3198 if (!std::isfinite(u_error))
3199 u_error = -1.;
3200 CHKERR save_scal_tag(th_disp_error, u_error, gg);
3201 CHKERR save_scal_tag(th_energy, t_energy, gg);
3202
3203 const double jac = determinantTensor3by3(t_h);
3205 t_cauchy(i, j) = (1. / jac) * (t_approx_P(i, k) * t_h(j, k));
3206 CHKERR save_mat_tag(th_cauchy_streess, t_cauchy, gg);
3207 CHKERR postProcMesh.tag_set_data(th_detF, &mapGaussPts[gg], 1, &jac);
3208
3209 next();
3210 }
3211
3213}
3214
3216 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3217 std::vector<FieldSpace> spaces, std::string geom_field_name,
3218 boost::shared_ptr<Range> crack_front_edges_ptr) {
3220
3221 constexpr bool scale_l2 = false;
3222
3223 if (scale_l2) {
3224 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3225 "Scale L2 Ainsworth Legendre base is not implemented");
3226 }
3227
3228 CHKERR MoFEM::AddHOOps<2, 3, 3>::add(pipeline, spaces, geom_field_name);
3229
3231}
3232
3234 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3235 std::vector<FieldSpace> spaces, std::string geom_field_name,
3236 boost::shared_ptr<Range> crack_front_edges_ptr) {
3238
3239 constexpr bool scale_l2 = false;
3240
3241 if (scale_l2) {
3242 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3243 "Scale L2 Ainsworth Legendre base is not implemented");
3244 }
3245
3246 CHKERR MoFEM::AddHOOps<2, 2, 3>::add(pipeline, spaces, geom_field_name);
3247
3249}
3250
3252 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3253 std::vector<FieldSpace> spaces, std::string geom_field_name,
3254 boost::shared_ptr<Range> crack_front_edges_ptr,
3255 boost::shared_ptr<MatrixDouble> jac, boost::shared_ptr<VectorDouble> det,
3256 boost::shared_ptr<MatrixDouble> inv_jac) {
3258
3260 auto jac = boost::make_shared<MatrixDouble>();
3261 auto det = boost::make_shared<VectorDouble>();
3263 geom_field_name, jac));
3264 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3265 pipeline.push_back(
3267 }
3268
3269 constexpr bool scale_l2_ainsworth_legendre_base = false;
3270
3271 if (scale_l2_ainsworth_legendre_base) {
3272
3274 : public MoFEM::OpCalculateVectorFieldGradient<SPACE_DIM, SPACE_DIM> {
3275
3277
3278 OpCalculateVectorFieldGradient(const std::string &field_name,
3279 boost::shared_ptr<MatrixDouble> jac,
3280 boost::shared_ptr<Range> edges_ptr)
3281 : OP(field_name, jac), edgesPtr(edges_ptr) {}
3282
3283 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
3284
3285 auto ent = data.getFieldEntities().size()
3286 ? data.getFieldEntities()[0]->getEnt()
3287 : 0;
3288
3289 if (type == MBEDGE && edgesPtr->find(ent) != edgesPtr->end()) {
3290 return 0;
3291 } else {
3292 return OP::doWork(side, type, data);
3293 }
3294 };
3295
3296 private:
3297 boost::shared_ptr<Range> edgesPtr;
3298 };
3299
3300 auto jac = boost::make_shared<MatrixDouble>();
3301 auto det = boost::make_shared<VectorDouble>();
3302 pipeline.push_back(new OpCalculateVectorFieldGradient(
3303 geom_field_name, jac,
3304 EshelbianCore::setSingularity ? crack_front_edges_ptr
3305 : boost::make_shared<Range>()));
3306 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3307 pipeline.push_back(new OpScaleBaseBySpaceInverseOfMeasure(
3309 }
3310
3311 CHKERR MoFEM::AddHOOps<3, 3, 3>::add(pipeline, spaces, geom_field_name,
3312 jac, det, inv_jac);
3313
3315}
3316
3317/**
3318 * @brief Caluclate face material force and normal pressure at gauss points
3319 *
3320 * @param side
3321 * @param type
3322 * @param data
3323 * @return MoFEMErrorCode
3324 *
3325 * Reconstruct the full gradient \f$U=\nabla u\f$ on a surface from the symmetric part and the surface gradient.
3326 *
3327 * @details
3328 * Inputs:
3329 * - \c t_strain : \f$\varepsilon=\tfrac12(U+U^\top)\f$ (symmetric strain on S),
3330 * - \c t_grad_u_gamma : \f$u^\Gamma = U P\f$ (right-projected/surface gradient), with \f$P=I-\mathbf N\otimes\mathbf N\f$,
3331 * - \c t_normal : (possibly non‑unit) surface normal.
3332 *
3333 * Procedure (pointwise on S):
3334 * 1) Normalize the normal \f$\mathbf n=\mathbf N/\|\mathbf N\|\f$.
3335 * 2) Form the residual \f$R=\varepsilon-\operatorname{sym}(u^\Gamma)\f$, where
3336 * \f$\operatorname{sym}(A)=\tfrac12(A+A^\top)\f$.
3337 * 3) Recover the normal directional derivative (a vector)
3338 * \f$\mathbf v=\partial_{\mathbf n}u=2R\mathbf n-(\mathbf n^\top R\,\mathbf n)\,\mathbf n\f$.
3339 * 4) Assemble the full gradient
3340 * \f$U = u^\Gamma + \mathbf v\otimes \mathbf n\f$.
3341 *
3342 * Properties (sanity checks):
3343 * - \f$\tfrac12(U+U^\top)=\varepsilon\f$ (matches the given symmetric part),
3344 * - \f$U P = u^\Gamma\f$ (tangential/right-projected columns unchanged),
3345 * - Only the **normal column** is updated via \f$\mathbf v\otimes\mathbf n\f$.
3346 *
3347 * Mapping to variables in this snippet:
3348 * - \f$\varepsilon \leftrightarrow\f$ \c t_strain,
3349 * - \f$u^\Gamma \leftrightarrow\f$ \c t_grad_u_gamma,
3350 * - \f$\mathbf N \leftrightarrow\f$ \c t_normal (normalized into \c t_N),
3351 * - \f$R \leftrightarrow\f$ \c t_R,
3352 * - \f$U \leftrightarrow\f$ \c t_grad_u.
3353 *
3354 * @pre \c t_normal is nonzero; \c t_strain is symmetric.
3355 * @note All indices use Einstein summation; computation is local to the surface point.
3356 *
3357*/
3359 EntData &data) {
3361
3374
3375 dataAtPts->faceMaterialForceAtPts.resize(3, getGaussPts().size2(), false);
3376 dataAtPts->normalPressureAtPts.resize(getGaussPts().size2(), false);
3377 if (getNinTheLoop() == 0) {
3378 dataAtPts->faceMaterialForceAtPts.clear();
3379 dataAtPts->normalPressureAtPts.clear();
3380 }
3381 auto loop_size = getLoopSize();
3382 if (loop_size == 1) {
3383 auto numebered_fe_ptr = getSidePtrFE()->numeredEntFiniteElementPtr;
3384 auto pstatus = numebered_fe_ptr->getPStatus();
3385 if (pstatus & (PSTATUS_SHARED | PSTATUS_MULTISHARED)) {
3386 loop_size = 2;
3387 }
3388 }
3389
3391
3392 auto t_normal = getFTensor1NormalsAtGaussPts();
3393 auto t_T = getFTensor1FromMat<SPACE_DIM>(
3394 dataAtPts->faceMaterialForceAtPts); //< face material force
3395 auto t_p =
3396 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
3397 auto t_P = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->approxPAtPts);
3398 // auto t_grad_P = getFTensor3FromMat<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
3399 // dataAtPts->gradPAtPts);
3400 auto t_u_gamma =
3401 getFTensor1FromMat<SPACE_DIM>(dataAtPts->hybridDispAtPts);
3402 auto t_grad_u_gamma =
3403 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->gradHybridDispAtPts);
3404 auto t_strain =
3405 getFTensor2SymmetricFromMat<SPACE_DIM>(dataAtPts->logStretchTensorAtPts);
3406 auto t_omega = getFTensor1FromMat<3>(dataAtPts->rotAxisAtPts);
3407
3413
3414 auto next = [&]() {
3415 ++t_normal;
3416 ++t_P;
3417 // ++t_grad_P;
3418 ++t_omega;
3419 ++t_u_gamma;
3420 ++t_grad_u_gamma;
3421 ++t_strain;
3422 ++t_T;
3423 ++t_p;
3424 };
3425
3427 case GRIFFITH_FORCE:
3428 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3429 t_N(I) = t_normal(I);
3430 t_N.normalize();
3431
3432 t_A(i, j) = levi_civita(i, j, k) * t_omega(k);
3433 t_R(i, k) = t_kd(i, k) + t_A(i, k);
3434 t_grad_u(i, j) = t_R(i, j) + t_strain(i, j);
3435
3436 t_T(I) +=
3437 t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
3438 // note that works only for Hooke material, for nonlinear material we need
3439 // strain energy expressed by stress
3440 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2.) / loop_size;
3441
3442 t_p += t_N(I) *
3443 (t_N(J) * ((t_kd(i, I) + t_grad_u_gamma(i, I)) * t_P(i, J))) /
3444 loop_size;
3445
3446 next();
3447 }
3448 break;
3449 case GRIFFITH_SKELETON:
3450 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3451
3452 // Normalize the normal
3453 t_N(I) = t_normal(I);
3454 t_N.normalize();
3455
3456 // R = ε − sym(u^Γ)
3457 t_R(i, j) =
3458 t_strain(i, j) - 0.5 * (t_grad_u_gamma(i, j) + t_grad_u_gamma(j, i));
3459
3460 // U = u^Γ + [2 R N − (Nᵀ R N) N] ⊗ N
3461 t_grad_u(i, J) = t_grad_u_gamma(i, J) + (2 * t_R(i, K) * t_N(K) -
3462 (t_R(k, L) * t_N(k) * t_N(L)) * t_N(i)) *
3463 t_N(J);
3464
3465 t_T(I) += t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
3466 // note that works only for Hooke material, for nonlinear material we need
3467 // strain energy expressed by stress
3468 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2.) / loop_size;
3469
3470 // calculate nominal face pressure
3471 t_p += t_N(I) *
3472 (t_N(J) * ((t_kd(i, I) + t_grad_u_gamma(i, I)) * t_P(i, J))) /
3473 loop_size;
3474
3475 next();
3476 }
3477 break;
3478
3479 default:
3480 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3481 "Grffith energy release "
3482 "selector not implemented");
3483 };
3484
3485#ifndef NDEBUG
3486 auto side_fe_ptr = getSidePtrFE();
3487 auto side_fe_mi_ptr = side_fe_ptr->numeredEntFiniteElementPtr;
3488 auto pstatus = side_fe_mi_ptr->getPStatus();
3489 if (pstatus) {
3490 auto owner = side_fe_mi_ptr->getOwnerProc();
3491 MOFEM_LOG("SELF", Sev::noisy)
3492 << "OpFaceSideMaterialForce: owner proc is not 0, owner proc: " << owner
3493 << " " << getPtrFE()->mField.get_comm_rank() << " n in the loop "
3494 << getNinTheLoop() << " loop size " << getLoopSize();
3495 }
3496#endif // NDEBUG
3497
3499}
3500
3502 EntData &data) {
3504
3505#ifndef NDEBUG
3506 auto fe_mi_ptr = getFEMethod()->numeredEntFiniteElementPtr;
3507 auto pstatus = fe_mi_ptr->getPStatus();
3508 if (pstatus) {
3509 auto owner = fe_mi_ptr->getOwnerProc();
3510 MOFEM_LOG("SELF", Sev::noisy)
3511 << "OpFaceMaterialForce: owner proc is not 0, owner proc: " << owner
3512 << " " << getPtrFE()->mField.get_comm_rank();
3513 }
3514#endif // NDEBUG
3515
3517
3519 t_face_T(I) = 0.;
3520 double face_pressure = 0.;
3521 auto t_T = getFTensor1FromMat<SPACE_DIM>(
3522 dataAtPts->faceMaterialForceAtPts); //< face material force
3523 auto t_p =
3524 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
3525 auto t_w = getFTensor0IntegrationWeight();
3526 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3527 t_face_T(I) += t_w * t_T(I);
3528 face_pressure += t_w * t_p;
3529 ++t_w;
3530 ++t_T;
3531 ++t_p;
3532 }
3533 t_face_T(I) *= getMeasure();
3534 face_pressure *= getMeasure();
3535
3536 auto get_tag = [&](auto name, auto dim) {
3537 auto &moab = getPtrFE()->mField.get_moab();
3538 Tag tag;
3539 double def_val[] = {0., 0., 0.};
3540 CHK_MOAB_THROW(moab.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
3541 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
3542 "create tag");
3543 return tag;
3544 };
3545
3546 auto set_tag = [&](auto &&tag, auto ptr) {
3547 auto &moab = getPtrFE()->mField.get_moab();
3548 auto face = getPtrFE()->getFEEntityHandle();
3549 CHK_MOAB_THROW(moab.tag_set_data(tag, &face, 1, ptr), "set tag");
3550 };
3551
3552 set_tag(get_tag("MaterialForce", 3), &t_face_T(0));
3553 set_tag(get_tag("FacePressure", 1), &face_pressure);
3554
3556}
3557
3558
3559template <typename OP_PTR>
3560std::tuple<std::string, MatrixDouble> getAnalyticalExpr(OP_PTR op_ptr, MatrixDouble &analytical_expr,
3561 const std::string block_name) {
3562
3563 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
3564
3565 auto ts_time = op_ptr->getTStime();
3566 auto ts_time_step = op_ptr->getTStimeStep();
3569 ts_time_step = EshelbianCore::dynamicStep;
3570 }
3571
3572 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
3573 MatrixDouble m_ref_normals = op_ptr->getNormalsAtGaussPts();
3574
3575 auto v_analytical_expr =
3576 analytical_expr_function(ts_time_step, ts_time, nb_gauss_pts,
3577 m_ref_coords, m_ref_normals, block_name);
3578
3579 if (PetscUnlikely(!v_analytical_expr.size2())) {
3581 "Analytical expression is empty or does not exist, "
3582 "check python file");
3583 }
3584
3585 return std::make_tuple(block_name, v_analytical_expr);
3586}
3587
3588//! [Analytical displacement function from python]
3589#ifdef ENABLE_PYTHON_BINDING
3590
3591 MoFEMErrorCode AnalyticalExprPython::analyticalExprInit(const std::string py_file) {
3593 try {
3594
3595 // create main module
3596 auto main_module = bp::import("__main__");
3597 mainNamespace = main_module.attr("__dict__");
3598 bp::exec_file(py_file.c_str(), mainNamespace, mainNamespace);
3599 // create a reference to python function
3600 analyticalDispFun = mainNamespace["analytical_disp"];
3601 analyticalTractionFun = mainNamespace["analytical_traction"];
3602 analyticalExternalStrainFun = mainNamespace["analytical_external_strain"];
3603
3604 } catch (bp::error_already_set const &) {
3605 // print all other errors to stderr
3606 PyErr_Print();
3608 }
3610 }
3611
3612 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalDisp(
3613
3614 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3615 np::ndarray nx, np::ndarray ny, np::ndarray nz,
3616 const std::string &block_name, np::ndarray &analytical_expr
3617
3618 ) {
3620 try {
3621
3622 // call python function
3623 analytical_expr = bp::extract<np::ndarray>(
3624 analyticalDispFun(delta_t, t, x, y, z, nx, ny, nz, block_name));
3625
3626 } catch (bp::error_already_set const &) {
3627 // print all other errors to stderr
3628 PyErr_Print();
3630 }
3632 }
3633
3634 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalTraction(
3635
3636 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3637 np::ndarray nx, np::ndarray ny, np::ndarray nz,
3638 const std::string& block_name, np::ndarray &analytical_expr
3639
3640 ) {
3642 try {
3643
3644 // call python function
3645 analytical_expr = bp::extract<np::ndarray>(
3646 analyticalTractionFun(delta_t, t, x, y, z, nx, ny, nz, block_name));
3647
3648 } catch (bp::error_already_set const &) {
3649 // print all other errors to stderr
3650 PyErr_Print();
3652 }
3654 }
3655
3656 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalExternalStrain(
3657
3658 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3659 const std::string& block_name, np::ndarray &analytical_expr
3660
3661 ) {
3663 try {
3664
3665 // call python function
3666 analytical_expr = bp::extract<np::ndarray>(
3667 analyticalExternalStrainFun(delta_t, t, x, y, z, block_name));
3668
3669 } catch (bp::error_already_set const &) {
3670 // print all other errors to stderr
3671 PyErr_Print();
3673 }
3675 }
3676
3677boost::weak_ptr<AnalyticalExprPython> AnalyticalExprPythonWeakPtr;
3678
3679inline np::ndarray convert_to_numpy(VectorDouble &data, int nb_gauss_pts,
3680 int id) {
3681 auto dtype = np::dtype::get_builtin<double>();
3682 auto size = bp::make_tuple(nb_gauss_pts);
3683 auto stride = bp::make_tuple(3 * sizeof(double));
3684 return (np::from_data(&data[id], dtype, size, stride, bp::object()));
3685};
3686#endif
3687//! Analytical displacement function from python]
3688
3690 int nb_gauss_pts,
3691 MatrixDouble &m_ref_coords,
3692 MatrixDouble &m_ref_normals,
3693 const std::string block_name) {
3694
3695#ifdef ENABLE_PYTHON_BINDING
3696 if (auto analytical_expr_ptr = AnalyticalExprPythonWeakPtr.lock()) {
3697
3698 VectorDouble v_ref_coords = m_ref_coords.data();
3699 VectorDouble v_ref_normals = m_ref_normals.data();
3700
3701 bp::list python_coords;
3702 bp::list python_normals;
3703
3704 for (int idx = 0; idx < 3; ++idx) {
3705 python_coords.append(convert_to_numpy(v_ref_coords, nb_gauss_pts, idx));
3706 python_normals.append(convert_to_numpy(v_ref_normals, nb_gauss_pts, idx));
3707 }
3708
3709 auto disp_block_name = "(.*)ANALYTICAL_DISPLACEMENT(.*)";
3710 auto traction_block_name = "(.*)ANALYTICAL_TRACTION(.*)";
3711
3712 std::regex reg_disp_name(disp_block_name);
3713 std::regex reg_traction_name(traction_block_name);
3714
3715 np::ndarray np_analytical_expr = np::empty(
3716 bp::make_tuple(nb_gauss_pts, 3), np::dtype::get_builtin<double>());
3717
3718 if (std::regex_match(block_name, reg_disp_name)) {
3719 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalDisp(
3720 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3721 bp::extract<np::ndarray>(python_coords[1]),
3722 bp::extract<np::ndarray>(python_coords[2]),
3723 bp::extract<np::ndarray>(python_normals[0]),
3724 bp::extract<np::ndarray>(python_normals[1]),
3725 bp::extract<np::ndarray>(python_normals[2]),
3726 block_name, np_analytical_expr),
3727 "Failed analytical_disp() python call");
3728 } else if (std::regex_match(block_name, reg_traction_name)) {
3729 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalTraction(
3730 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3731 bp::extract<np::ndarray>(python_coords[1]),
3732 bp::extract<np::ndarray>(python_coords[2]),
3733 bp::extract<np::ndarray>(python_normals[0]),
3734 bp::extract<np::ndarray>(python_normals[1]),
3735 bp::extract<np::ndarray>(python_normals[2]),
3736 block_name, np_analytical_expr),
3737 "Failed analytical_traction() python call");
3738 } else {
3740 "Unknown analytical block");
3741 }
3742
3743 // check the shape of returned array
3744 if (PetscUnlikely(np_analytical_expr.get_shape()[0] != nb_gauss_pts ||
3745 np_analytical_expr.get_shape()[1] != 3)) {
3748 "Wrong shape of analytical expression returned from "
3749 "python, expected: (" +
3750 std::to_string(nb_gauss_pts) + ", 3), got: (" +
3751 std::to_string(np_analytical_expr.get_shape()[0]) + ", " +
3752 std::to_string(np_analytical_expr.get_shape()[1]) + ")");
3753 }
3754
3755 double *analytical_expr_val_ptr =
3756 reinterpret_cast<double *>(np_analytical_expr.get_data());
3757
3758 MatrixDouble v_analytical_expr;
3759 v_analytical_expr.resize(3, nb_gauss_pts, false);
3760 for (size_t gg = 0; gg < nb_gauss_pts; ++gg) {
3761 for (int idx = 0; idx < 3; ++idx)
3762 v_analytical_expr(idx, gg) =
3763 *(analytical_expr_val_ptr + (3 * gg + idx));
3764 }
3765 return v_analytical_expr;
3766 } else {
3767 // Returns empty vector
3768 }
3769#endif
3770 return MatrixDouble();
3771}
3772
3774 int nb_gauss_pts,
3775 MatrixDouble &m_ref_coords,
3776 const std::string block_name) {
3777
3778#ifdef ENABLE_PYTHON_BINDING
3779 if (auto analytical_expr_ptr = AnalyticalExprPythonWeakPtr.lock()) {
3780
3781 VectorDouble v_ref_coords = m_ref_coords.data();
3782
3783 bp::list python_coords;
3784
3785 for (int idx = 0; idx < 3; ++idx) {
3786 python_coords.append(convert_to_numpy(v_ref_coords, nb_gauss_pts, idx));
3787 }
3788
3789 auto externalstrain_block_name = "(.*)ANALYTICAL_EXTERNALSTRAIN(.*)";
3790
3791 std::regex reg_externalstrain_name(externalstrain_block_name);
3792
3793 np::ndarray np_analytical_expr = np::empty(
3794 bp::make_tuple(nb_gauss_pts), np::dtype::get_builtin<double>());
3795
3796 if (std::regex_match(block_name, reg_externalstrain_name)) {
3797 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalExternalStrain(
3798 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3799 bp::extract<np::ndarray>(python_coords[1]),
3800 bp::extract<np::ndarray>(python_coords[2]), block_name,
3801 np_analytical_expr),
3802 "Failed analytical_external_strain() python call");
3803 } else {
3805 "Unknown analytical block");
3806 }
3807
3808 // check the shape of returned array
3809 if (PetscUnlikely(np_analytical_expr.get_shape()[0] != nb_gauss_pts ||
3810 np_analytical_expr.get_shape()[1] != 1)) {
3813 "Wrong shape of analytical expression returned from "
3814 "python, expected: (" +
3815 std::to_string(nb_gauss_pts) + ", 1), got: (" +
3816 std::to_string(np_analytical_expr.get_shape()[0]) + ", " +
3817 std::to_string(np_analytical_expr.get_shape()[1]) + ")");
3818 }
3819
3820 double *analytical_expr_val_ptr =
3821 reinterpret_cast<double *>(np_analytical_expr.get_data());
3822
3823 VectorDouble v_analytical_expr;
3824 v_analytical_expr.resize(nb_gauss_pts, false);
3825 for (size_t gg = 0; gg < nb_gauss_pts; ++gg)
3826 v_analytical_expr[gg] = *(analytical_expr_val_ptr + gg);
3827
3828 return v_analytical_expr;
3829 } else {
3830 // Returns empty vector
3831 }
3832#endif
3833 return VectorDouble();
3834}
3835
3837 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3838 boost::shared_ptr<MatrixDouble> vec, ScalarFun beta_coeff,
3839 boost::shared_ptr<Range> ents_ptr)
3840 : OP(broken_base_side_data, ents_ptr) {
3841 this->sourceVec = vec;
3842 this->betaCoeff = beta_coeff;
3843}
3844
3846 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3847 ScalarFun beta_coeff, boost::shared_ptr<Range> ents_ptr)
3848 : OP(broken_base_side_data, ents_ptr) {
3849 this->sourceVec = boost::shared_ptr<MatrixDouble>();
3850 this->betaCoeff = beta_coeff;
3851}
3852
3854OpBrokenBaseTimesBrokenDisp::doWork(int row_side, EntityType row_type,
3855 EntitiesFieldData::EntData &row_data) {
3857
3858 if (OP::entsPtr) {
3859 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
3861 }
3862
3863#ifndef NDEBUG
3864 if (!brokenBaseSideData) {
3865 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
3866 }
3867#endif // NDEBUG
3868
3869 auto do_work_rhs = [this](int row_side, EntityType row_type,
3870 EntitiesFieldData::EntData &row_data) {
3872 // get number of dofs on row
3873 OP::nbRows = row_data.getIndices().size();
3874 if (!OP::nbRows)
3876 // get number of integration points
3877 OP::nbIntegrationPts = OP::getGaussPts().size2();
3878 // get row base functions
3879 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
3880 // resize and clear the right hand side vector
3881 OP::locF.resize(OP::nbRows, false);
3882 OP::locF.clear();
3883 // integrate local vector
3884 CHKERR this->iNtegrate(row_data);
3885 // assemble local vector
3886 CHKERR this->aSsemble(row_data);
3888 };
3889
3890 switch (OP::opType) {
3891 case OP::OPSPACE:
3892 for (auto &bd : *brokenBaseSideData) {
3893 this->sourceVec =
3894 boost::shared_ptr<MatrixDouble>(brokenBaseSideData, &bd.getFlux());
3895 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData());
3896 this->sourceVec.reset();
3897 }
3898 break;
3899 default:
3901 (std::string("wrong op type ") +
3902 OpBaseDerivativesBase::OpTypeNames[OP::opType])
3903 .c_str());
3904 }
3905
3907}
3908
3910 const std::string row_field,
3911 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3912 ScalarFun beta_coeff, boost::shared_ptr<Range> ents_ptr)
3913 : OP(row_field, boost::shared_ptr<MatrixDouble>(), beta_coeff, ents_ptr),
3914 brokenBaseSideDataPtr(broken_base_side_data) {
3915 this->betaCoeff = beta_coeff;
3916}
3917
3921 for (auto &bd : (*brokenBaseSideDataPtr)) {
3922 this->sourceVec =
3923 boost::shared_ptr<MatrixDouble>(brokenBaseSideDataPtr, &bd.getFlux());
3924
3925#ifndef NDEBUG
3926 if (this->sourceVec->size1() != SPACE_DIM) {
3927 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3928 "Inconsistent size of the source vector");
3929 }
3930 if (this->sourceVec->size2() != OP::getGaussPts().size2()) {
3931 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3932 "Inconsistent size of the source vector");
3933 }
3934#endif // NDEBUG
3935
3936 CHKERR OP::iNtegrate(data);
3937
3938 this->sourceVec.reset();
3939 }
3941}
3942
3944 std::string row_field,
3945 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3946 ScalarFun beta, const bool assmb_transpose, const bool only_transpose,
3947 boost::shared_ptr<Range> ents_ptr)
3948 : OP(row_field, broken_base_side_data, assmb_transpose, only_transpose,
3949 ents_ptr) {
3950 this->betaCoeff = beta;
3951 this->sYmm = false;
3952 }
3953
3955 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3956 ScalarFun beta, boost::shared_ptr<Range> ents_ptr)
3957 : OP(broken_base_side_data, ents_ptr) {
3958 this->sYmm = false;
3959 this->betaCoeff = beta;
3960 OP::assembleTranspose = false;
3961 OP::onlyTranspose = false;
3962}
3963
3965OpBrokenBaseBrokenBase::doWork(int row_side, EntityType row_type,
3966 EntitiesFieldData::EntData &row_data) {
3968
3969 if (OP::entsPtr) {
3970 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
3972 }
3973
3974#ifndef NDEBUG
3975 if (!brokenBaseSideData) {
3976 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
3977 }
3978#endif // NDEBUG
3979
3980 auto do_work_lhs = [this](int row_side, int col_side, EntityType row_type,
3981 EntityType col_type,
3983 EntitiesFieldData::EntData &col_data) {
3985
3986 auto check_if_assemble_transpose = [&] {
3987 if (this->sYmm) {
3988 if (OP::rowSide != OP::colSide || OP::rowType != OP::colType)
3989 return true;
3990 else
3991 return false;
3992 } else if (OP::assembleTranspose) {
3993 return true;
3994 }
3995 return false;
3996 };
3997
3998 OP::rowSide = row_side;
3999 OP::rowType = row_type;
4000 OP::colSide = col_side;
4001 OP::colType = col_type;
4002 OP::nbCols = col_data.getIndices().size();
4003 OP::locMat.resize(OP::nbRows, OP::nbCols, false);
4004 OP::locMat.clear();
4005 CHKERR this->iNtegrate(row_data, col_data);
4006 CHKERR this->aSsemble(row_data, col_data, check_if_assemble_transpose());
4008 };
4009
4010 switch (OP::opType) {
4011 case OP::OPSPACE:
4012
4013 for (auto &bd : *brokenBaseSideData) {
4014
4015#ifndef NDEBUG
4016 if (!bd.getData().getNSharedPtr(bd.getData().getBase())) {
4017 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4018 "base functions not set");
4019 }
4020#endif
4021
4022 OP::nbRows = bd.getData().getIndices().size();
4023 if (!OP::nbRows)
4025 OP::nbIntegrationPts = OP::getGaussPts().size2();
4026 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(bd.getData());
4027
4028 if (!OP::nbRows)
4030
4031 CHKERR do_work_lhs(
4032
4033 // side
4034 bd.getSide(), bd.getSide(),
4035
4036 // type
4037 bd.getType(), bd.getType(),
4038
4039 // row_data
4040 bd.getData(), bd.getData()
4041
4042 );
4043 }
4044
4045 break;
4046
4047 default:
4049 (std::string("wrong op type ") +
4050 OpBaseDerivativesBase::OpTypeNames[OP::opType])
4051 .c_str());
4052 }
4053
4055}
4056
4057} // namespace EshelbianPlasticity
Auxilary functions for Eshelbian plasticity.
Eshelbian plasticity interface.
Lie algebra implementation.
#define FTENSOR_INDEX(DIM, I)
constexpr double a
constexpr int SPACE_DIM
Kronecker Delta class symmetric.
Kronecker Delta class.
Tensor1< T, Tensor_Dim > normalize()
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ USER_BASE
user implemented approximation base
Definition definitions.h:68
@ NOBASE
Definition definitions.h:59
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#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
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_IMPOSSIBLE_CASE
Definition definitions.h:35
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ 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 auto t_kd
boost::function< double(const double, const double, const double)> ScalarFun
Scalar function type.
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
MoFEM::TsCtx * ts_ctx
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
auto getMat(A &&t_val, B &&t_vec, Fun< double > f)
Get the Mat object.
auto getDiffMat(A &&t_val, B &&t_vec, Fun< double > f, Fun< double > d_f, const int nb)
Get the Diff Mat object.
VectorDouble analytical_externalstrain_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, const std::string block_name)
auto sort_eigen_vals(A &eig, B &eigen_vec)
static Tag get_tag(moab::Interface &moab, std::string tag_name, int size)
std::tuple< std::string, MatrixDouble > getAnalyticalExpr(OP_PTR op_ptr, MatrixDouble &analytical_expr, const std::string block_name)
static constexpr auto size_symm
MatrixDouble analytical_expr_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, MatrixDouble &m_ref_normals, const std::string block_name)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
VectorBoundedArray< double, 3 > VectorDouble3
Definition Types.hpp:92
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
UBlasVector< double > VectorDouble
Definition Types.hpp:68
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
MoFEMErrorCode computeEigenValuesSymmetric(const MatrixDouble &mat, VectorDouble &eig, MatrixDouble &eigen_vec)
compute eigenvalues of a symmetric matrix using lapack dsyev
static auto determinantTensor3by3(T &t)
Calculate the determinant of a 3x3 matrix or a tensor of rank 2.
constexpr IntegrationType I
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
FTensor::Index< 'm', 3 > m
const int N
Definition speed_test.cpp:3
static enum StretchSelector stretchSelector
static double dynamicTime
static PetscBool l2UserBaseScale
static int dynamicStep
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static PetscBool dynamicRelaxation
static enum SymmetrySelector symmetrySelector
static boost::function< double(const double)> f
static PetscBool setSingularity
static boost::function< double(const double)> d_f
static enum EnergyReleaseSelector energyReleaseSelector
static boost::function< double(const double)> inv_f
static auto diffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:104
static auto exp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:63
Add operators pushing bases from local to physical configuration.
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor2< FTensor::PackPtr< double *, Tensor_Dim0 *Tensor_Dim1 >, Tensor_Dim0, Tensor_Dim1 > getFTensor2DiffN(FieldApproximationBase base)
Get derivatives of base functions for Hdiv space.
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
FTensor::Tensor2< FTensor::PackPtr< double *, Tensor_Dim0 *Tensor_Dim1 >, Tensor_Dim0, Tensor_Dim1 > getFTensor2N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
const VectorFieldEntities & getFieldEntities() const
Get field entities (const version)
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorDouble & getFieldData() const
Get DOF values on entity.
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Operator for inverting matrices at integration points.
Scale base functions by inverses of measure of element.
@ CTX_TSSETIJACOBIAN
Setting up implicit Jacobian.
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
OpBrokenBaseBrokenBase(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, ScalarFun beta, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
OpBrokenBaseTimesBrokenDisp(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, ScalarFun beta_coeff=[](double, double, double) constexpr { return 1;}, boost::shared_ptr< Range > ents_ptr=nullptr)
OpBrokenBaseTimesHybridDisp(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< MatrixDouble > vec, ScalarFun beta_coeff=[](double, double, double) constexpr { return 1;}, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntData &row_data)
Operator for linear form, usually to calculate values on right hand side.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Operator for linear form, usually to calculate values on right hand side.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Caluclate face material force and normal pressure at gauss points.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpHybridBaseTimesBrokenDisp(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, ScalarFun beta_coeff, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenBaseSideDataPtr
OpHyrbridBaseBrokenBase(std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, ScalarFun beta, const bool assmb_transpose, const bool only_transpose, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode integrate(EntData &data)
MoFEMErrorCode integrate(EntData &data)
MoFEMErrorCode integrate(EntData &data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrateImpl(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrateImpl(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrateImpl(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &data)
MoFEMErrorCode integrate(EntData &row_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &data)
double scale
Definition plastic.cpp:123