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 ? EshelbianCore::dynamicTime : getFEMethod()->ts_t;
1316
1317 // default scaling is constant
1318 double scale = scalingMethodPtr->getScale(time);
1319
1321 auto t_L = symm_L_tensor();
1322
1323 int nb_base_functions = data.getN().size2();
1324 auto t_row_base_fun = data.getFTensor0N();
1325 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1326 double a = v * t_w;
1327 auto t_nf = get_ftensor2(nF);
1328
1329 FTensor::Tensor2<double, 3, 3> t_symm_stress;
1330 t_symm_stress(i, j) =
1331 (t_internal_stress(i, j) + t_internal_stress(j, i)) / 2;
1332
1334 t_residual(L) = t_L(i, j, L) * (scale * t_symm_stress(i, j));
1335
1336 int bb = 0;
1337 for (; bb != nb_dofs / 6; ++bb) {
1338 t_nf(L) += a * t_row_base_fun * t_residual(L);
1339 ++t_nf;
1340 ++t_row_base_fun;
1341 }
1342 for (; bb != nb_base_functions; ++bb)
1343 ++t_row_base_fun;
1344
1345 ++t_w;
1346 ++t_internal_stress;
1347 }
1349}
1350
1351template <>
1354
1355 int nb_dofs = data.getIndices().size();
1356 int nb_integration_pts = data.getN().size1();
1357 auto v = getVolume();
1358 auto t_w = getFTensor0IntegrationWeight();
1359
1360 auto get_ftensor2 = [](auto &v) {
1362 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1363 };
1364
1365 auto t_internal_stress =
1366 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1367
1369 FTensor::Index<'M', size_symm> M;
1371 t_L = voigt_to_symm();
1372
1373 const double time = EshelbianCore::dynamicRelaxation ? EshelbianCore::dynamicTime : getFEMethod()->ts_t;
1374
1375 // default is constant
1376 double scale = scalingMethodPtr->getScale(time);
1377
1378 int nb_base_functions = data.getN().size2();
1379 auto t_row_base_fun = data.getFTensor0N();
1380 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1381 double a = v * t_w;
1382 auto t_nf = get_ftensor2(nF);
1383
1385 t_residual(L) = t_L(M, L) * (scale * t_internal_stress(M));
1386
1387 int bb = 0;
1388 for (; bb != nb_dofs / 6; ++bb) {
1389 t_nf(L) += a * t_row_base_fun * t_residual(L);
1390 ++t_nf;
1391 ++t_row_base_fun;
1392 }
1393 for (; bb != nb_base_functions; ++bb)
1394 ++t_row_base_fun;
1395
1396 ++t_w;
1397 ++t_internal_stress;
1398 }
1400}
1401
1402template <AssemblyType A>
1405 // get entity of face
1406 EntityHandle fe_ent = OP::getFEEntityHandle();
1407 // iterate over all boundary data
1408 for (auto &bc : (*bcDispPtr)) {
1409 // check if finite element entity is part of boundary condition
1410 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1411 int nb_dofs = data.getIndices().size();
1412
1413 int nb_integration_pts = OP::getGaussPts().size2();
1414 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1415 auto t_w = OP::getFTensor0IntegrationWeight();
1416 int nb_base_functions = data.getN().size2() / 3;
1417 auto t_row_base_fun = data.getFTensor1N<3>();
1418
1421
1422 double scale = 1;
1423 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1425 scale *= scalingMethodsMap.at(bc.blockName)
1426 ->getScale(EshelbianCore::dynamicTime);
1427 } else {
1428 scale *= scalingMethodsMap.at(bc.blockName)
1429 ->getScale(OP::getFEMethod()->ts_t);
1430 }
1431 } else {
1432 MOFEM_LOG("SELF", Sev::warning)
1433 << "No scaling method found for " << bc.blockName;
1434 }
1435
1436 // get bc data
1437 FTensor::Tensor1<double, 3> t_bc_disp(bc.vals[0], bc.vals[1], bc.vals[2]);
1438 t_bc_disp(i) *= scale;
1439
1440 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1441 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1442 int bb = 0;
1443 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1444 t_nf(i) +=
1445 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1446 ++t_nf;
1447 ++t_row_base_fun;
1448 }
1449 for (; bb != nb_base_functions; ++bb)
1450 ++t_row_base_fun;
1451
1452 ++t_w;
1453 ++t_normal;
1454 }
1455 }
1456 }
1458}
1459
1461 return OP::iNtegrate(data);
1462}
1463
1464template <AssemblyType A>
1467
1468 FTENSOR_INDEX(3, i);
1469 FTENSOR_INDEX(3, j);
1470 FTENSOR_INDEX(3, k);
1471
1472 double time = OP::getFEMethod()->ts_t;
1475 }
1476
1477 // get entity of face
1478 EntityHandle fe_ent = OP::getFEEntityHandle();
1479 // interate over all boundary data
1480 for (auto &bc : (*bcRotPtr)) {
1481 // check if finite element entity is part of boundary condition
1482 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1483 int nb_dofs = data.getIndices().size();
1484 int nb_integration_pts = OP::getGaussPts().size2();
1485 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1486 auto t_w = OP::getFTensor0IntegrationWeight();
1487
1488 int nb_base_functions = data.getN().size2() / 3;
1489 auto t_row_base_fun = data.getFTensor1N<3>();
1490
1491 auto get_ftensor1 = [](auto &v) {
1493 &v[2]);
1494 };
1495
1496 // Note: First three values of bc.vals are the center of rotation
1497 // 4th is rotation angle in radians, and remaining values are axis of
1498 // rotation. Also, if rotation axis is not provided, it defaults to the
1499 // normal vector of the face.
1500
1501 // get bc data
1502 FTensor::Tensor1<double, 3> t_center(bc.vals[0], bc.vals[1], bc.vals[2]);
1503
1504 auto get_rotation_angle = [&]() {
1505 double theta = bc.theta;
1506 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1507 theta *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1508 }
1509 return theta;
1510 };
1511
1512 auto get_rotation = [&](auto theta) {
1514 if (bc.vals.size() == 7) {
1515 t_omega(0) = bc.vals[4];
1516 t_omega(1) = bc.vals[5];
1517 t_omega(2) = bc.vals[6];
1518 } else {
1519 // Use gemetric face normal as rotation axis
1520 t_omega(i) = OP::getFTensor1Normal()(i);
1521 }
1522 t_omega.normalize();
1523 t_omega(i) *= theta;
1526 ? 0.
1527 : t_omega.l2());
1528 };
1529
1530 auto t_R = get_rotation(get_rotation_angle());
1531 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1532
1533 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1535 t_delta(i) = t_center(i) - t_coords(i);
1537 t_disp(i) = t_delta(i) - t_R(i, j) * t_delta(j);
1538
1539 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1540 int bb = 0;
1541 for (; bb != nb_dofs / 3; ++bb) {
1542 t_nf(i) += t_w * (t_row_base_fun(j) * t_normal(j)) * t_disp(i) * 0.5;
1543 ++t_nf;
1544 ++t_row_base_fun;
1545 }
1546 for (; bb != nb_base_functions; ++bb)
1547 ++t_row_base_fun;
1548
1549 ++t_w;
1550 ++t_normal;
1551 ++t_coords;
1552 }
1553 }
1554 }
1556}
1557
1559 return OP::iNtegrate(data);
1560}
1561
1562template <AssemblyType A>
1565
1566 double time = OP::getFEMethod()->ts_t;
1569 }
1570
1571 // get entity of face
1572 EntityHandle fe_ent = OP::getFEEntityHandle();
1573 // iterate over all boundary data
1574 for (auto &bc : (*bcDispPtr)) {
1575 // check if finite element entity is part of boundary condition
1576 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1577
1578 for (auto &bd : (*brokenBaseSideDataPtr)) {
1579
1580 auto t_approx_P = getFTensor2FromMat<3, 3>(bd.getFlux());
1581 auto t_u = getFTensor1FromMat<3>(*hybridDispPtr);
1582 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1583 auto t_w = OP::getFTensor0IntegrationWeight();
1584
1587
1589
1590 double scale = 1;
1591 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1592 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1593 } else {
1594 MOFEM_LOG("SELF", Sev::warning)
1595 << "No scaling method found for " << bc.blockName;
1596 }
1597
1598 // get bc data
1599 double val = scale * bc.val;
1600
1601 int nb_dofs = data.getIndices().size();
1602 int nb_integration_pts = OP::getGaussPts().size2();
1603 int nb_base_functions = data.getN().size2();
1604 auto t_row_base = data.getFTensor0N();
1605 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1606
1608 t_N(i) = t_normal(i);
1609 t_N.normalize();
1610
1612 t_P(i, j) = t_N(i) * t_N(j);
1614 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
1615
1616 FTensor::Tensor1<double, 3> t_traction;
1617 t_traction(i) = t_approx_P(i, j) * t_N(j);
1618
1620 t_res(i) =
1621 t_Q(i, j) * t_traction(j) + t_P(i, j) * 2 * t_u(j) - t_N(i) * val;
1622
1623 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1624 int bb = 0;
1625 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1626 t_nf(i) += (t_w * t_row_base * OP::getMeasure()) * t_res(i);
1627 ++t_nf;
1628 ++t_row_base;
1629 }
1630 for (; bb != nb_base_functions; ++bb)
1631 ++t_row_base;
1632
1633 ++t_w;
1634 ++t_normal;
1635 ++t_u;
1636 ++t_approx_P;
1637 }
1638 }
1639 }
1640 }
1642}
1643
1644template <AssemblyType A>
1647 EntData &col_data) {
1649
1650 double time = OP::getFEMethod()->ts_t;
1653 }
1654
1655 int row_nb_dofs = row_data.getIndices().size();
1656 int col_nb_dofs = col_data.getIndices().size();
1657 auto &locMat = OP::locMat;
1658 locMat.resize(row_nb_dofs, col_nb_dofs, false);
1659 locMat.clear();
1660
1661 // get entity of face
1662 EntityHandle fe_ent = OP::getFEEntityHandle();
1663 // iterate over all boundary data
1664 for (auto &bc : (*bcDispPtr)) {
1665 // check if finite element entity is part of boundary condition
1666 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1667
1668 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1669 auto t_w = OP::getFTensor0IntegrationWeight();
1670
1673
1674 double scale = 1;
1675 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1676 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1677 } else {
1678 MOFEM_LOG("SELF", Sev::warning)
1679 << "No scaling method found for " << bc.blockName;
1680 }
1681
1682 int nb_integration_pts = OP::getGaussPts().size2();
1683 int row_nb_dofs = row_data.getIndices().size();
1684 int col_nb_dofs = col_data.getIndices().size();
1685 int nb_base_functions = row_data.getN().size2();
1686 auto t_row_base = row_data.getFTensor0N();
1687
1689
1690 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1691
1693 t_N(i) = t_normal(i);
1694 t_N.normalize();
1695
1697 t_P(i, j) = t_N(i) * t_N(j);
1698
1700 t_d_res(i, j) = 2.0 * t_P(i, j);
1701
1702 int rr = 0;
1703 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
1704 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
1705 locMat, SPACE_DIM * rr);
1706 auto t_col_base = col_data.getFTensor0N(gg, 0);
1707 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
1708 t_mat(i, j) += (t_w * t_row_base * t_col_base) * t_d_res(i, j);
1709 ++t_mat;
1710 ++t_col_base;
1711 }
1712 ++t_row_base;
1713 }
1714
1715 for (; rr != nb_base_functions; ++rr)
1716 ++t_row_base;
1717
1718 ++t_w;
1719 ++t_normal;
1720 }
1721
1722 locMat *= OP::getMeasure();
1723
1724 }
1725 }
1727}
1728
1729template <AssemblyType A>
1732 EntData &col_data) {
1734
1735 double time = OP::getFEMethod()->ts_t;
1738 }
1739
1740 int row_nb_dofs = row_data.getIndices().size();
1741 int col_nb_dofs = col_data.getIndices().size();
1742 auto &locMat = OP::locMat;
1743 locMat.resize(row_nb_dofs, col_nb_dofs, false);
1744 locMat.clear();
1745
1746 // get entity of face
1747 EntityHandle fe_ent = OP::getFEEntityHandle();
1748 // iterate over all boundary data
1749 for (auto &bc : (*bcDispPtr)) {
1750 // check if finite element entity is part of boundary condition
1751 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1752
1753 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1754 auto t_w = OP::getFTensor0IntegrationWeight();
1755
1759
1761
1762 double scale = 1;
1763 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1764 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1765 } else {
1766 MOFEM_LOG("SELF", Sev::warning)
1767 << "No scaling method found for " << bc.blockName;
1768 }
1769
1770 int nb_integration_pts = OP::getGaussPts().size2();
1771 int nb_base_functions = row_data.getN().size2();
1772 auto t_row_base = row_data.getFTensor0N();
1773
1774 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1775
1777 t_N(i) = t_normal(i);
1778 t_N.normalize();
1779
1781 t_P(i, j) = t_N(i) * t_N(j);
1783 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
1784
1786 t_d_res(i, j) = t_Q(i, j);
1787
1788 int rr = 0;
1789 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
1790 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
1791 OP::locMat, SPACE_DIM * rr);
1792 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1793 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
1794 t_mat(i, j) +=
1795 ((t_w * t_row_base) * (t_N(k) * t_col_base(k))) * t_d_res(i, j);
1796 ++t_mat;
1797 ++t_col_base;
1798 }
1799 ++t_row_base;
1800 }
1801
1802 for (; rr != nb_base_functions; ++rr)
1803 ++t_row_base;
1804
1805 ++t_w;
1806 ++t_normal;
1807 }
1808
1809 locMat *= OP::getMeasure();
1810 }
1811 }
1813}
1814
1816 return OP::iNtegrate(data);
1817}
1818
1820 EntData &col_data) {
1821 return OP::iNtegrate(row_data, col_data);
1822}
1823
1825 EntData &col_data) {
1826 return OP::iNtegrate(row_data, col_data);
1827}
1828
1829template <AssemblyType A>
1832
1833 double time = OP::getFEMethod()->ts_t;
1836 }
1837
1838 // get entity of face
1839 EntityHandle fe_ent = OP::getFEEntityHandle();
1840 // iterate over all boundary data
1841 for (auto &bc : (*bcDispPtr)) {
1842 // check if finite element entity is part of boundary condition
1843 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1844
1845 MatrixDouble analytical_expr;
1846 // placeholder to pass boundary block id to python
1847
1848 auto [block_name, v_analytical_expr] =
1849 getAnalyticalExpr(this, analytical_expr, bc.blockName);
1850
1851 int nb_dofs = data.getIndices().size();
1852
1853 int nb_integration_pts = OP::getGaussPts().size2();
1854 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1855 auto t_w = OP::getFTensor0IntegrationWeight();
1856 int nb_base_functions = data.getN().size2() / 3;
1857 auto t_row_base_fun = data.getFTensor1N<3>();
1858 auto t_coord = OP::getFTensor1CoordsAtGaussPts();
1859
1862
1863 // get bc data
1864 auto t_bc_disp = getFTensor1FromMat<3>(v_analytical_expr);
1865
1866 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1867 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1868
1869 int bb = 0;
1870 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1871 t_nf(i) +=
1872 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1873 ++t_nf;
1874 ++t_row_base_fun;
1875 }
1876 for (; bb != nb_base_functions; ++bb)
1877 ++t_row_base_fun;
1878
1879 ++t_bc_disp;
1880 ++t_coord;
1881 ++t_w;
1882 ++t_normal;
1883 }
1884 }
1885 }
1887}
1888
1890 return OP::iNtegrate(data);
1891}
1892
1895
1896 FTENSOR_INDEX(3, i);
1897
1898 int nb_dofs = data.getFieldData().size();
1899 int nb_integration_pts = getGaussPts().size2();
1900 int nb_base_functions = data.getN().size2();
1901
1902 double time = getFEMethod()->ts_t;
1905 }
1906
1907#ifndef NDEBUG
1908 if (this->locF.size() != nb_dofs)
1909 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1910 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
1911#endif // NDEBUG
1912
1913 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1915
1916 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
1917 auto t_row_base = data.getFTensor0N();
1918 auto t_w = getFTensor0IntegrationWeight();
1919 auto t_coords = getFTensor1CoordsAtGaussPts();
1920
1921 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
1922
1923 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1924
1925 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
1926 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
1927 int rr = 0;
1928 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1929 t_f(i) -= (time_scale * t_w * t_row_base * tau) * (t_val(i) * scale);
1930 ++t_row_base;
1931 ++t_f;
1932 }
1933
1934 for (; rr != nb_base_functions; ++rr)
1935 ++t_row_base;
1936 ++t_w;
1937 ++t_coords;
1938 }
1939 this->locF *= getMeasure();
1941 };
1942
1943 // get entity of face
1944 EntityHandle fe_ent = getFEEntityHandle();
1945 for (auto &bc : *(bcData)) {
1946 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1947
1948 double time_scale = 1;
1949 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1950 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1951 }
1952
1953 int nb_dofs = data.getFieldData().size();
1954 if (nb_dofs) {
1955
1956 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
1957 auto calc_tau = [](double, double y, double) {
1958 y -= 44;
1959 y /= (60 - 44);
1960 return -y * (y - 1) / 0.25;
1961 };
1962 CHKERR integrate_rhs(bc, calc_tau, time_scale);
1963 } else {
1964 CHKERR integrate_rhs(
1965 bc, [](double, double, double) { return 1; }, time_scale);
1966 }
1967 }
1968 }
1969 }
1971}
1972
1975
1976 FTENSOR_INDEX(3, i);
1977
1978 int nb_dofs = data.getFieldData().size();
1979 int nb_integration_pts = getGaussPts().size2();
1980 int nb_base_functions = data.getN().size2();
1981
1982 double time = getFEMethod()->ts_t;
1985 }
1986
1987#ifndef NDEBUG
1988 if (this->locF.size() != nb_dofs)
1989 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1990 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
1991#endif // NDEBUG
1992
1993 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1995
1996 auto val = bc.val;
1997 auto t_row_base = data.getFTensor0N();
1998 auto t_w = getFTensor0IntegrationWeight();
1999 auto t_coords = getFTensor1CoordsAtGaussPts();
2000 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
2001 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
2002
2003 auto t_grad_gamma_u = getFTensor2FromMat<3, 2>(*hybridGradDispPtr);
2004
2005 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2006
2007 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2008
2014
2018
2019 t_normal(i) = (FTensor::levi_civita<double>(i, j, k) * t_tangent1(j)) *
2020 t_tangent2(k);
2021 } else {
2022 t_normal(i) = (FTensor::levi_civita<double>(i, j, k) *
2023 (t_tangent1(j) + t_grad_gamma_u(j, N0))) *
2024 (t_tangent2(k) + t_grad_gamma_u(k, N1));
2025 }
2026 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2027 auto t_val = FTensor::Tensor1<double, 3>();
2028 t_val(i) = (time_scale * t_w * tau * scale * val) * t_normal(i);
2029
2030 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2031 int rr = 0;
2032 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2033 t_f(i) += t_row_base * t_val(i);
2034 ++t_row_base;
2035 ++t_f;
2036 }
2037
2038 for (; rr != nb_base_functions; ++rr)
2039 ++t_row_base;
2040 ++t_w;
2041 ++t_coords;
2042 ++t_tangent1;
2043 ++t_tangent2;
2044 ++t_grad_gamma_u;
2045 }
2046 this->locF /= 2.;
2047
2049 };
2050
2051 // get entity of face
2052 EntityHandle fe_ent = getFEEntityHandle();
2053 for (auto &bc : *(bcData)) {
2054 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2055
2056 double time_scale = 1;
2057 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2058 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2059 }
2060
2061 int nb_dofs = data.getFieldData().size();
2062 if (nb_dofs) {
2063 CHKERR integrate_rhs(
2064 bc, [](double, double, double) { return 1; }, time_scale);
2065 }
2066 }
2067 }
2069}
2070
2071template <AssemblyType A>
2074 EntData &col_data) {
2076
2080 }
2081
2082 double time = OP::getFEMethod()->ts_t;
2085 }
2086
2087 int nb_base_functions = row_data.getN().size2();
2088 int row_nb_dofs = row_data.getIndices().size();
2089 int col_nb_dofs = col_data.getIndices().size();
2090 int nb_integration_pts = OP::getGaussPts().size2();
2091 auto &locMat = OP::locMat;
2092 locMat.resize(row_nb_dofs, col_nb_dofs, false);
2093 locMat.clear();
2094
2095auto integrate_lhs = [&](auto &bc, auto calc_tau, double time_scale) {
2097
2098 auto val = bc.val;
2099 auto t_row_base = row_data.getFTensor0N();
2100 auto t_w = OP::getFTensor0IntegrationWeight();
2101 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
2102 auto t_tangent1 = OP::getFTensor1Tangent1AtGaussPts();
2103 auto t_tangent2 = OP::getFTensor1Tangent2AtGaussPts();
2104
2105 auto t_grad_gamma_u = getFTensor2FromMat<3, 2>(*hybridGradDispPtr);
2107
2108 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2109
2114
2117
2118 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2119 auto t_val = time_scale * t_w * tau * val;
2120
2121 int rr = 0;
2122 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
2123 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
2124 locMat, SPACE_DIM * rr);
2125 auto t_diff_col_base = col_data.getFTensor1DiffN<2>(gg, 0);
2126 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
2128 t_normal_du(i, l) = (FTensor::levi_civita<double>(i, j, k) *
2129 (t_tangent2(k) + t_grad_gamma_u(k, N1))) *
2130 t_kd(j, l) * t_diff_col_base(N0)
2131
2132 +
2133
2134 (FTensor::levi_civita<double>(i, j, k) *
2135 (t_tangent1(j) + t_grad_gamma_u(j, N0))) *
2136 t_kd(k, l) * t_diff_col_base(N1);
2137
2138 t_mat(i, j) += (t_w * t_row_base) * t_val * t_normal_du(i, j);
2139 ++t_mat;
2140 ++t_diff_col_base;
2141 }
2142 ++t_row_base;
2143 }
2144
2145 for (; rr != nb_base_functions; ++rr)
2146 ++t_row_base;
2147 ++t_w;
2148 ++t_coords;
2149 ++t_tangent1;
2150 ++t_tangent2;
2151 ++t_grad_gamma_u;
2152 }
2153
2154 OP::locMat /= 2.;
2155
2157 };
2158
2159 // get entity of face
2160 EntityHandle fe_ent = OP::getFEEntityHandle();
2161 for (auto &bc : *(bcData)) {
2162 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2163
2164 double time_scale = 1;
2165 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2166 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2167 }
2168
2169 int nb_dofs = row_data.getFieldData().size();
2170 if (nb_dofs) {
2171 CHKERR integrate_lhs(
2172 bc, [](double, double, double) { return 1; }, time_scale);
2173 }
2174 }
2175 }
2176
2178
2179}
2180
2182 EntData &col_data) {
2183 return OP::iNtegrate(row_data, col_data);
2184}
2185
2186
2189
2190 FTENSOR_INDEX(3, i);
2191
2192 int nb_dofs = data.getFieldData().size();
2193 int nb_integration_pts = getGaussPts().size2();
2194 int nb_base_functions = data.getN().size2();
2195
2196 double time = getFEMethod()->ts_t;
2199 }
2200
2201#ifndef NDEBUG
2202 if (this->locF.size() != nb_dofs)
2203 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2204 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
2205#endif // NDEBUG
2206
2207 // get entity of face
2208 EntityHandle fe_ent = getFEEntityHandle();
2209 for (auto &bc : *(bcData)) {
2210 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2211
2212 MatrixDouble analytical_expr;
2213 // placeholder to pass boundary block id to python
2214 auto [block_name, v_analytical_expr] =
2215 getAnalyticalExpr(this, analytical_expr, bc.blockName);
2216 auto t_val =
2217 getFTensor1FromMat<3>(v_analytical_expr);
2218 auto t_row_base = data.getFTensor0N();
2219 auto t_w = getFTensor0IntegrationWeight();
2220 auto t_coords = getFTensor1CoordsAtGaussPts();
2221
2222 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2223
2224 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2225
2226 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2227 int rr = 0;
2228 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2229 t_f(i) -= t_w * t_row_base * (t_val(i) * scale);
2230 ++t_row_base;
2231 ++t_f;
2232 }
2233
2234 for (; rr != nb_base_functions; ++rr)
2235 ++t_row_base;
2236 ++t_w;
2237 ++t_coords;
2238 ++t_val;
2239 }
2240 this->locF *= getMeasure();
2241 }
2242 }
2244}
2245
2247 EntData &col_data) {
2249 int nb_integration_pts = row_data.getN().size1();
2250 int row_nb_dofs = row_data.getIndices().size();
2251 int col_nb_dofs = col_data.getIndices().size();
2252 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2254 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2));
2255 };
2256 FTensor::Index<'i', 3> i;
2257 auto v = getVolume();
2258 auto t_w = getFTensor0IntegrationWeight();
2259 int row_nb_base_functions = row_data.getN().size2();
2260 auto t_row_base_fun = row_data.getFTensor0N();
2261 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2262 double a = v * t_w;
2263 int rr = 0;
2264 for (; rr != row_nb_dofs / 3; ++rr) {
2265 auto t_col_diff_base_fun = col_data.getFTensor2DiffN<3, 3>(gg, 0);
2266 auto t_m = get_ftensor1(K, 3 * rr, 0);
2267 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2268 double div_col_base = t_col_diff_base_fun(i, i);
2269 t_m(i) -= a * t_row_base_fun * div_col_base;
2270 ++t_m;
2271 ++t_col_diff_base_fun;
2272 }
2273 ++t_row_base_fun;
2274 }
2275 for (; rr != row_nb_base_functions; ++rr)
2276 ++t_row_base_fun;
2277 ++t_w;
2278 }
2280}
2281
2283 EntData &col_data) {
2285
2286 if (alphaW < std::numeric_limits<double>::epsilon() &&
2287 alphaRho < std::numeric_limits<double>::epsilon())
2289
2290 const int nb_integration_pts = row_data.getN().size1();
2291 const int row_nb_dofs = row_data.getIndices().size();
2292 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2294 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2)
2295
2296 );
2297 };
2298 FTensor::Index<'i', 3> i;
2299
2300 auto v = getVolume();
2301 auto t_w = getFTensor0IntegrationWeight();
2302
2303 auto piola_scale = dataAtPts->piolaScale;
2304 auto alpha_w = alphaW / piola_scale;
2305 auto alpha_rho = alphaRho / piola_scale;
2306
2307 int row_nb_base_functions = row_data.getN().size2();
2308 auto t_row_base_fun = row_data.getFTensor0N();
2309
2310 double ts_scale = alpha_w * getTSa();
2311 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon())
2312 ts_scale += alpha_rho * getTSaa();
2313
2314 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2315 double a = v * t_w * ts_scale;
2316
2317 int rr = 0;
2318 for (; rr != row_nb_dofs / 3; ++rr) {
2319
2320 auto t_col_base_fun = row_data.getFTensor0N(gg, 0);
2321 auto t_m = get_ftensor1(K, 3 * rr, 0);
2322 for (int cc = 0; cc != row_nb_dofs / 3; ++cc) {
2323 const double b = a * t_row_base_fun * t_col_base_fun;
2324 t_m(i) += b;
2325 ++t_m;
2326 ++t_col_base_fun;
2327 }
2328
2329 ++t_row_base_fun;
2330 }
2331
2332 for (; rr != row_nb_base_functions; ++rr)
2333 ++t_row_base_fun;
2334
2335 ++t_w;
2336 }
2337
2339}
2340
2342 EntData &col_data) {
2344
2350
2351 int nb_integration_pts = row_data.getN().size1();
2352 int row_nb_dofs = row_data.getIndices().size();
2353 int col_nb_dofs = col_data.getIndices().size();
2354 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
2356
2357 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2358
2359 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2360
2361 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
2362
2363 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
2364
2365 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
2366
2367 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2));
2368 };
2369
2370 auto v = getVolume();
2371 auto t_w = getFTensor0IntegrationWeight();
2372
2373 int row_nb_base_functions = row_data.getN().size2();
2374 auto t_row_base_fun = row_data.getFTensor0N();
2375
2376 auto t_approx_P_adjoint_log_du_dP =
2377 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
2378
2379 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2380 double a = v * t_w;
2381 int rr = 0;
2382 for (; rr != row_nb_dofs / 6; ++rr) {
2383
2384 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
2385 auto t_m = get_ftensor3(K, 6 * rr, 0);
2386
2387 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2388 t_m(L, i) -=
2389 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(j)) *
2390 t_row_base_fun;
2391 ++t_col_base_fun;
2392 ++t_m;
2393 }
2394
2395 ++t_row_base_fun;
2396 }
2397 for (; rr != row_nb_base_functions; ++rr)
2398 ++t_row_base_fun;
2399 ++t_w;
2400 ++t_approx_P_adjoint_log_du_dP;
2401 }
2402
2404}
2405
2407 EntData &col_data) {
2409
2415
2416 int nb_integration_pts = row_data.getN().size1();
2417 int row_nb_dofs = row_data.getIndices().size();
2418 int col_nb_dofs = col_data.getIndices().size();
2419 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2421 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c), &m(r + 3, c), &m(r + 4, c),
2422 &m(r + 5, c));
2423 };
2424
2425 auto v = getVolume();
2426 auto t_w = getFTensor0IntegrationWeight();
2427 auto t_row_base_fun = row_data.getFTensor0N();
2428
2429 int row_nb_base_functions = row_data.getN().size2();
2430
2431 auto t_approx_P_adjoint_log_du_dP =
2432 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
2433
2434 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2435 double a = v * t_w;
2436 int rr = 0;
2437 for (; rr != row_nb_dofs / 6; ++rr) {
2438 auto t_m = get_ftensor2(K, 6 * rr, 0);
2439 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
2440 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2441 t_m(L) -=
2442 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(i, j)) *
2443 t_row_base_fun;
2444 ++t_m;
2445 ++t_col_base_fun;
2446 }
2447 ++t_row_base_fun;
2448 }
2449 for (; rr != row_nb_base_functions; ++rr)
2450 ++t_row_base_fun;
2451 ++t_w;
2452 ++t_approx_P_adjoint_log_du_dP;
2453 }
2455}
2456
2458 EntData &col_data) {
2460
2462 auto t_L = symm_L_tensor();
2463
2464 int row_nb_dofs = row_data.getIndices().size();
2465 int col_nb_dofs = col_data.getIndices().size();
2466 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
2468
2469 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2470
2471 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2472
2473 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
2474
2475 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
2476
2477 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
2478
2479 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2)
2480
2481 );
2482 };
2483 FTensor::Index<'i', 3> i;
2484 FTensor::Index<'j', 3> j;
2485 FTensor::Index<'k', 3> k;
2486 FTensor::Index<'m', 3> m;
2487 FTensor::Index<'n', 3> n;
2488
2489 auto v = getVolume();
2490 auto t_w = getFTensor0IntegrationWeight();
2491 auto t_approx_P_adjoint_log_du_domega =
2492 getFTensor2FromMat<3, size_symm>(dataAtPts->adjointPdUdOmegaAtPts);
2493
2494 int row_nb_base_functions = row_data.getN().size2();
2495 auto t_row_base_fun = row_data.getFTensor0N();
2496
2497 int nb_integration_pts = row_data.getN().size1();
2498
2499 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2500 double a = v * t_w;
2501
2502 int rr = 0;
2503 for (; rr != row_nb_dofs / 6; ++rr) {
2504 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2505 auto t_m = get_ftensor3(K, 6 * rr, 0);
2506 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2507 double v = a * t_row_base_fun * t_col_base_fun;
2508 t_m(L, k) -= v * t_approx_P_adjoint_log_du_domega(k, L);
2509 ++t_m;
2510 ++t_col_base_fun;
2511 }
2512 ++t_row_base_fun;
2513 }
2514
2515 for (; rr != row_nb_base_functions; ++rr)
2516 ++t_row_base_fun;
2517
2518 ++t_w;
2519 ++t_approx_P_adjoint_log_du_domega;
2520 }
2521
2523}
2524
2526 EntData &col_data) {
2528 int nb_integration_pts = getGaussPts().size2();
2529 int row_nb_dofs = row_data.getIndices().size();
2530 int col_nb_dofs = col_data.getIndices().size();
2531 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2533 size_symm>{
2534
2535 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2), &m(r + 0, c + 3),
2536 &m(r + 0, c + 4), &m(r + 0, c + 5),
2537
2538 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2), &m(r + 1, c + 3),
2539 &m(r + 1, c + 4), &m(r + 1, c + 5),
2540
2541 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2), &m(r + 2, c + 3),
2542 &m(r + 2, c + 4), &m(r + 2, c + 5)
2543
2544 };
2545 };
2546
2549
2550 auto v = getVolume();
2551 auto t_w = getFTensor0IntegrationWeight();
2552 auto t_levi_kirchhoff_du = getFTensor2FromMat<3, size_symm>(
2553 dataAtPts->leviKirchhoffdLogStreatchAtPts);
2554 int row_nb_base_functions = row_data.getN().size2();
2555 auto t_row_base_fun = row_data.getFTensor0N();
2556 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2557 double a = v * t_w;
2558 int rr = 0;
2559 for (; rr != row_nb_dofs / 3; ++rr) {
2560 auto t_m = get_ftensor2(K, 3 * rr, 0);
2561 const double b = a * t_row_base_fun;
2562 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2563 for (int cc = 0; cc != col_nb_dofs / size_symm; ++cc) {
2564 t_m(k, L) -= (b * t_col_base_fun) * t_levi_kirchhoff_du(k, L);
2565 ++t_m;
2566 ++t_col_base_fun;
2567 }
2568 ++t_row_base_fun;
2569 }
2570 for (; rr != row_nb_base_functions; ++rr) {
2571 ++t_row_base_fun;
2572 }
2573 ++t_w;
2574 ++t_levi_kirchhoff_du;
2575 }
2577}
2578
2580 EntData &col_data) {
2582
2589
2590 int nb_integration_pts = getGaussPts().size2();
2591 int row_nb_dofs = row_data.getIndices().size();
2592 int col_nb_dofs = col_data.getIndices().size();
2593 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2595
2596 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2597
2598 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2599
2600 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2601
2602 );
2603 };
2604
2605 auto v = getVolume();
2606 auto t_w = getFTensor0IntegrationWeight();
2607
2608 int row_nb_base_functions = row_data.getN().size2();
2609 auto t_row_base_fun = row_data.getFTensor0N();
2610 auto t_levi_kirchhoff_dP =
2611 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
2612
2613 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2614 double a = v * t_w;
2615 int rr = 0;
2616 for (; rr != row_nb_dofs / 3; ++rr) {
2617 double b = a * t_row_base_fun;
2618 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
2619 auto t_m = get_ftensor2(K, 3 * rr, 0);
2620 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2621 t_m(m, i) -= b * (t_levi_kirchhoff_dP(m, i, k) * t_col_base_fun(k));
2622 ++t_m;
2623 ++t_col_base_fun;
2624 }
2625 ++t_row_base_fun;
2626 }
2627 for (; rr != row_nb_base_functions; ++rr) {
2628 ++t_row_base_fun;
2629 }
2630
2631 ++t_w;
2632 ++t_levi_kirchhoff_dP;
2633 }
2635}
2636
2638 EntData &col_data) {
2640 int nb_integration_pts = getGaussPts().size2();
2641 int row_nb_dofs = row_data.getIndices().size();
2642 int col_nb_dofs = col_data.getIndices().size();
2643
2644 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2646 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c));
2647 };
2648
2649 FTENSOR_INDEX(3, i);
2650 FTENSOR_INDEX(3, k);
2651 FTENSOR_INDEX(3, m);
2652
2653 auto v = getVolume();
2654 auto t_w = getFTensor0IntegrationWeight();
2655 auto t_levi_kirchoff_dP =
2656 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
2657
2658 int row_nb_base_functions = row_data.getN().size2();
2659 auto t_row_base_fun = row_data.getFTensor0N();
2660
2661 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2662 double a = v * t_w;
2663 int rr = 0;
2664 for (; rr != row_nb_dofs / 3; ++rr) {
2665 double b = a * t_row_base_fun;
2666 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
2667 auto t_m = get_ftensor1(K, 3 * rr, 0);
2668 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2669 t_m(m) -= b * (t_levi_kirchoff_dP(m, i, k) * t_col_base_fun(i, k));
2670 ++t_m;
2671 ++t_col_base_fun;
2672 }
2673 ++t_row_base_fun;
2674 }
2675
2676 for (; rr != row_nb_base_functions; ++rr) {
2677 ++t_row_base_fun;
2678 }
2679 ++t_w;
2680 ++t_levi_kirchoff_dP;
2681 }
2683}
2684
2686 EntData &col_data) {
2688 int nb_integration_pts = getGaussPts().size2();
2689 int row_nb_dofs = row_data.getIndices().size();
2690 int col_nb_dofs = col_data.getIndices().size();
2691 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2693
2694 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2695
2696 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2697
2698 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2699
2700 );
2701 };
2702 FTensor::Index<'i', 3> i;
2703 FTensor::Index<'j', 3> j;
2704 FTensor::Index<'k', 3> k;
2705 FTensor::Index<'l', 3> l;
2706 FTensor::Index<'m', 3> m;
2707 FTensor::Index<'n', 3> n;
2708
2710
2711 auto v = getVolume();
2712 auto ts_a = getTSa();
2713 auto t_w = getFTensor0IntegrationWeight();
2714 auto t_levi_kirchhoff_domega =
2715 getFTensor2FromMat<3, 3>(dataAtPts->leviKirchhoffdOmegaAtPts);
2716 int row_nb_base_functions = row_data.getN().size2();
2717 auto t_row_base_fun = row_data.getFTensor0N();
2718 auto t_row_grad_fun = row_data.getFTensor1DiffN<3>();
2719
2720 // auto time_step = getTStimeStep();
2721 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2722 double a = v * t_w;
2723 double c = (a * alphaOmega) * (ts_a /*/ time_step*/);
2724
2725 int rr = 0;
2726 for (; rr != row_nb_dofs / 3; ++rr) {
2727 auto t_m = get_ftensor2(K, 3 * rr, 0);
2728 const double b = a * t_row_base_fun;
2729 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2730 auto t_col_grad_fun = col_data.getFTensor1DiffN<3>(gg, 0);
2731 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2732 t_m(k, l) -= (b * t_col_base_fun) * t_levi_kirchhoff_domega(k, l);
2733 t_m(k, l) += t_kd(k, l) * (c * (t_row_grad_fun(i) * t_col_grad_fun(i)));
2734 ++t_m;
2735 ++t_col_base_fun;
2736 ++t_col_grad_fun;
2737 }
2738 ++t_row_base_fun;
2739 ++t_row_grad_fun;
2740 }
2741 for (; rr != row_nb_base_functions; ++rr) {
2742 ++t_row_base_fun;
2743 ++t_row_grad_fun;
2744 }
2745 ++t_w;
2746 ++t_levi_kirchhoff_domega;
2747 }
2749}
2750
2752 EntData &col_data) {
2754 if (dataAtPts->matInvD.size1() == size_symm &&
2755 dataAtPts->matInvD.size2() == size_symm) {
2756 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2757 } else {
2758 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2759 }
2761};
2762
2763template <int S>
2765 EntData &col_data) {
2767
2768 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2770
2771 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2772
2773 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2774
2775 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2776
2777 );
2778 };
2779
2780 int nb_integration_pts = getGaussPts().size2();
2781 int row_nb_dofs = row_data.getIndices().size();
2782 int col_nb_dofs = col_data.getIndices().size();
2783
2784 auto v = getVolume();
2785 auto t_w = getFTensor0IntegrationWeight();
2786 int row_nb_base_functions = row_data.getN().size2() / 3;
2787
2792
2793 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2794 &*dataAtPts->matInvD.data().begin());
2795
2796 auto t_row_base = row_data.getFTensor1N<3>();
2797 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2798 double a = v * t_w;
2799
2800 int rr = 0;
2801 for (; rr != row_nb_dofs / 3; ++rr) {
2802 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2803 auto t_m = get_ftensor2(K, 3 * rr, 0);
2804 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2805 t_m(i, k) -= a * t_row_base(j) * (t_inv_D(i, j, k, l) * t_col_base(l));
2806 ++t_m;
2807 ++t_col_base;
2808 }
2809
2810 ++t_row_base;
2811 }
2812
2813 for (; rr != row_nb_base_functions; ++rr)
2814 ++t_row_base;
2815
2816 ++t_w;
2817 ++t_inv_D;
2818 }
2820}
2821
2824 EntData &col_data) {
2826 if (dataAtPts->matInvD.size1() == size_symm &&
2827 dataAtPts->matInvD.size2() == size_symm) {
2828 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2829 } else {
2830 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2831 }
2833};
2834
2835template <int S>
2838 EntData &col_data) {
2840
2841 int nb_integration_pts = getGaussPts().size2();
2842 int row_nb_dofs = row_data.getIndices().size();
2843 int col_nb_dofs = col_data.getIndices().size();
2844
2845 auto v = getVolume();
2846 auto t_w = getFTensor0IntegrationWeight();
2847 int row_nb_base_functions = row_data.getN().size2() / 9;
2848
2853
2854 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2855 &*dataAtPts->matInvD.data().begin());
2856
2857 auto t_row_base = row_data.getFTensor2N<3, 3>();
2858 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2859 double a = v * t_w;
2860
2861 int rr = 0;
2862 for (; rr != row_nb_dofs; ++rr) {
2863 auto t_col_base = col_data.getFTensor2N<3, 3>(gg, 0);
2864 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2865 K(rr, cc) -=
2866 a * (t_row_base(i, j) * (t_inv_D(i, j, k, l) * t_col_base(k, l)));
2867 ++t_col_base;
2868 }
2869
2870 ++t_row_base;
2871 }
2872
2873 for (; rr != row_nb_base_functions; ++rr)
2874 ++t_row_base;
2875 ++t_w;
2876 ++t_inv_D;
2877 }
2879}
2880
2882 EntData &col_data) {
2884 if (dataAtPts->matInvD.size1() == size_symm &&
2885 dataAtPts->matInvD.size2() == size_symm) {
2886 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2887 } else {
2888 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2889 }
2891};
2892
2893template <int S>
2896 EntData &col_data) {
2898
2899 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2901
2902 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2)
2903
2904 );
2905 };
2906
2907 int nb_integration_pts = getGaussPts().size2();
2908 int row_nb_dofs = row_data.getIndices().size();
2909 int col_nb_dofs = col_data.getIndices().size();
2910
2911 auto v = getVolume();
2912 auto t_w = getFTensor0IntegrationWeight();
2913 int row_nb_base_functions = row_data.getN().size2() / 9;
2914
2921
2922 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2923 &*dataAtPts->matInvD.data().begin());
2924
2925 auto t_row_base = row_data.getFTensor2N<3, 3>();
2926 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2927 double a = v * t_w;
2928
2929 auto t_m = get_ftensor1(K, 0, 0);
2930
2931 int rr = 0;
2932 for (; rr != row_nb_dofs; ++rr) {
2933 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2934 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2935 t_m(k) -= a * (t_row_base(i, j) * t_inv_D(i, j, k, l)) * t_col_base(l);
2936 ++t_col_base;
2937 ++t_m;
2938 }
2939
2940 ++t_row_base;
2941 }
2942
2943 for (; rr != row_nb_base_functions; ++rr)
2944 ++t_row_base;
2945 ++t_w;
2946 ++t_inv_D;
2947 }
2949}
2950
2952 EntData &col_data) {
2954
2961
2962 int nb_integration_pts = row_data.getN().size1();
2963 int row_nb_dofs = row_data.getIndices().size();
2964 int col_nb_dofs = col_data.getIndices().size();
2965
2966 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2968
2969 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2970
2971 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2972
2973 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2974
2975 );
2976 };
2977
2978 auto v = getVolume();
2979 auto t_w = getFTensor0IntegrationWeight();
2980 int row_nb_base_functions = row_data.getN().size2() / 3;
2981 auto t_row_base_fun = row_data.getFTensor1N<3>();
2982
2983 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
2984
2985 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2986 double a = v * t_w;
2987
2988 int rr = 0;
2989 for (; rr != row_nb_dofs / 3; ++rr) {
2990
2992 t_PRT(i, k) = t_row_base_fun(j) * t_h_domega(i, j, k);
2993
2994 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2995 auto t_m = get_ftensor2(K, 3 * rr, 0);
2996 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2997 t_m(i, j) -= (a * t_col_base_fun) * t_PRT(i, j);
2998 ++t_m;
2999 ++t_col_base_fun;
3000 }
3001
3002 ++t_row_base_fun;
3003 }
3004
3005 for (; rr != row_nb_base_functions; ++rr)
3006 ++t_row_base_fun;
3007 ++t_w;
3008 ++t_h_domega;
3009 }
3011}
3012
3015 EntData &col_data) {
3017
3024
3025 int nb_integration_pts = row_data.getN().size1();
3026 int row_nb_dofs = row_data.getIndices().size();
3027 int col_nb_dofs = col_data.getIndices().size();
3028
3029 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3031 &m(r, c + 0), &m(r, c + 1), &m(r, c + 2));
3032 };
3033
3034 auto v = getVolume();
3035 auto t_w = getFTensor0IntegrationWeight();
3036 int row_nb_base_functions = row_data.getN().size2() / 9;
3037 auto t_row_base_fun = row_data.getFTensor2N<3, 3>();
3038
3039 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
3040 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3041 double a = v * t_w;
3042
3043 int rr = 0;
3044 for (; rr != row_nb_dofs; ++rr) {
3045
3047 t_PRT(k) = t_row_base_fun(i, j) * t_h_domega(i, j, k);
3048
3049 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
3050 auto t_m = get_ftensor2(K, rr, 0);
3051 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3052 t_m(j) -= (a * t_col_base_fun) * t_PRT(j);
3053 ++t_m;
3054 ++t_col_base_fun;
3055 }
3056
3057 ++t_row_base_fun;
3058 }
3059
3060 for (; rr != row_nb_base_functions; ++rr)
3061 ++t_row_base_fun;
3062
3063 ++t_w;
3064 ++t_h_domega;
3065 }
3067}
3068
3070 EntData &data) {
3072
3073 if (tagSense != getSkeletonSense())
3075
3076 auto get_tag = [&](auto name) {
3077 auto &mob = getPtrFE()->mField.get_moab();
3078 Tag tag;
3079 CHK_MOAB_THROW(mob.tag_get_handle(name, tag), "get tag");
3080 return tag;
3081 };
3082
3083 auto get_tag_value = [&](auto &&tag, int dim) {
3084 auto &mob = getPtrFE()->mField.get_moab();
3085 auto face = getSidePtrFE()->getFEEntityHandle();
3086 std::vector<double> value(dim);
3087 CHK_MOAB_THROW(mob.tag_get_data(tag, &face, 1, value.data()), "set tag");
3088 return value;
3089 };
3090
3091 auto create_tag = [this](const std::string tag_name, const int size) {
3092 double def_VAL[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
3093 Tag th;
3094 CHKERR postProcMesh.tag_get_handle(tag_name.c_str(), size, MB_TYPE_DOUBLE,
3095 th, MB_TAG_CREAT | MB_TAG_SPARSE,
3096 def_VAL);
3097 return th;
3098 };
3099
3100 Tag th_cauchy_streess = create_tag("CauchyStress", 9);
3101 Tag th_detF = create_tag("detF", 1);
3102 Tag th_traction = create_tag("traction", 3);
3103 Tag th_disp_error = create_tag("DisplacementError", 1);
3104
3105 Tag th_energy = create_tag("Energy", 1);
3106
3107 auto t_w = getFTensor1FromMat<3>(dataAtPts->wL2AtPts);
3108 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
3109 auto t_approx_P = getFTensor2FromMat<3, 3>(dataAtPts->approxPAtPts);
3110
3111 auto t_normal = getFTensor1NormalsAtGaussPts();
3112 auto t_disp = getFTensor1FromMat<3>(dataAtPts->wH1AtPts);
3113
3114 // auto sense = getSkeletonSense();
3115
3116 auto next = [&]() {
3117 ++t_w;
3118 ++t_h;
3119 ++t_approx_P;
3120 ++t_normal;
3121 ++t_disp;
3122 };
3123
3124 if (dataAtPts->energyAtPts.size() == 0) {
3125 // that is for case that energy is not calculated
3126 dataAtPts->energyAtPts.resize(getGaussPts().size2());
3127 dataAtPts->energyAtPts.clear();
3128 }
3129 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
3130
3131 FTensor::Index<'i', 3> i;
3132 FTensor::Index<'j', 3> j;
3133 FTensor::Index<'k', 3> k;
3134 FTensor::Index<'l', 3> l;
3135
3136 auto set_float_precision = [](const double x) {
3137 if (std::abs(x) < std::numeric_limits<float>::epsilon())
3138 return 0.;
3139 else
3140 return x;
3141 };
3142
3143 // scalars
3144 auto save_scal_tag = [&](auto &th, auto v, const int gg) {
3146 v = set_float_precision(v);
3147 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1, &v);
3149 };
3150
3151 // vectors
3152 VectorDouble3 v(3);
3153 FTensor::Tensor1<FTensor::PackPtr<double *, 0>, 3> t_v(&v[0], &v[1], &v[2]);
3154 auto save_vec_tag = [&](auto &th, auto &t_d, const int gg) {
3156 t_v(i) = t_d(i);
3157 for (auto &a : v.data())
3158 a = set_float_precision(a);
3159 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
3160 &*v.data().begin());
3162 };
3163
3164 // tensors
3165
3166 MatrixDouble3by3 m(3, 3);
3168 &m(0, 0), &m(0, 1), &m(0, 2),
3169
3170 &m(1, 0), &m(1, 1), &m(1, 2),
3171
3172 &m(2, 0), &m(2, 1), &m(2, 2));
3173
3174 auto save_mat_tag = [&](auto &th, auto &t_d, const int gg) {
3176 t_m(i, j) = t_d(i, j);
3177 for (auto &v : m.data())
3178 v = set_float_precision(v);
3179 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
3180 &*m.data().begin());
3182 };
3183
3184 const auto nb_gauss_pts = getGaussPts().size2();
3185 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
3186
3187 FTensor::Tensor1<double, 3> t_traction;
3188 t_traction(i) = t_approx_P(i, j) * t_normal(j) / t_normal.l2();
3189 // vectors
3190 t_traction(i) *= tagSense;
3191 CHKERR save_vec_tag(th_traction, t_traction, gg);
3192
3193 double u_error = sqrt((t_disp(i) - t_w(i)) * (t_disp(i) - t_w(i)));
3194 CHKERR save_scal_tag(th_disp_error, u_error, gg);
3195 CHKERR save_scal_tag(th_energy, t_energy, gg);
3196
3197 const double jac = determinantTensor3by3(t_h);
3199 t_cauchy(i, j) = (1. / jac) * (t_approx_P(i, k) * t_h(j, k));
3200 CHKERR save_mat_tag(th_cauchy_streess, t_cauchy, gg);
3201 CHKERR postProcMesh.tag_set_data(th_detF, &mapGaussPts[gg], 1, &jac);
3202
3203 next();
3204 }
3205
3207}
3208
3210 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3211 std::vector<FieldSpace> spaces, std::string geom_field_name,
3212 boost::shared_ptr<Range> crack_front_edges_ptr) {
3214
3215 constexpr bool scale_l2 = false;
3216
3217 if (scale_l2) {
3218 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3219 "Scale L2 Ainsworth Legendre base is not implemented");
3220 }
3221
3222 CHKERR MoFEM::AddHOOps<2, 3, 3>::add(pipeline, spaces, geom_field_name);
3223
3225}
3226
3228 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3229 std::vector<FieldSpace> spaces, std::string geom_field_name,
3230 boost::shared_ptr<Range> crack_front_edges_ptr) {
3232
3233 constexpr bool scale_l2 = false;
3234
3235 if (scale_l2) {
3236 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3237 "Scale L2 Ainsworth Legendre base is not implemented");
3238 }
3239
3240 CHKERR MoFEM::AddHOOps<2, 2, 3>::add(pipeline, spaces, geom_field_name);
3241
3243}
3244
3246 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3247 std::vector<FieldSpace> spaces, std::string geom_field_name,
3248 boost::shared_ptr<Range> crack_front_edges_ptr,
3249 boost::shared_ptr<MatrixDouble> jac, boost::shared_ptr<VectorDouble> det,
3250 boost::shared_ptr<MatrixDouble> inv_jac) {
3252
3254 auto jac = boost::make_shared<MatrixDouble>();
3255 auto det = boost::make_shared<VectorDouble>();
3257 geom_field_name, jac));
3258 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3259 pipeline.push_back(
3261 }
3262
3263 constexpr bool scale_l2_ainsworth_legendre_base = false;
3264
3265 if (scale_l2_ainsworth_legendre_base) {
3266
3268 : public MoFEM::OpCalculateVectorFieldGradient<SPACE_DIM, SPACE_DIM> {
3269
3271
3272 OpCalculateVectorFieldGradient(const std::string &field_name,
3273 boost::shared_ptr<MatrixDouble> jac,
3274 boost::shared_ptr<Range> edges_ptr)
3275 : OP(field_name, jac), edgesPtr(edges_ptr) {}
3276
3277 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
3278
3279 auto ent = data.getFieldEntities().size()
3280 ? data.getFieldEntities()[0]->getEnt()
3281 : 0;
3282
3283 if (type == MBEDGE && edgesPtr->find(ent) != edgesPtr->end()) {
3284 return 0;
3285 } else {
3286 return OP::doWork(side, type, data);
3287 }
3288 };
3289
3290 private:
3291 boost::shared_ptr<Range> edgesPtr;
3292 };
3293
3294 auto jac = boost::make_shared<MatrixDouble>();
3295 auto det = boost::make_shared<VectorDouble>();
3296 pipeline.push_back(new OpCalculateVectorFieldGradient(
3297 geom_field_name, jac,
3298 EshelbianCore::setSingularity ? crack_front_edges_ptr
3299 : boost::make_shared<Range>()));
3300 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3301 pipeline.push_back(new OpScaleBaseBySpaceInverseOfMeasure(
3303 }
3304
3305 CHKERR MoFEM::AddHOOps<3, 3, 3>::add(pipeline, spaces, geom_field_name,
3306 jac, det, inv_jac);
3307
3309}
3310
3311/**
3312 * @brief Caluclate face material force and normal pressure at gauss points
3313 *
3314 * @param side
3315 * @param type
3316 * @param data
3317 * @return MoFEMErrorCode
3318 *
3319 * Reconstruct the full gradient \f$U=\nabla u\f$ on a surface from the symmetric part and the surface gradient.
3320 *
3321 * @details
3322 * Inputs:
3323 * - \c t_strain : \f$\varepsilon=\tfrac12(U+U^\top)\f$ (symmetric strain on S),
3324 * - \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$,
3325 * - \c t_normal : (possibly non‑unit) surface normal.
3326 *
3327 * Procedure (pointwise on S):
3328 * 1) Normalize the normal \f$\mathbf n=\mathbf N/\|\mathbf N\|\f$.
3329 * 2) Form the residual \f$R=\varepsilon-\operatorname{sym}(u^\Gamma)\f$, where
3330 * \f$\operatorname{sym}(A)=\tfrac12(A+A^\top)\f$.
3331 * 3) Recover the normal directional derivative (a vector)
3332 * \f$\mathbf v=\partial_{\mathbf n}u=2R\mathbf n-(\mathbf n^\top R\,\mathbf n)\,\mathbf n\f$.
3333 * 4) Assemble the full gradient
3334 * \f$U = u^\Gamma + \mathbf v\otimes \mathbf n\f$.
3335 *
3336 * Properties (sanity checks):
3337 * - \f$\tfrac12(U+U^\top)=\varepsilon\f$ (matches the given symmetric part),
3338 * - \f$U P = u^\Gamma\f$ (tangential/right-projected columns unchanged),
3339 * - Only the **normal column** is updated via \f$\mathbf v\otimes\mathbf n\f$.
3340 *
3341 * Mapping to variables in this snippet:
3342 * - \f$\varepsilon \leftrightarrow\f$ \c t_strain,
3343 * - \f$u^\Gamma \leftrightarrow\f$ \c t_grad_u_gamma,
3344 * - \f$\mathbf N \leftrightarrow\f$ \c t_normal (normalized into \c t_N),
3345 * - \f$R \leftrightarrow\f$ \c t_R,
3346 * - \f$U \leftrightarrow\f$ \c t_grad_u.
3347 *
3348 * @pre \c t_normal is nonzero; \c t_strain is symmetric.
3349 * @note All indices use Einstein summation; computation is local to the surface point.
3350 *
3351*/
3353 EntData &data) {
3355
3368
3369 dataAtPts->faceMaterialForceAtPts.resize(3, getGaussPts().size2(), false);
3370 dataAtPts->normalPressureAtPts.resize(getGaussPts().size2(), false);
3371 if (getNinTheLoop() == 0) {
3372 dataAtPts->faceMaterialForceAtPts.clear();
3373 dataAtPts->normalPressureAtPts.clear();
3374 }
3375 auto loop_size = getLoopSize();
3376 if (loop_size == 1) {
3377 auto numebered_fe_ptr = getSidePtrFE()->numeredEntFiniteElementPtr;
3378 auto pstatus = numebered_fe_ptr->getPStatus();
3379 if (pstatus & (PSTATUS_SHARED | PSTATUS_MULTISHARED)) {
3380 loop_size = 2;
3381 }
3382 }
3383
3385
3386 auto t_normal = getFTensor1NormalsAtGaussPts();
3387 auto t_T = getFTensor1FromMat<SPACE_DIM>(
3388 dataAtPts->faceMaterialForceAtPts); //< face material force
3389 auto t_p =
3390 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
3391 auto t_P = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->approxPAtPts);
3392 // auto t_grad_P = getFTensor3FromMat<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
3393 // dataAtPts->gradPAtPts);
3394 auto t_u_gamma =
3395 getFTensor1FromMat<SPACE_DIM>(dataAtPts->hybridDispAtPts);
3396 auto t_grad_u_gamma =
3397 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->gradHybridDispAtPts);
3398 auto t_strain =
3399 getFTensor2SymmetricFromMat<SPACE_DIM>(dataAtPts->logStretchTensorAtPts);
3400 auto t_omega = getFTensor1FromMat<3>(dataAtPts->rotAxisAtPts);
3401
3407
3408 auto next = [&]() {
3409 ++t_normal;
3410 ++t_P;
3411 // ++t_grad_P;
3412 ++t_omega;
3413 ++t_u_gamma;
3414 ++t_grad_u_gamma;
3415 ++t_strain;
3416 ++t_T;
3417 ++t_p;
3418 };
3419
3421 case GRIFFITH_FORCE:
3422 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3423 t_N(I) = t_normal(I);
3424 t_N.normalize();
3425
3426 t_A(i, j) = levi_civita(i, j, k) * t_omega(k);
3427 t_R(i, k) = t_kd(i, k) + t_A(i, k);
3428 t_grad_u(i, j) = t_R(i, j) + t_strain(i, j);
3429
3430 t_T(I) +=
3431 t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
3432 // note that works only for Hooke material, for nonlinear material we need
3433 // strain energy expressed by stress
3434 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2.) / loop_size;
3435
3436 t_p += t_N(I) * (t_N(J) * (t_grad_u_gamma(i, I) * t_P(i, J))) / loop_size;
3437
3438 next();
3439 }
3440 break;
3441 case GRIFFITH_SKELETON:
3442 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3443
3444 // Normalize the normal
3445 t_N(I) = t_normal(I);
3446 t_N.normalize();
3447
3448 // R = ε − sym(u^Γ)
3449 t_R(i, j) =
3450 t_strain(i, j) - 0.5 * (t_grad_u_gamma(i, j) + t_grad_u_gamma(j, i));
3451
3452 // U = u^Γ + [2 R N − (Nᵀ R N) N] ⊗ N
3453 t_grad_u(i, J) = t_grad_u_gamma(i, J) + (2 * t_R(i, K) * t_N(K) -
3454 (t_R(k, L) * t_N(k) * t_N(L)) * t_N(i)) *
3455 t_N(J);
3456
3457 t_T(I) += t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
3458 // note that works only for Hooke material, for nonlinear material we need
3459 // strain energy expressed by stress
3460 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2.) / loop_size;
3461
3462 // calculate nominal face pressure
3463 t_p += t_N(I) * (t_N(J) * (t_grad_u_gamma(i, I) * t_P(i, J))) / loop_size;
3464
3465 next();
3466 }
3467 break;
3468
3469 default:
3470 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3471 "Grffith energy release "
3472 "selector not implemented");
3473 };
3474
3475#ifndef NDEBUG
3476 auto side_fe_ptr = getSidePtrFE();
3477 auto side_fe_mi_ptr = side_fe_ptr->numeredEntFiniteElementPtr;
3478 auto pstatus = side_fe_mi_ptr->getPStatus();
3479 if (pstatus) {
3480 auto owner = side_fe_mi_ptr->getOwnerProc();
3481 MOFEM_LOG("SELF", Sev::noisy)
3482 << "OpFaceSideMaterialForce: owner proc is not 0, owner proc: " << owner
3483 << " " << getPtrFE()->mField.get_comm_rank() << " n in the loop "
3484 << getNinTheLoop() << " loop size " << getLoopSize();
3485 }
3486#endif // NDEBUG
3487
3489}
3490
3492 EntData &data) {
3494
3495#ifndef NDEBUG
3496 auto fe_mi_ptr = getFEMethod()->numeredEntFiniteElementPtr;
3497 auto pstatus = fe_mi_ptr->getPStatus();
3498 if (pstatus) {
3499 auto owner = fe_mi_ptr->getOwnerProc();
3500 MOFEM_LOG("SELF", Sev::noisy)
3501 << "OpFaceMaterialForce: owner proc is not 0, owner proc: " << owner
3502 << " " << getPtrFE()->mField.get_comm_rank();
3503 }
3504#endif // NDEBUG
3505
3507
3509 t_face_T(I) = 0.;
3510 double face_pressure = 0.;
3511 auto t_T = getFTensor1FromMat<SPACE_DIM>(
3512 dataAtPts->faceMaterialForceAtPts); //< face material force
3513 auto t_p =
3514 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
3515 auto t_w = getFTensor0IntegrationWeight();
3516 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3517 t_face_T(I) += t_w * t_T(I);
3518 face_pressure += t_w * t_p;
3519 ++t_w;
3520 ++t_T;
3521 ++t_p;
3522 }
3523 t_face_T(I) *= getMeasure();
3524 face_pressure *= getMeasure();
3525
3526 auto get_tag = [&](auto name, auto dim) {
3527 auto &moab = getPtrFE()->mField.get_moab();
3528 Tag tag;
3529 double def_val[] = {0., 0., 0.};
3530 CHK_MOAB_THROW(moab.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
3531 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
3532 "create tag");
3533 return tag;
3534 };
3535
3536 auto set_tag = [&](auto &&tag, auto ptr) {
3537 auto &moab = getPtrFE()->mField.get_moab();
3538 auto face = getPtrFE()->getFEEntityHandle();
3539 CHK_MOAB_THROW(moab.tag_set_data(tag, &face, 1, ptr), "set tag");
3540 };
3541
3542 set_tag(get_tag("MaterialForce", 3), &t_face_T(0));
3543 set_tag(get_tag("FacePressure", 1), &face_pressure);
3544
3546}
3547
3548
3549template <typename OP_PTR>
3550std::tuple<std::string, MatrixDouble> getAnalyticalExpr(OP_PTR op_ptr, MatrixDouble &analytical_expr,
3551 const std::string block_name) {
3552
3553 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
3554
3555 auto ts_time = op_ptr->getTStime();
3556 auto ts_time_step = op_ptr->getTStimeStep();
3559 ts_time_step = EshelbianCore::dynamicStep;
3560 }
3561
3562 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
3563 MatrixDouble m_ref_normals = op_ptr->getNormalsAtGaussPts();
3564
3565 auto v_analytical_expr =
3566 analytical_expr_function(ts_time_step, ts_time, nb_gauss_pts,
3567 m_ref_coords, m_ref_normals, block_name);
3568
3569#ifndef NDEBUG
3570 if (v_analytical_expr.size2() != nb_gauss_pts)
3572 "Wrong number of integration pts");
3573#endif // NDEBUG
3574
3575 return std::make_tuple(block_name, v_analytical_expr);
3576}
3577
3578//! [Analytical displacement function from python]
3579#ifdef ENABLE_PYTHON_BINDING
3580
3581 MoFEMErrorCode AnalyticalExprPython::analyticalExprInit(const std::string py_file) {
3583 try {
3584
3585 // create main module
3586 auto main_module = bp::import("__main__");
3587 mainNamespace = main_module.attr("__dict__");
3588 bp::exec_file(py_file.c_str(), mainNamespace, mainNamespace);
3589 // create a reference to python function
3590 analyticalDispFun = mainNamespace["analytical_disp"];
3591 analyticalTractionFun = mainNamespace["analytical_traction"];
3592 analyticalExternalStrainFun = mainNamespace["analytical_external_strain"];
3593
3594 } catch (bp::error_already_set const &) {
3595 // print all other errors to stderr
3596 PyErr_Print();
3598 }
3600 }
3601
3602 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalDisp(
3603
3604 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3605 np::ndarray nx, np::ndarray ny, np::ndarray nz,
3606 const std::string &block_name, np::ndarray &analytical_expr
3607
3608 ) {
3610 try {
3611
3612 // call python function
3613 analytical_expr = bp::extract<np::ndarray>(
3614 analyticalDispFun(delta_t, t, x, y, z, nx, ny, nz, block_name));
3615
3616 } catch (bp::error_already_set const &) {
3617 // print all other errors to stderr
3618 PyErr_Print();
3620 }
3622 }
3623
3624 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalTraction(
3625
3626 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3627 np::ndarray nx, np::ndarray ny, np::ndarray nz,
3628 const std::string& block_name, np::ndarray &analytical_expr
3629
3630 ) {
3632 try {
3633
3634 // call python function
3635 analytical_expr = bp::extract<np::ndarray>(
3636 analyticalTractionFun(delta_t, t, x, y, z, nx, ny, nz, block_name));
3637
3638 } catch (bp::error_already_set const &) {
3639 // print all other errors to stderr
3640 PyErr_Print();
3642 }
3644 }
3645
3646 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalExternalStrain(
3647
3648 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3649 const std::string& block_name, np::ndarray &analytical_expr
3650
3651 ) {
3653 try {
3654
3655 // call python function
3656 analytical_expr = bp::extract<np::ndarray>(
3657 analyticalExternalStrainFun(delta_t, t, x, y, z, block_name));
3658
3659 } catch (bp::error_already_set const &) {
3660 // print all other errors to stderr
3661 PyErr_Print();
3663 }
3665 }
3666
3667boost::weak_ptr<AnalyticalExprPython> AnalyticalExprPythonWeakPtr;
3668
3669inline np::ndarray convert_to_numpy(VectorDouble &data, int nb_gauss_pts,
3670 int id) {
3671 auto dtype = np::dtype::get_builtin<double>();
3672 auto size = bp::make_tuple(nb_gauss_pts);
3673 auto stride = bp::make_tuple(3 * sizeof(double));
3674 return (np::from_data(&data[id], dtype, size, stride, bp::object()));
3675};
3676#endif
3677//! Analytical displacement function from python]
3678
3680 int nb_gauss_pts,
3681 MatrixDouble &m_ref_coords,
3682 MatrixDouble &m_ref_normals,
3683 const std::string block_name) {
3684
3685#ifdef ENABLE_PYTHON_BINDING
3686 if (auto analytical_expr_ptr = AnalyticalExprPythonWeakPtr.lock()) {
3687
3688 VectorDouble v_ref_coords = m_ref_coords.data();
3689 VectorDouble v_ref_normals = m_ref_normals.data();
3690
3691 bp::list python_coords;
3692 bp::list python_normals;
3693
3694 for (int idx = 0; idx < 3; ++idx) {
3695 python_coords.append(convert_to_numpy(v_ref_coords, nb_gauss_pts, idx));
3696 python_normals.append(convert_to_numpy(v_ref_normals, nb_gauss_pts, idx));
3697 }
3698
3699 auto disp_block_name = "(.*)ANALYTICAL_DISPLACEMENT(.*)";
3700 auto traction_block_name = "(.*)ANALYTICAL_TRACTION(.*)";
3701
3702 std::regex reg_disp_name(disp_block_name);
3703 std::regex reg_traction_name(traction_block_name);
3704
3705 np::ndarray np_analytical_expr = np::empty(
3706 bp::make_tuple(nb_gauss_pts, 3), np::dtype::get_builtin<double>());
3707
3708 if (std::regex_match(block_name, reg_disp_name)) {
3709 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalDisp(
3710 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3711 bp::extract<np::ndarray>(python_coords[1]),
3712 bp::extract<np::ndarray>(python_coords[2]),
3713 bp::extract<np::ndarray>(python_normals[0]),
3714 bp::extract<np::ndarray>(python_normals[1]),
3715 bp::extract<np::ndarray>(python_normals[2]),
3716 block_name, np_analytical_expr),
3717 "Failed analytical_disp() python call");
3718 } else if (std::regex_match(block_name, reg_traction_name)) {
3719 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalTraction(
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_traction() python call");
3728 } else {
3730 "Unknown analytical block");
3731 }
3732
3733 double *analytical_expr_val_ptr =
3734 reinterpret_cast<double *>(np_analytical_expr.get_data());
3735
3736 MatrixDouble v_analytical_expr;
3737 v_analytical_expr.resize(3, nb_gauss_pts, false);
3738 for (size_t gg = 0; gg < nb_gauss_pts; ++gg) {
3739 for (int idx = 0; idx < 3; ++idx)
3740 v_analytical_expr(idx, gg) =
3741 *(analytical_expr_val_ptr + (3 * gg + idx));
3742 }
3743 return v_analytical_expr;
3744 } else {
3745 // Returns empty vector
3746 }
3747#endif
3748 return MatrixDouble();
3749}
3750
3752 int nb_gauss_pts,
3753 MatrixDouble &m_ref_coords,
3754 const std::string block_name) {
3755
3756#ifdef ENABLE_PYTHON_BINDING
3757 if (auto analytical_expr_ptr = AnalyticalExprPythonWeakPtr.lock()) {
3758
3759 VectorDouble v_ref_coords = m_ref_coords.data();
3760
3761 bp::list python_coords;
3762
3763 for (int idx = 0; idx < 3; ++idx) {
3764 python_coords.append(convert_to_numpy(v_ref_coords, nb_gauss_pts, idx));
3765 }
3766
3767 auto externalstrain_block_name = "(.*)ANALYTICAL_EXTERNALSTRAIN(.*)";
3768
3769 std::regex reg_externalstrain_name(externalstrain_block_name);
3770
3771 np::ndarray np_analytical_expr = np::empty(
3772 bp::make_tuple(nb_gauss_pts), np::dtype::get_builtin<double>());
3773
3774 if (std::regex_match(block_name, reg_externalstrain_name)) {
3775 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalExternalStrain(
3776 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3777 bp::extract<np::ndarray>(python_coords[1]),
3778 bp::extract<np::ndarray>(python_coords[2]), block_name,
3779 np_analytical_expr),
3780 "Failed analytical_external_strain() python call");
3781 } else {
3783 "Unknown analytical block");
3784 }
3785
3786 double *analytical_expr_val_ptr =
3787 reinterpret_cast<double *>(np_analytical_expr.get_data());
3788
3789 VectorDouble v_analytical_expr;
3790 v_analytical_expr.resize(nb_gauss_pts, false);
3791 for (size_t gg = 0; gg < nb_gauss_pts; ++gg)
3792 v_analytical_expr[gg] = *(analytical_expr_val_ptr + gg);
3793
3794 return v_analytical_expr;
3795 } else {
3796 // Returns empty vector
3797 }
3798#endif
3799 return VectorDouble();
3800}
3801
3803 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3804 boost::shared_ptr<MatrixDouble> vec, ScalarFun beta_coeff,
3805 boost::shared_ptr<Range> ents_ptr)
3806 : OP(broken_base_side_data, ents_ptr) {
3807 this->sourceVec = vec;
3808 this->betaCoeff = beta_coeff;
3809}
3810
3812 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3813 ScalarFun beta_coeff, boost::shared_ptr<Range> ents_ptr)
3814 : OP(broken_base_side_data, ents_ptr) {
3815 this->sourceVec = boost::shared_ptr<MatrixDouble>();
3816 this->betaCoeff = beta_coeff;
3817}
3818
3820OpBrokenBaseTimesBrokenDisp::doWork(int row_side, EntityType row_type,
3821 EntitiesFieldData::EntData &row_data) {
3823
3824 if (OP::entsPtr) {
3825 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
3827 }
3828
3829#ifndef NDEBUG
3830 if (!brokenBaseSideData) {
3831 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
3832 }
3833#endif // NDEBUG
3834
3835 auto do_work_rhs = [this](int row_side, EntityType row_type,
3836 EntitiesFieldData::EntData &row_data) {
3838 // get number of dofs on row
3839 OP::nbRows = row_data.getIndices().size();
3840 if (!OP::nbRows)
3842 // get number of integration points
3843 OP::nbIntegrationPts = OP::getGaussPts().size2();
3844 // get row base functions
3845 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
3846 // resize and clear the right hand side vector
3847 OP::locF.resize(OP::nbRows, false);
3848 OP::locF.clear();
3849 // integrate local vector
3850 CHKERR this->iNtegrate(row_data);
3851 // assemble local vector
3852 CHKERR this->aSsemble(row_data);
3854 };
3855
3856 switch (OP::opType) {
3857 case OP::OPSPACE:
3858 for (auto &bd : *brokenBaseSideData) {
3859 this->sourceVec =
3860 boost::shared_ptr<MatrixDouble>(brokenBaseSideData, &bd.getFlux());
3861 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData());
3862 this->sourceVec.reset();
3863 }
3864 break;
3865 default:
3867 (std::string("wrong op type ") +
3868 OpBaseDerivativesBase::OpTypeNames[OP::opType])
3869 .c_str());
3870 }
3871
3873}
3874
3876 const std::string row_field,
3877 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3878 ScalarFun beta_coeff, boost::shared_ptr<Range> ents_ptr)
3879 : OP(row_field, boost::shared_ptr<MatrixDouble>(), beta_coeff, ents_ptr),
3880 brokenBaseSideDataPtr(broken_base_side_data) {
3881 this->betaCoeff = beta_coeff;
3882}
3883
3887 for (auto &bd : (*brokenBaseSideDataPtr)) {
3888 this->sourceVec =
3889 boost::shared_ptr<MatrixDouble>(brokenBaseSideDataPtr, &bd.getFlux());
3890
3891#ifndef NDEBUG
3892 if (this->sourceVec->size1() != SPACE_DIM) {
3893 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3894 "Inconsistent size of the source vector");
3895 }
3896 if (this->sourceVec->size2() != OP::getGaussPts().size2()) {
3897 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3898 "Inconsistent size of the source vector");
3899 }
3900#endif // NDEBUG
3901
3902 CHKERR OP::iNtegrate(data);
3903
3904 this->sourceVec.reset();
3905 }
3907}
3908
3910 std::string row_field,
3911 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3912 ScalarFun beta, const bool assmb_transpose, const bool only_transpose,
3913 boost::shared_ptr<Range> ents_ptr)
3914 : OP(row_field, broken_base_side_data, assmb_transpose, only_transpose,
3915 ents_ptr) {
3916 this->betaCoeff = beta;
3917 this->sYmm = false;
3918 }
3919
3921 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3922 ScalarFun beta, boost::shared_ptr<Range> ents_ptr)
3923 : OP(broken_base_side_data, ents_ptr) {
3924 this->sYmm = false;
3925 this->betaCoeff = beta;
3926}
3927
3929OpBrokenBaseBrokenBase::doWork(int row_side, EntityType row_type,
3930 EntitiesFieldData::EntData &row_data) {
3932
3933 if (OP::entsPtr) {
3934 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
3936 }
3937
3938#ifndef NDEBUG
3939 if (!brokenBaseSideData) {
3940 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
3941 }
3942#endif // NDEBUG
3943
3944 auto do_work_lhs = [this](int row_side, int col_side, EntityType row_type,
3945 EntityType col_type,
3947 EntitiesFieldData::EntData &col_data) {
3949
3950 auto check_if_assemble_transpose = [&] {
3951 if (this->sYmm) {
3952 if (OP::rowSide != OP::colSide || OP::rowType != OP::colType)
3953 return true;
3954 else
3955 return false;
3956 } else if (OP::assembleTranspose) {
3957 return true;
3958 }
3959 return false;
3960 };
3961
3962 OP::rowSide = row_side;
3963 OP::rowType = row_type;
3964 OP::colSide = col_side;
3965 OP::colType = col_type;
3966 OP::nbCols = col_data.getIndices().size();
3967 OP::locMat.resize(OP::nbRows, OP::nbCols, false);
3968 OP::locMat.clear();
3969 CHKERR this->iNtegrate(row_data, col_data);
3970 CHKERR this->aSsemble(row_data, col_data, check_if_assemble_transpose());
3972 };
3973
3974 switch (OP::opType) {
3975 case OP::OPSPACE:
3976
3977 for (auto &bd : *brokenBaseSideData) {
3978
3979#ifndef NDEBUG
3980 if (!bd.getData().getNSharedPtr(bd.getData().getBase())) {
3981 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3982 "base functions not set");
3983 }
3984#endif
3985
3986 OP::nbRows = bd.getData().getIndices().size();
3987 if (!OP::nbRows)
3989 OP::nbIntegrationPts = OP::getGaussPts().size2();
3990 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(bd.getData());
3991
3992 if (!OP::nbRows)
3994
3995 CHKERR do_work_lhs(
3996
3997 // side
3998 bd.getSide(), bd.getSide(),
3999
4000 // type
4001 bd.getType(), bd.getType(),
4002
4003 // row_data
4004 bd.getData(), bd.getData()
4005
4006 );
4007 }
4008
4009 break;
4010
4011 default:
4013 (std::string("wrong op type ") +
4014 OpBaseDerivativesBase::OpTypeNames[OP::opType])
4015 .c_str());
4016 }
4017
4019}
4020
4021} // 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
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data)
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:79
static auto exp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:48
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