v0.15.4
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 for (int gg = 0; gg != nb_integration_pts; ++gg) {
952 double a = v * t_w;
953 auto t_nf = get_ftensor1(nF);
954 int bb = 0;
955 for (; bb != nb_dofs / 3; ++bb) {
956 t_nf(i) -= a * t_row_base_fun * t_div_P(i);
957 t_nf(i) += a * t_row_base_fun * alpha_w * t_s_dot_w(i);
958 t_nf(i) += a * t_row_base_fun * alpha_rho * t_s_dot_dot_w(i);
959 ++t_nf;
960 ++t_row_base_fun;
961 }
962 for (; bb != nb_base_functions; ++bb)
963 ++t_row_base_fun;
964 ++t_w;
965 ++t_div_P;
966 ++t_s_dot_w;
967 ++t_s_dot_dot_w;
968 }
969
971}
972
975 int nb_dofs = data.getIndices().size();
976 int nb_integration_pts = getGaussPts().size2();
977 auto v = getVolume();
978 auto t_w = getFTensor0IntegrationWeight();
979 auto t_levi_kirchhoff = getFTensor1FromMat<3>(dataAtPts->leviKirchhoffAtPts);
980 auto t_omega_grad_dot =
981 getFTensor2FromMat<3, 3>(dataAtPts->rotAxisGradDotAtPts);
982 int nb_base_functions = data.getN().size2();
983 auto t_row_base_fun = data.getFTensor0N();
984 auto t_row_grad_fun = data.getFTensor1DiffN<3>();
985 FTensor::Index<'i', 3> i;
986 FTensor::Index<'j', 3> j;
987 FTensor::Index<'k', 3> k;
988 auto get_ftensor1 = [](auto &v) {
990 &v[2]);
991 };
992 // auto time_step = getTStimeStep();
993
994 for (int gg = 0; gg != nb_integration_pts; ++gg) {
995
996 double a = v * t_w;
997 auto t_nf = get_ftensor1(nF);
998 int bb = 0;
999 for (; bb != nb_dofs / 3; ++bb) {
1000 t_nf(k) -= (a * t_row_base_fun) * t_levi_kirchhoff(k);
1001 t_nf(k) += (a * alphaOmega /*/ time_step*/) *
1002 (t_row_grad_fun(i) * t_omega_grad_dot(k, i));
1003 ++t_nf;
1004 ++t_row_base_fun;
1005 ++t_row_grad_fun;
1006 }
1007 for (; bb != nb_base_functions; ++bb) {
1008 ++t_row_base_fun;
1009 ++t_row_grad_fun;
1010 }
1011 ++t_w;
1012 ++t_levi_kirchhoff;
1013 ++t_omega_grad_dot;
1014 }
1016}
1017
1020 int nb_dofs = data.getIndices().size();
1021 int nb_integration_pts = data.getN().size1();
1022 auto v = getVolume();
1023 auto t_w = getFTensor0IntegrationWeight();
1024
1025 int nb_base_functions = data.getN().size2() / 3;
1026 auto t_row_base_fun = data.getFTensor1N<3>();
1027 FTENSOR_INDEX(3, i);
1028 FTENSOR_INDEX(3, j);
1029 FTENSOR_INDEX(3, k);
1030 FTENSOR_INDEX(3, m);
1031 FTENSOR_INDEX(3, l);
1032
1033 auto get_ftensor1 = [](auto &v) {
1035 &v[2]);
1036 };
1037
1039
1040 auto t_R = getFTensor2FromMat<3, 3>(dataAtPts->rotMatAtPts);
1041 auto t_u = getFTensor2SymmetricFromMat<3>(dataAtPts->stretchTensorAtPts);
1042
1043 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1044 double a = v * t_w;
1045 auto t_nf = get_ftensor1(nF);
1046
1047 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1048
1049 int bb = 0;
1050 for (; bb != nb_dofs / 3; ++bb) {
1051 t_nf(i) -= a * (t_row_base_fun(k) * (t_R(i, l) * t_u(l, k)) / 2);
1052 t_nf(i) -= a * (t_row_base_fun(l) * (t_R(i, k) * t_u(l, k)) / 2);
1053 t_nf(i) += a * (t_row_base_fun(j) * t_kd(i, j));
1054 ++t_nf;
1055 ++t_row_base_fun;
1056 }
1057
1058 for (; bb != nb_base_functions; ++bb)
1059 ++t_row_base_fun;
1060
1061 ++t_w;
1062 ++t_R;
1063 ++t_u;
1064 }
1065
1066 } else {
1067
1068 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
1069
1070 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1071 double a = v * t_w;
1072 auto t_nf = get_ftensor1(nF);
1073
1074 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1076
1077 t_residuum(i, j) = t_h(i, j) - t_kd(i, j);
1078
1079 int bb = 0;
1080 for (; bb != nb_dofs / 3; ++bb) {
1081 t_nf(i) -= a * t_row_base_fun(j) * t_residuum(i, j);
1082 ++t_nf;
1083 ++t_row_base_fun;
1084 }
1085
1086 for (; bb != nb_base_functions; ++bb)
1087 ++t_row_base_fun;
1088
1089 ++t_w;
1090 ++t_h;
1091 }
1092 }
1093
1095}
1096
1099 int nb_dofs = data.getIndices().size();
1100 int nb_integration_pts = data.getN().size1();
1101 auto v = getVolume();
1102 auto t_w = getFTensor0IntegrationWeight();
1103
1104 int nb_base_functions = data.getN().size2() / 9;
1105 auto t_row_base_fun = data.getFTensor2N<3, 3>();
1106 FTENSOR_INDEX(3, i);
1107 FTENSOR_INDEX(3, j);
1108 FTENSOR_INDEX(3, k);
1109 FTENSOR_INDEX(3, m);
1110 FTENSOR_INDEX(3, l);
1111
1112 auto get_ftensor0 = [](auto &v) {
1114 };
1115
1117
1118 auto t_R = getFTensor2FromMat<3, 3>(dataAtPts->rotMatAtPts);
1119 auto t_u = getFTensor2SymmetricFromMat<3>(dataAtPts->stretchTensorAtPts);
1120
1121 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1122 double a = v * t_w;
1123 auto t_nf = get_ftensor0(nF);
1124
1125 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1126
1127 int bb = 0;
1128 for (; bb != nb_dofs; ++bb) {
1129 t_nf -= a * t_row_base_fun(i, k) * (t_R(i, l) * t_u(l, k)) / 2;
1130 t_nf -= a * t_row_base_fun(i, l) * (t_R(i, k) * t_u(l, k)) / 2;
1131 ++t_nf;
1132 ++t_row_base_fun;
1133 }
1134 for (; bb != nb_base_functions; ++bb) {
1135 ++t_row_base_fun;
1136 }
1137 ++t_w;
1138 ++t_R;
1139 ++t_u;
1140 }
1141
1142 } else {
1143
1144 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
1145
1146 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1147 double a = v * t_w;
1148 auto t_nf = get_ftensor0(nF);
1149
1150 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1152 t_residuum(i, j) = t_h(i, j);
1153
1154 int bb = 0;
1155 for (; bb != nb_dofs; ++bb) {
1156 t_nf -= a * t_row_base_fun(i, j) * t_residuum(i, j);
1157 ++t_nf;
1158 ++t_row_base_fun;
1159 }
1160 for (; bb != nb_base_functions; ++bb) {
1161 ++t_row_base_fun;
1162 }
1163 ++t_w;
1164 ++t_h;
1165 }
1166 }
1167
1169}
1170
1173 int nb_dofs = data.getIndices().size();
1174 int nb_integration_pts = data.getN().size1();
1175 auto v = getVolume();
1176 auto t_w = getFTensor0IntegrationWeight();
1177 auto t_w_l2 = getFTensor1FromMat<3>(dataAtPts->wL2AtPts);
1178 int nb_base_functions = data.getN().size2() / 3;
1179 auto t_row_diff_base_fun = data.getFTensor2DiffN<3, 3>();
1180 FTensor::Index<'i', 3> i;
1181 auto get_ftensor1 = [](auto &v) {
1183 &v[2]);
1184 };
1185
1186 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1187 double a = v * t_w;
1188 auto t_nf = get_ftensor1(nF);
1189 int bb = 0;
1190 for (; bb != nb_dofs / 3; ++bb) {
1191 double div_row_base = t_row_diff_base_fun(i, i);
1192 t_nf(i) -= a * div_row_base * t_w_l2(i);
1193 ++t_nf;
1194 ++t_row_diff_base_fun;
1195 }
1196 for (; bb != nb_base_functions; ++bb) {
1197 ++t_row_diff_base_fun;
1198 }
1199 ++t_w;
1200 ++t_w_l2;
1201 }
1202
1204}
1205
1206template <>
1208 EntData &data) {
1210
1211 int nb_integration_pts = getGaussPts().size2();
1212
1213 Tag tag;
1214 CHKERR getPtrFE() -> mField.get_moab().tag_get_handle(tagName.c_str(), tag);
1215 int tag_length;
1216 CHKERR getPtrFE() -> mField.get_moab().tag_get_length(tag, tag_length);
1217 if (tag_length != 9) {
1218 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1219 "Number of internal stress components should be 9 but is %d",
1220 tag_length);
1221 }
1222
1223 VectorDouble const_stress_vec(9);
1224 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1225 CHKERR getPtrFE() -> mField.get_moab().tag_get_data(
1226 tag, &fe_ent, 1, &*const_stress_vec.data().begin());
1227 auto t_const_stress = getFTensor1FromArray<9, 9>(const_stress_vec);
1228
1229 dataAtPts->internalStressAtPts.resize(tag_length, nb_integration_pts, false);
1230 dataAtPts->internalStressAtPts.clear();
1231 auto t_internal_stress =
1232 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1233
1234 FTensor::Index<'L', 9> L;
1235 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1236 t_internal_stress(L) = t_const_stress(L);
1237 ++t_internal_stress;
1238 }
1239
1241}
1242
1243template <>
1245 EntityType type,
1246 EntData &data) {
1248
1249 int nb_integration_pts = getGaussPts().size2();
1250
1251 Tag tag;
1252 CHKERR getPtrFE() -> mField.get_moab().tag_get_handle(tagName.c_str(), tag);
1253 int tag_length;
1254 CHKERR getPtrFE() -> mField.get_moab().tag_get_length(tag, tag_length);
1255 if (tag_length != 9) {
1256 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1257 "Number of internal stress components should be 9 but is %d",
1258 tag_length);
1259 }
1260
1261 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1262 const EntityHandle *vert_conn;
1263 int vert_num;
1264 CHKERR getPtrFE() -> mField.get_moab().get_connectivity(fe_ent, vert_conn,
1265 vert_num, true);
1266 VectorDouble vert_data(vert_num * tag_length);
1267 CHKERR getPtrFE() -> mField.get_moab().tag_get_data(tag, vert_conn, vert_num,
1268 &vert_data[0]);
1269
1270 dataAtPts->internalStressAtPts.resize(tag_length, nb_integration_pts, false);
1271 dataAtPts->internalStressAtPts.clear();
1272 auto t_internal_stress =
1273 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1274
1275 auto t_shape_n = data.getFTensor0N();
1276 int nb_shape_fn = data.getN(NOBASE).size2();
1277 FTensor::Index<'L', 9> L;
1278 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1279 auto t_vert_data = getFTensor1FromArray<9, 9>(vert_data);
1280 for (int bb = 0; bb != nb_shape_fn; ++bb) {
1281 t_internal_stress(L) += t_vert_data(L) * t_shape_n;
1282 ++t_vert_data;
1283 ++t_shape_n;
1284 }
1285 ++t_internal_stress;
1286 }
1287
1289}
1290
1291template <>
1294
1295 int nb_dofs = data.getIndices().size();
1296 int nb_integration_pts = data.getN().size1();
1297 auto v = getVolume();
1298 auto t_w = getFTensor0IntegrationWeight();
1299
1300 FTensor::Index<'i', 3> i;
1301 FTensor::Index<'j', 3> j;
1302
1303 auto get_ftensor2 = [](auto &v) {
1305 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1306 };
1307
1308 auto t_internal_stress =
1309 getFTensor2FromMat<3, 3>(dataAtPts->internalStressAtPts);
1310
1311 const double time = EshelbianCore::dynamicRelaxation ? EshelbianCore::dynamicTime : getFEMethod()->ts_t;
1312
1313 // default scaling is constant
1314 double scale = scalingMethodPtr->getScale(time);
1315
1317 auto t_L = symm_L_tensor();
1318
1319 int nb_base_functions = data.getN().size2();
1320 auto t_row_base_fun = data.getFTensor0N();
1321 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1322 double a = v * t_w;
1323 auto t_nf = get_ftensor2(nF);
1324
1325 FTensor::Tensor2<double, 3, 3> t_symm_stress;
1326 t_symm_stress(i, j) =
1327 (t_internal_stress(i, j) + t_internal_stress(j, i)) / 2;
1328
1330 t_residual(L) = t_L(i, j, L) * (scale * t_symm_stress(i, j));
1331
1332 int bb = 0;
1333 for (; bb != nb_dofs / 6; ++bb) {
1334 t_nf(L) += a * t_row_base_fun * t_residual(L);
1335 ++t_nf;
1336 ++t_row_base_fun;
1337 }
1338 for (; bb != nb_base_functions; ++bb)
1339 ++t_row_base_fun;
1340
1341 ++t_w;
1342 ++t_internal_stress;
1343 }
1345}
1346
1347template <>
1350
1351 int nb_dofs = data.getIndices().size();
1352 int nb_integration_pts = data.getN().size1();
1353 auto v = getVolume();
1354 auto t_w = getFTensor0IntegrationWeight();
1355
1356 auto get_ftensor2 = [](auto &v) {
1358 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1359 };
1360
1361 auto t_internal_stress =
1362 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1363
1365 FTensor::Index<'M', size_symm> M;
1367 t_L = voigt_to_symm();
1368
1369 const double time = EshelbianCore::dynamicRelaxation ? EshelbianCore::dynamicTime : getFEMethod()->ts_t;
1370
1371 // default is constant
1372 double scale = scalingMethodPtr->getScale(time);
1373
1374 int nb_base_functions = data.getN().size2();
1375 auto t_row_base_fun = data.getFTensor0N();
1376 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1377 double a = v * t_w;
1378 auto t_nf = get_ftensor2(nF);
1379
1381 t_residual(L) = t_L(M, L) * (scale * t_internal_stress(M));
1382
1383 int bb = 0;
1384 for (; bb != nb_dofs / 6; ++bb) {
1385 t_nf(L) += a * t_row_base_fun * t_residual(L);
1386 ++t_nf;
1387 ++t_row_base_fun;
1388 }
1389 for (; bb != nb_base_functions; ++bb)
1390 ++t_row_base_fun;
1391
1392 ++t_w;
1393 ++t_internal_stress;
1394 }
1396}
1397
1398template <AssemblyType A>
1401 // get entity of face
1402 EntityHandle fe_ent = OP::getFEEntityHandle();
1403 // iterate over all boundary data
1404 for (auto &bc : (*bcDispPtr)) {
1405 // check if finite element entity is part of boundary condition
1406 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1407 int nb_dofs = data.getIndices().size();
1408
1409 int nb_integration_pts = OP::getGaussPts().size2();
1410 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1411 auto t_w = OP::getFTensor0IntegrationWeight();
1412 int nb_base_functions = data.getN().size2() / 3;
1413 auto t_row_base_fun = data.getFTensor1N<3>();
1414
1417
1418 double scale = 1;
1419 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1421 scale *= scalingMethodsMap.at(bc.blockName)
1422 ->getScale(EshelbianCore::dynamicTime);
1423 } else {
1424 scale *= scalingMethodsMap.at(bc.blockName)
1425 ->getScale(OP::getFEMethod()->ts_t);
1426 }
1427 } else {
1428 MOFEM_LOG("SELF", Sev::warning)
1429 << "No scaling method found for " << bc.blockName;
1430 }
1431
1432 // get bc data
1433 FTensor::Tensor1<double, 3> t_bc_disp(bc.vals[0], bc.vals[1], bc.vals[2]);
1434 t_bc_disp(i) *= scale;
1435
1436 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1437 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1438 int bb = 0;
1439 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1440 t_nf(i) +=
1441 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1442 ++t_nf;
1443 ++t_row_base_fun;
1444 }
1445 for (; bb != nb_base_functions; ++bb)
1446 ++t_row_base_fun;
1447
1448 ++t_w;
1449 ++t_normal;
1450 }
1451 }
1452 }
1454}
1455
1457 return OP::iNtegrate(data);
1458}
1459
1460template <AssemblyType A>
1463
1464 FTENSOR_INDEX(3, i);
1465 FTENSOR_INDEX(3, j);
1466 FTENSOR_INDEX(3, k);
1467
1468 double time = OP::getFEMethod()->ts_t;
1471 }
1472
1473 // get entity of face
1474 EntityHandle fe_ent = OP::getFEEntityHandle();
1475 // interate over all boundary data
1476 for (auto &bc : (*bcRotPtr)) {
1477 // check if finite element entity is part of boundary condition
1478 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1479 int nb_dofs = data.getIndices().size();
1480 int nb_integration_pts = OP::getGaussPts().size2();
1481 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1482 auto t_w = OP::getFTensor0IntegrationWeight();
1483
1484 int nb_base_functions = data.getN().size2() / 3;
1485 auto t_row_base_fun = data.getFTensor1N<3>();
1486
1487 auto get_ftensor1 = [](auto &v) {
1489 &v[2]);
1490 };
1491
1492 // Note: First three values of bc.vals are the center of rotation
1493 // 4th is rotation angle in radians, and remaining values are axis of
1494 // rotation. Also, if rotation axis is not provided, it defaults to the
1495 // normal vector of the face.
1496
1497 // get bc data
1498 FTensor::Tensor1<double, 3> t_center(bc.vals[0], bc.vals[1], bc.vals[2]);
1499
1500 auto get_rotation_angle = [&]() {
1501 double theta = bc.theta;
1502 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1503 theta *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1504 }
1505 return theta;
1506 };
1507
1508 auto get_rotation = [&](auto theta) {
1510 if (bc.vals.size() == 7) {
1511 t_omega(0) = bc.vals[4];
1512 t_omega(1) = bc.vals[5];
1513 t_omega(2) = bc.vals[6];
1514 } else {
1515 // Use gemetric face normal as rotation axis
1516 t_omega(i) = OP::getFTensor1Normal()(i);
1517 }
1518 t_omega.normalize();
1519 t_omega(i) *= theta;
1522 ? 0.
1523 : t_omega.l2());
1524 };
1525
1526 auto t_R = get_rotation(get_rotation_angle());
1527 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1528
1529 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1531 t_delta(i) = t_center(i) - t_coords(i);
1533 t_disp(i) = t_delta(i) - t_R(i, j) * t_delta(j);
1534
1535 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1536 int bb = 0;
1537 for (; bb != nb_dofs / 3; ++bb) {
1538 t_nf(i) += t_w * (t_row_base_fun(j) * t_normal(j)) * t_disp(i) * 0.5;
1539 ++t_nf;
1540 ++t_row_base_fun;
1541 }
1542 for (; bb != nb_base_functions; ++bb)
1543 ++t_row_base_fun;
1544
1545 ++t_w;
1546 ++t_normal;
1547 ++t_coords;
1548 }
1549 }
1550 }
1552}
1553
1555 return OP::iNtegrate(data);
1556}
1557
1558template <AssemblyType A>
1561
1562 double time = OP::getFEMethod()->ts_t;
1565 }
1566
1567 // get entity of face
1568 EntityHandle fe_ent = OP::getFEEntityHandle();
1569 // iterate over all boundary data
1570 for (auto &bc : (*bcDispPtr)) {
1571 // check if finite element entity is part of boundary condition
1572 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1573
1574 for (auto &bd : (*brokenBaseSideDataPtr)) {
1575
1576 auto t_approx_P = getFTensor2FromMat<3, 3>(bd.getFlux());
1577 auto t_u = getFTensor1FromMat<3>(*hybridDispPtr);
1578 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1579 auto t_w = OP::getFTensor0IntegrationWeight();
1580
1583
1585
1586 double scale = 1;
1587 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1588 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1589 } else {
1590 MOFEM_LOG("SELF", Sev::warning)
1591 << "No scaling method found for " << bc.blockName;
1592 }
1593
1594 // get bc data
1595 double val = scale * bc.val;
1596
1597 int nb_dofs = data.getIndices().size();
1598 int nb_integration_pts = OP::getGaussPts().size2();
1599 int nb_base_functions = data.getN().size2();
1600 auto t_row_base = data.getFTensor0N();
1601 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1602
1604 t_N(i) = t_normal(i);
1605 t_N.normalize();
1606
1608 t_P(i, j) = t_N(i) * t_N(j);
1610 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
1611
1612 FTensor::Tensor1<double, 3> t_traction;
1613 t_traction(i) = t_approx_P(i, j) * t_N(j);
1614
1616 t_res(i) =
1617 t_Q(i, j) * t_traction(j) + t_P(i, j) * 2 * t_u(j) - t_N(i) * val;
1618
1619 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1620 int bb = 0;
1621 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1622 t_nf(i) += (t_w * t_row_base * OP::getMeasure()) * t_res(i);
1623 ++t_nf;
1624 ++t_row_base;
1625 }
1626 for (; bb != nb_base_functions; ++bb)
1627 ++t_row_base;
1628
1629 ++t_w;
1630 ++t_normal;
1631 ++t_u;
1632 ++t_approx_P;
1633 }
1634 }
1635 }
1636 }
1638}
1639
1640template <AssemblyType A>
1643 EntData &col_data) {
1645
1646 double time = OP::getFEMethod()->ts_t;
1649 }
1650
1651 int row_nb_dofs = row_data.getIndices().size();
1652 int col_nb_dofs = col_data.getIndices().size();
1653 auto &locMat = OP::locMat;
1654 locMat.resize(row_nb_dofs, col_nb_dofs, false);
1655 locMat.clear();
1656
1657 // get entity of face
1658 EntityHandle fe_ent = OP::getFEEntityHandle();
1659 // iterate over all boundary data
1660 for (auto &bc : (*bcDispPtr)) {
1661 // check if finite element entity is part of boundary condition
1662 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1663
1664 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1665 auto t_w = OP::getFTensor0IntegrationWeight();
1666
1669
1670 double scale = 1;
1671 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1672 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1673 } else {
1674 MOFEM_LOG("SELF", Sev::warning)
1675 << "No scaling method found for " << bc.blockName;
1676 }
1677
1678 int nb_integration_pts = OP::getGaussPts().size2();
1679 int row_nb_dofs = row_data.getIndices().size();
1680 int col_nb_dofs = col_data.getIndices().size();
1681 int nb_base_functions = row_data.getN().size2();
1682 auto t_row_base = row_data.getFTensor0N();
1683
1685
1686 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1687
1689 t_N(i) = t_normal(i);
1690 t_N.normalize();
1691
1693 t_P(i, j) = t_N(i) * t_N(j);
1694
1696 t_d_res(i, j) = 2.0 * t_P(i, j);
1697
1698 int rr = 0;
1699 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
1700 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
1701 locMat, SPACE_DIM * rr);
1702 auto t_col_base = col_data.getFTensor0N(gg, 0);
1703 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
1704 t_mat(i, j) += (t_w * t_row_base * t_col_base) * t_d_res(i, j);
1705 ++t_mat;
1706 ++t_col_base;
1707 }
1708 ++t_row_base;
1709 }
1710
1711 for (; rr != nb_base_functions; ++rr)
1712 ++t_row_base;
1713
1714 ++t_w;
1715 ++t_normal;
1716 }
1717
1718 locMat *= OP::getMeasure();
1719
1720 }
1721 }
1723}
1724
1725template <AssemblyType A>
1728 EntData &col_data) {
1730
1731 double time = OP::getFEMethod()->ts_t;
1734 }
1735
1736 int row_nb_dofs = row_data.getIndices().size();
1737 int col_nb_dofs = col_data.getIndices().size();
1738 auto &locMat = OP::locMat;
1739 locMat.resize(row_nb_dofs, col_nb_dofs, false);
1740 locMat.clear();
1741
1742 // get entity of face
1743 EntityHandle fe_ent = OP::getFEEntityHandle();
1744 // iterate over all boundary data
1745 for (auto &bc : (*bcDispPtr)) {
1746 // check if finite element entity is part of boundary condition
1747 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1748
1749 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1750 auto t_w = OP::getFTensor0IntegrationWeight();
1751
1755
1757
1758 double scale = 1;
1759 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1760 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1761 } else {
1762 MOFEM_LOG("SELF", Sev::warning)
1763 << "No scaling method found for " << bc.blockName;
1764 }
1765
1766 int nb_integration_pts = OP::getGaussPts().size2();
1767 int nb_base_functions = row_data.getN().size2();
1768 auto t_row_base = row_data.getFTensor0N();
1769
1770 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1771
1773 t_N(i) = t_normal(i);
1774 t_N.normalize();
1775
1777 t_P(i, j) = t_N(i) * t_N(j);
1779 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
1780
1782 t_d_res(i, j) = t_Q(i, j);
1783
1784 int rr = 0;
1785 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
1786 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
1787 OP::locMat, SPACE_DIM * rr);
1788 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1789 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
1790 t_mat(i, j) +=
1791 ((t_w * t_row_base) * (t_N(k) * t_col_base(k))) * t_d_res(i, j);
1792 ++t_mat;
1793 ++t_col_base;
1794 }
1795 ++t_row_base;
1796 }
1797
1798 for (; rr != nb_base_functions; ++rr)
1799 ++t_row_base;
1800
1801 ++t_w;
1802 ++t_normal;
1803 }
1804
1805 locMat *= OP::getMeasure();
1806 }
1807 }
1809}
1810
1812 return OP::iNtegrate(data);
1813}
1814
1816 EntData &col_data) {
1817 return OP::iNtegrate(row_data, col_data);
1818}
1819
1821 EntData &col_data) {
1822 return OP::iNtegrate(row_data, col_data);
1823}
1824
1825template <AssemblyType A>
1828
1829 double time = OP::getFEMethod()->ts_t;
1832 }
1833
1834 // get entity of face
1835 EntityHandle fe_ent = OP::getFEEntityHandle();
1836 // iterate over all boundary data
1837 for (auto &bc : (*bcDispPtr)) {
1838 // check if finite element entity is part of boundary condition
1839 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1840
1841 MatrixDouble analytical_expr;
1842 // placeholder to pass boundary block id to python
1843
1844 auto [block_name, v_analytical_expr] =
1845 getAnalyticalExpr(this, analytical_expr, bc.blockName);
1846
1847 int nb_dofs = data.getIndices().size();
1848
1849 int nb_integration_pts = OP::getGaussPts().size2();
1850 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1851 auto t_w = OP::getFTensor0IntegrationWeight();
1852 int nb_base_functions = data.getN().size2() / 3;
1853 auto t_row_base_fun = data.getFTensor1N<3>();
1854 auto t_coord = OP::getFTensor1CoordsAtGaussPts();
1855
1858
1859 // get bc data
1860 auto t_bc_disp = getFTensor1FromMat<3>(v_analytical_expr);
1861
1862 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1863 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1864
1865 int bb = 0;
1866 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1867 t_nf(i) +=
1868 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1869 ++t_nf;
1870 ++t_row_base_fun;
1871 }
1872 for (; bb != nb_base_functions; ++bb)
1873 ++t_row_base_fun;
1874
1875 ++t_bc_disp;
1876 ++t_coord;
1877 ++t_w;
1878 ++t_normal;
1879 }
1880 }
1881 }
1883}
1884
1886 return OP::iNtegrate(data);
1887}
1888
1891
1892 FTENSOR_INDEX(3, i);
1893
1894 int nb_dofs = data.getFieldData().size();
1895 int nb_integration_pts = getGaussPts().size2();
1896 int nb_base_functions = data.getN().size2();
1897
1898 double time = getFEMethod()->ts_t;
1901 }
1902
1903#ifndef NDEBUG
1904 if (this->locF.size() != nb_dofs)
1905 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1906 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
1907#endif // NDEBUG
1908
1909 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1911
1912 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
1913 auto t_row_base = data.getFTensor0N();
1914 auto t_w = getFTensor0IntegrationWeight();
1915 auto t_coords = getFTensor1CoordsAtGaussPts();
1916
1917 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
1918
1919 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1920
1921 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
1922 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
1923 int rr = 0;
1924 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1925 t_f(i) -= (time_scale * t_w * t_row_base * tau) * (t_val(i) * scale);
1926 ++t_row_base;
1927 ++t_f;
1928 }
1929
1930 for (; rr != nb_base_functions; ++rr)
1931 ++t_row_base;
1932 ++t_w;
1933 ++t_coords;
1934 }
1935 this->locF *= getMeasure();
1937 };
1938
1939 // get entity of face
1940 EntityHandle fe_ent = getFEEntityHandle();
1941 for (auto &bc : *(bcData)) {
1942 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1943
1944 double time_scale = 1;
1945 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1946 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1947 }
1948
1949 int nb_dofs = data.getFieldData().size();
1950 if (nb_dofs) {
1951
1952 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
1953 auto calc_tau = [](double, double y, double) {
1954 y -= 44;
1955 y /= (60 - 44);
1956 return -y * (y - 1) / 0.25;
1957 };
1958 CHKERR integrate_rhs(bc, calc_tau, time_scale);
1959 } else {
1960 CHKERR integrate_rhs(
1961 bc, [](double, double, double) { return 1; }, time_scale);
1962 }
1963 }
1964 }
1965 }
1967}
1968
1971
1972 FTENSOR_INDEX(3, i);
1973
1974 int nb_dofs = data.getFieldData().size();
1975 int nb_integration_pts = getGaussPts().size2();
1976 int nb_base_functions = data.getN().size2();
1977
1978 double time = getFEMethod()->ts_t;
1981 }
1982
1983#ifndef NDEBUG
1984 if (this->locF.size() != nb_dofs)
1985 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1986 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
1987#endif // NDEBUG
1988
1989 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1991
1992 auto val = bc.val;
1993 auto t_row_base = data.getFTensor0N();
1994 auto t_w = getFTensor0IntegrationWeight();
1995 auto t_coords = getFTensor1CoordsAtGaussPts();
1996 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1997 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1998
1999 auto t_grad_gamma_u = getFTensor2FromMat<3, 2>(*hybridGradDispPtr);
2000
2001 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2002
2003 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2004
2010
2014
2015 t_normal(i) = (FTensor::levi_civita<double>(i, j, k) * t_tangent1(j)) *
2016 t_tangent2(k);
2017 } else {
2018 t_normal(i) = (FTensor::levi_civita<double>(i, j, k) *
2019 (t_tangent1(j) + t_grad_gamma_u(j, N0))) *
2020 (t_tangent2(k) + t_grad_gamma_u(k, N1));
2021 }
2022 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2023 auto t_val = FTensor::Tensor1<double, 3>();
2024 t_val(i) = (time_scale * t_w * tau * scale * val) * t_normal(i);
2025
2026 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2027 int rr = 0;
2028 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2029 t_f(i) += t_row_base * t_val(i);
2030 ++t_row_base;
2031 ++t_f;
2032 }
2033
2034 for (; rr != nb_base_functions; ++rr)
2035 ++t_row_base;
2036 ++t_w;
2037 ++t_coords;
2038 ++t_tangent1;
2039 ++t_tangent2;
2040 ++t_grad_gamma_u;
2041 }
2042 this->locF /= 2.;
2043
2045 };
2046
2047 // get entity of face
2048 EntityHandle fe_ent = getFEEntityHandle();
2049 for (auto &bc : *(bcData)) {
2050 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2051
2052 double time_scale = 1;
2053 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2054 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2055 }
2056
2057 int nb_dofs = data.getFieldData().size();
2058 if (nb_dofs) {
2059 CHKERR integrate_rhs(
2060 bc, [](double, double, double) { return 1; }, time_scale);
2061 }
2062 }
2063 }
2065}
2066
2067template <AssemblyType A>
2070 EntData &col_data) {
2072
2076 }
2077
2078 double time = OP::getFEMethod()->ts_t;
2081 }
2082
2083 int nb_base_functions = row_data.getN().size2();
2084 int row_nb_dofs = row_data.getIndices().size();
2085 int col_nb_dofs = col_data.getIndices().size();
2086 int nb_integration_pts = OP::getGaussPts().size2();
2087 auto &locMat = OP::locMat;
2088 locMat.resize(row_nb_dofs, col_nb_dofs, false);
2089 locMat.clear();
2090
2091auto integrate_lhs = [&](auto &bc, auto calc_tau, double time_scale) {
2093
2094 auto val = bc.val;
2095 auto t_row_base = row_data.getFTensor0N();
2096 auto t_w = OP::getFTensor0IntegrationWeight();
2097 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
2098 auto t_tangent1 = OP::getFTensor1Tangent1AtGaussPts();
2099 auto t_tangent2 = OP::getFTensor1Tangent2AtGaussPts();
2100
2101 auto t_grad_gamma_u = getFTensor2FromMat<3, 2>(*hybridGradDispPtr);
2103
2104 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2105
2110
2113
2114 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2115 auto t_val = time_scale * t_w * tau * val;
2116
2117 int rr = 0;
2118 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
2119 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
2120 locMat, SPACE_DIM * rr);
2121 auto t_diff_col_base = col_data.getFTensor1DiffN<2>(gg, 0);
2122 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
2124 t_normal_du(i, l) = (FTensor::levi_civita<double>(i, j, k) *
2125 (t_tangent2(k) + t_grad_gamma_u(k, N1))) *
2126 t_kd(j, l) * t_diff_col_base(N0)
2127
2128 +
2129
2130 (FTensor::levi_civita<double>(i, j, k) *
2131 (t_tangent1(j) + t_grad_gamma_u(j, N0))) *
2132 t_kd(k, l) * t_diff_col_base(N1);
2133
2134 t_mat(i, j) += (t_w * t_row_base) * t_val * t_normal_du(i, j);
2135 ++t_mat;
2136 ++t_diff_col_base;
2137 }
2138 ++t_row_base;
2139 }
2140
2141 for (; rr != nb_base_functions; ++rr)
2142 ++t_row_base;
2143 ++t_w;
2144 ++t_coords;
2145 ++t_tangent1;
2146 ++t_tangent2;
2147 ++t_grad_gamma_u;
2148 }
2149
2150 OP::locMat /= 2.;
2151
2153 };
2154
2155 // get entity of face
2156 EntityHandle fe_ent = OP::getFEEntityHandle();
2157 for (auto &bc : *(bcData)) {
2158 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2159
2160 double time_scale = 1;
2161 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2162 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2163 }
2164
2165 int nb_dofs = row_data.getFieldData().size();
2166 if (nb_dofs) {
2167 CHKERR integrate_lhs(
2168 bc, [](double, double, double) { return 1; }, time_scale);
2169 }
2170 }
2171 }
2172
2174
2175}
2176
2178 EntData &col_data) {
2179 return OP::iNtegrate(row_data, col_data);
2180}
2181
2182
2185
2186 FTENSOR_INDEX(3, i);
2187
2188 int nb_dofs = data.getFieldData().size();
2189 int nb_integration_pts = getGaussPts().size2();
2190 int nb_base_functions = data.getN().size2();
2191
2192 double time = getFEMethod()->ts_t;
2195 }
2196
2197#ifndef NDEBUG
2198 if (this->locF.size() != nb_dofs)
2199 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2200 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
2201#endif // NDEBUG
2202
2203 // get entity of face
2204 EntityHandle fe_ent = getFEEntityHandle();
2205 for (auto &bc : *(bcData)) {
2206 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2207
2208 MatrixDouble analytical_expr;
2209 // placeholder to pass boundary block id to python
2210 auto [block_name, v_analytical_expr] =
2211 getAnalyticalExpr(this, analytical_expr, bc.blockName);
2212 auto t_val =
2213 getFTensor1FromMat<3>(v_analytical_expr);
2214 auto t_row_base = data.getFTensor0N();
2215 auto t_w = getFTensor0IntegrationWeight();
2216 auto t_coords = getFTensor1CoordsAtGaussPts();
2217
2218 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2219
2220 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2221
2222 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2223 int rr = 0;
2224 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2225 t_f(i) -= t_w * t_row_base * (t_val(i) * scale);
2226 ++t_row_base;
2227 ++t_f;
2228 }
2229
2230 for (; rr != nb_base_functions; ++rr)
2231 ++t_row_base;
2232 ++t_w;
2233 ++t_coords;
2234 ++t_val;
2235 }
2236 this->locF *= getMeasure();
2237 }
2238 }
2240}
2241
2243 EntData &col_data) {
2245 int nb_integration_pts = row_data.getN().size1();
2246 int row_nb_dofs = row_data.getIndices().size();
2247 int col_nb_dofs = col_data.getIndices().size();
2248 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2250 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2));
2251 };
2252 FTensor::Index<'i', 3> i;
2253 auto v = getVolume();
2254 auto t_w = getFTensor0IntegrationWeight();
2255 int row_nb_base_functions = row_data.getN().size2();
2256 auto t_row_base_fun = row_data.getFTensor0N();
2257 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2258 double a = v * t_w;
2259 int rr = 0;
2260 for (; rr != row_nb_dofs / 3; ++rr) {
2261 auto t_col_diff_base_fun = col_data.getFTensor2DiffN<3, 3>(gg, 0);
2262 auto t_m = get_ftensor1(K, 3 * rr, 0);
2263 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2264 double div_col_base = t_col_diff_base_fun(i, i);
2265 t_m(i) -= a * t_row_base_fun * div_col_base;
2266 ++t_m;
2267 ++t_col_diff_base_fun;
2268 }
2269 ++t_row_base_fun;
2270 }
2271 for (; rr != row_nb_base_functions; ++rr)
2272 ++t_row_base_fun;
2273 ++t_w;
2274 }
2276}
2277
2279 EntData &col_data) {
2281
2282 if (alphaW < std::numeric_limits<double>::epsilon() &&
2283 alphaRho < std::numeric_limits<double>::epsilon())
2285
2286 const int nb_integration_pts = row_data.getN().size1();
2287 const int row_nb_dofs = row_data.getIndices().size();
2288 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2290 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2)
2291
2292 );
2293 };
2294 FTensor::Index<'i', 3> i;
2295
2296 auto v = getVolume();
2297 auto t_w = getFTensor0IntegrationWeight();
2298
2299 auto piola_scale = dataAtPts->piolaScale;
2300 auto alpha_w = alphaW / piola_scale;
2301 auto alpha_rho = alphaRho / piola_scale;
2302
2303 int row_nb_base_functions = row_data.getN().size2();
2304 auto t_row_base_fun = row_data.getFTensor0N();
2305
2306 double ts_scale = alpha_w * getTSa();
2307 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon())
2308 ts_scale += alpha_rho * getTSaa();
2309
2310 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2311 double a = v * t_w * ts_scale;
2312
2313 int rr = 0;
2314 for (; rr != row_nb_dofs / 3; ++rr) {
2315
2316 auto t_col_base_fun = row_data.getFTensor0N(gg, 0);
2317 auto t_m = get_ftensor1(K, 3 * rr, 0);
2318 for (int cc = 0; cc != row_nb_dofs / 3; ++cc) {
2319 const double b = a * t_row_base_fun * t_col_base_fun;
2320 t_m(i) += b;
2321 ++t_m;
2322 ++t_col_base_fun;
2323 }
2324
2325 ++t_row_base_fun;
2326 }
2327
2328 for (; rr != row_nb_base_functions; ++rr)
2329 ++t_row_base_fun;
2330
2331 ++t_w;
2332 }
2333
2335}
2336
2338 EntData &col_data) {
2340
2346
2347 int nb_integration_pts = row_data.getN().size1();
2348 int row_nb_dofs = row_data.getIndices().size();
2349 int col_nb_dofs = col_data.getIndices().size();
2350 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
2352
2353 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2354
2355 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2356
2357 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
2358
2359 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
2360
2361 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
2362
2363 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2));
2364 };
2365
2366 auto v = getVolume();
2367 auto t_w = getFTensor0IntegrationWeight();
2368
2369 int row_nb_base_functions = row_data.getN().size2();
2370 auto t_row_base_fun = row_data.getFTensor0N();
2371
2372 auto t_approx_P_adjoint_log_du_dP =
2373 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
2374
2375 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2376 double a = v * t_w;
2377 int rr = 0;
2378 for (; rr != row_nb_dofs / 6; ++rr) {
2379
2380 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
2381 auto t_m = get_ftensor3(K, 6 * rr, 0);
2382
2383 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2384 t_m(L, i) -=
2385 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(j)) *
2386 t_row_base_fun;
2387 ++t_col_base_fun;
2388 ++t_m;
2389 }
2390
2391 ++t_row_base_fun;
2392 }
2393 for (; rr != row_nb_base_functions; ++rr)
2394 ++t_row_base_fun;
2395 ++t_w;
2396 ++t_approx_P_adjoint_log_du_dP;
2397 }
2398
2400}
2401
2403 EntData &col_data) {
2405
2411
2412 int nb_integration_pts = row_data.getN().size1();
2413 int row_nb_dofs = row_data.getIndices().size();
2414 int col_nb_dofs = col_data.getIndices().size();
2415 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2417 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c), &m(r + 3, c), &m(r + 4, c),
2418 &m(r + 5, c));
2419 };
2420
2421 auto v = getVolume();
2422 auto t_w = getFTensor0IntegrationWeight();
2423 auto t_row_base_fun = row_data.getFTensor0N();
2424
2425 int row_nb_base_functions = row_data.getN().size2();
2426
2427 auto t_approx_P_adjoint_log_du_dP =
2428 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
2429
2430 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2431 double a = v * t_w;
2432 int rr = 0;
2433 for (; rr != row_nb_dofs / 6; ++rr) {
2434 auto t_m = get_ftensor2(K, 6 * rr, 0);
2435 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
2436 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2437 t_m(L) -=
2438 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(i, j)) *
2439 t_row_base_fun;
2440 ++t_m;
2441 ++t_col_base_fun;
2442 }
2443 ++t_row_base_fun;
2444 }
2445 for (; rr != row_nb_base_functions; ++rr)
2446 ++t_row_base_fun;
2447 ++t_w;
2448 ++t_approx_P_adjoint_log_du_dP;
2449 }
2451}
2452
2454 EntData &col_data) {
2456
2458 auto t_L = symm_L_tensor();
2459
2460 int row_nb_dofs = row_data.getIndices().size();
2461 int col_nb_dofs = col_data.getIndices().size();
2462 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
2464
2465 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2466
2467 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2468
2469 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
2470
2471 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
2472
2473 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
2474
2475 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2)
2476
2477 );
2478 };
2479 FTensor::Index<'i', 3> i;
2480 FTensor::Index<'j', 3> j;
2481 FTensor::Index<'k', 3> k;
2482 FTensor::Index<'m', 3> m;
2483 FTensor::Index<'n', 3> n;
2484
2485 auto v = getVolume();
2486 auto t_w = getFTensor0IntegrationWeight();
2487 auto t_approx_P_adjoint_log_du_domega =
2488 getFTensor2FromMat<3, size_symm>(dataAtPts->adjointPdUdOmegaAtPts);
2489
2490 int row_nb_base_functions = row_data.getN().size2();
2491 auto t_row_base_fun = row_data.getFTensor0N();
2492
2493 int nb_integration_pts = row_data.getN().size1();
2494
2495 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2496 double a = v * t_w;
2497
2498 int rr = 0;
2499 for (; rr != row_nb_dofs / 6; ++rr) {
2500 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2501 auto t_m = get_ftensor3(K, 6 * rr, 0);
2502 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2503 double v = a * t_row_base_fun * t_col_base_fun;
2504 t_m(L, k) -= v * t_approx_P_adjoint_log_du_domega(k, L);
2505 ++t_m;
2506 ++t_col_base_fun;
2507 }
2508 ++t_row_base_fun;
2509 }
2510
2511 for (; rr != row_nb_base_functions; ++rr)
2512 ++t_row_base_fun;
2513
2514 ++t_w;
2515 ++t_approx_P_adjoint_log_du_domega;
2516 }
2517
2519}
2520
2522 EntData &col_data) {
2524 int nb_integration_pts = getGaussPts().size2();
2525 int row_nb_dofs = row_data.getIndices().size();
2526 int col_nb_dofs = col_data.getIndices().size();
2527 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2529 size_symm>{
2530
2531 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2), &m(r + 0, c + 3),
2532 &m(r + 0, c + 4), &m(r + 0, c + 5),
2533
2534 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2), &m(r + 1, c + 3),
2535 &m(r + 1, c + 4), &m(r + 1, c + 5),
2536
2537 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2), &m(r + 2, c + 3),
2538 &m(r + 2, c + 4), &m(r + 2, c + 5)
2539
2540 };
2541 };
2542
2545
2546 auto v = getVolume();
2547 auto t_w = getFTensor0IntegrationWeight();
2548 auto t_levi_kirchhoff_du = getFTensor2FromMat<3, size_symm>(
2549 dataAtPts->leviKirchhoffdLogStreatchAtPts);
2550 int row_nb_base_functions = row_data.getN().size2();
2551 auto t_row_base_fun = row_data.getFTensor0N();
2552 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2553 double a = v * t_w;
2554 int rr = 0;
2555 for (; rr != row_nb_dofs / 3; ++rr) {
2556 auto t_m = get_ftensor2(K, 3 * rr, 0);
2557 const double b = a * t_row_base_fun;
2558 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2559 for (int cc = 0; cc != col_nb_dofs / size_symm; ++cc) {
2560 t_m(k, L) -= (b * t_col_base_fun) * t_levi_kirchhoff_du(k, L);
2561 ++t_m;
2562 ++t_col_base_fun;
2563 }
2564 ++t_row_base_fun;
2565 }
2566 for (; rr != row_nb_base_functions; ++rr) {
2567 ++t_row_base_fun;
2568 }
2569 ++t_w;
2570 ++t_levi_kirchhoff_du;
2571 }
2573}
2574
2576 EntData &col_data) {
2578
2585
2586 int nb_integration_pts = getGaussPts().size2();
2587 int row_nb_dofs = row_data.getIndices().size();
2588 int col_nb_dofs = col_data.getIndices().size();
2589 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2591
2592 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2593
2594 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2595
2596 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2597
2598 );
2599 };
2600
2601 auto v = getVolume();
2602 auto t_w = getFTensor0IntegrationWeight();
2603
2604 int row_nb_base_functions = row_data.getN().size2();
2605 auto t_row_base_fun = row_data.getFTensor0N();
2606 auto t_levi_kirchhoff_dP =
2607 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
2608
2609 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2610 double a = v * t_w;
2611 int rr = 0;
2612 for (; rr != row_nb_dofs / 3; ++rr) {
2613 double b = a * t_row_base_fun;
2614 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
2615 auto t_m = get_ftensor2(K, 3 * rr, 0);
2616 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2617 t_m(m, i) -= b * (t_levi_kirchhoff_dP(m, i, k) * t_col_base_fun(k));
2618 ++t_m;
2619 ++t_col_base_fun;
2620 }
2621 ++t_row_base_fun;
2622 }
2623 for (; rr != row_nb_base_functions; ++rr) {
2624 ++t_row_base_fun;
2625 }
2626
2627 ++t_w;
2628 ++t_levi_kirchhoff_dP;
2629 }
2631}
2632
2634 EntData &col_data) {
2636 int nb_integration_pts = getGaussPts().size2();
2637 int row_nb_dofs = row_data.getIndices().size();
2638 int col_nb_dofs = col_data.getIndices().size();
2639
2640 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2642 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c));
2643 };
2644
2645 FTENSOR_INDEX(3, i);
2646 FTENSOR_INDEX(3, k);
2647 FTENSOR_INDEX(3, m);
2648
2649 auto v = getVolume();
2650 auto t_w = getFTensor0IntegrationWeight();
2651 auto t_levi_kirchoff_dP =
2652 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
2653
2654 int row_nb_base_functions = row_data.getN().size2();
2655 auto t_row_base_fun = row_data.getFTensor0N();
2656
2657 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2658 double a = v * t_w;
2659 int rr = 0;
2660 for (; rr != row_nb_dofs / 3; ++rr) {
2661 double b = a * t_row_base_fun;
2662 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
2663 auto t_m = get_ftensor1(K, 3 * rr, 0);
2664 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2665 t_m(m) -= b * (t_levi_kirchoff_dP(m, i, k) * t_col_base_fun(i, k));
2666 ++t_m;
2667 ++t_col_base_fun;
2668 }
2669 ++t_row_base_fun;
2670 }
2671
2672 for (; rr != row_nb_base_functions; ++rr) {
2673 ++t_row_base_fun;
2674 }
2675 ++t_w;
2676 ++t_levi_kirchoff_dP;
2677 }
2679}
2680
2682 EntData &col_data) {
2684 int nb_integration_pts = getGaussPts().size2();
2685 int row_nb_dofs = row_data.getIndices().size();
2686 int col_nb_dofs = col_data.getIndices().size();
2687 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2689
2690 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2691
2692 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2693
2694 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2695
2696 );
2697 };
2698 FTensor::Index<'i', 3> i;
2699 FTensor::Index<'j', 3> j;
2700 FTensor::Index<'k', 3> k;
2701 FTensor::Index<'l', 3> l;
2702 FTensor::Index<'m', 3> m;
2703 FTensor::Index<'n', 3> n;
2704
2706
2707 auto v = getVolume();
2708 auto ts_a = getTSa();
2709 auto t_w = getFTensor0IntegrationWeight();
2710 auto t_levi_kirchhoff_domega =
2711 getFTensor2FromMat<3, 3>(dataAtPts->leviKirchhoffdOmegaAtPts);
2712 int row_nb_base_functions = row_data.getN().size2();
2713 auto t_row_base_fun = row_data.getFTensor0N();
2714 auto t_row_grad_fun = row_data.getFTensor1DiffN<3>();
2715
2716 // auto time_step = getTStimeStep();
2717 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2718 double a = v * t_w;
2719 double c = (a * alphaOmega) * (ts_a /*/ time_step*/);
2720
2721 int rr = 0;
2722 for (; rr != row_nb_dofs / 3; ++rr) {
2723 auto t_m = get_ftensor2(K, 3 * rr, 0);
2724 const double b = a * t_row_base_fun;
2725 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2726 auto t_col_grad_fun = col_data.getFTensor1DiffN<3>(gg, 0);
2727 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2728 t_m(k, l) -= (b * t_col_base_fun) * t_levi_kirchhoff_domega(k, l);
2729 t_m(k, l) += t_kd(k, l) * (c * (t_row_grad_fun(i) * t_col_grad_fun(i)));
2730 ++t_m;
2731 ++t_col_base_fun;
2732 ++t_col_grad_fun;
2733 }
2734 ++t_row_base_fun;
2735 ++t_row_grad_fun;
2736 }
2737 for (; rr != row_nb_base_functions; ++rr) {
2738 ++t_row_base_fun;
2739 ++t_row_grad_fun;
2740 }
2741 ++t_w;
2742 ++t_levi_kirchhoff_domega;
2743 }
2745}
2746
2748 EntData &col_data) {
2750 if (dataAtPts->matInvD.size1() == size_symm &&
2751 dataAtPts->matInvD.size2() == size_symm) {
2752 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2753 } else {
2754 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2755 }
2757};
2758
2759template <int S>
2761 EntData &col_data) {
2763
2764 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2766
2767 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2768
2769 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2770
2771 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2772
2773 );
2774 };
2775
2776 int nb_integration_pts = getGaussPts().size2();
2777 int row_nb_dofs = row_data.getIndices().size();
2778 int col_nb_dofs = col_data.getIndices().size();
2779
2780 auto v = getVolume();
2781 auto t_w = getFTensor0IntegrationWeight();
2782 int row_nb_base_functions = row_data.getN().size2() / 3;
2783
2788
2789 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2790 &*dataAtPts->matInvD.data().begin());
2791
2792 auto t_row_base = row_data.getFTensor1N<3>();
2793 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2794 double a = v * t_w;
2795
2796 int rr = 0;
2797 for (; rr != row_nb_dofs / 3; ++rr) {
2798 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2799 auto t_m = get_ftensor2(K, 3 * rr, 0);
2800 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2801 t_m(i, k) -= a * t_row_base(j) * (t_inv_D(i, j, k, l) * t_col_base(l));
2802 ++t_m;
2803 ++t_col_base;
2804 }
2805
2806 ++t_row_base;
2807 }
2808
2809 for (; rr != row_nb_base_functions; ++rr)
2810 ++t_row_base;
2811
2812 ++t_w;
2813 ++t_inv_D;
2814 }
2816}
2817
2820 EntData &col_data) {
2822 if (dataAtPts->matInvD.size1() == size_symm &&
2823 dataAtPts->matInvD.size2() == size_symm) {
2824 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2825 } else {
2826 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2827 }
2829};
2830
2831template <int S>
2834 EntData &col_data) {
2836
2837 int nb_integration_pts = getGaussPts().size2();
2838 int row_nb_dofs = row_data.getIndices().size();
2839 int col_nb_dofs = col_data.getIndices().size();
2840
2841 auto v = getVolume();
2842 auto t_w = getFTensor0IntegrationWeight();
2843 int row_nb_base_functions = row_data.getN().size2() / 9;
2844
2849
2850 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2851 &*dataAtPts->matInvD.data().begin());
2852
2853 auto t_row_base = row_data.getFTensor2N<3, 3>();
2854 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2855 double a = v * t_w;
2856
2857 int rr = 0;
2858 for (; rr != row_nb_dofs; ++rr) {
2859 auto t_col_base = col_data.getFTensor2N<3, 3>(gg, 0);
2860 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2861 K(rr, cc) -=
2862 a * (t_row_base(i, j) * (t_inv_D(i, j, k, l) * t_col_base(k, l)));
2863 ++t_col_base;
2864 }
2865
2866 ++t_row_base;
2867 }
2868
2869 for (; rr != row_nb_base_functions; ++rr)
2870 ++t_row_base;
2871 ++t_w;
2872 ++t_inv_D;
2873 }
2875}
2876
2878 EntData &col_data) {
2880 if (dataAtPts->matInvD.size1() == size_symm &&
2881 dataAtPts->matInvD.size2() == size_symm) {
2882 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2883 } else {
2884 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2885 }
2887};
2888
2889template <int S>
2892 EntData &col_data) {
2894
2895 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2897
2898 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2)
2899
2900 );
2901 };
2902
2903 int nb_integration_pts = getGaussPts().size2();
2904 int row_nb_dofs = row_data.getIndices().size();
2905 int col_nb_dofs = col_data.getIndices().size();
2906
2907 auto v = getVolume();
2908 auto t_w = getFTensor0IntegrationWeight();
2909 int row_nb_base_functions = row_data.getN().size2() / 9;
2910
2917
2918 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2919 &*dataAtPts->matInvD.data().begin());
2920
2921 auto t_row_base = row_data.getFTensor2N<3, 3>();
2922 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2923 double a = v * t_w;
2924
2925 auto t_m = get_ftensor1(K, 0, 0);
2926
2927 int rr = 0;
2928 for (; rr != row_nb_dofs; ++rr) {
2929 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2930 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2931 t_m(k) -= a * (t_row_base(i, j) * t_inv_D(i, j, k, l)) * t_col_base(l);
2932 ++t_col_base;
2933 ++t_m;
2934 }
2935
2936 ++t_row_base;
2937 }
2938
2939 for (; rr != row_nb_base_functions; ++rr)
2940 ++t_row_base;
2941 ++t_w;
2942 ++t_inv_D;
2943 }
2945}
2946
2948 EntData &col_data) {
2950
2957
2958 int nb_integration_pts = row_data.getN().size1();
2959 int row_nb_dofs = row_data.getIndices().size();
2960 int col_nb_dofs = col_data.getIndices().size();
2961
2962 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2964
2965 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2966
2967 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2968
2969 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2970
2971 );
2972 };
2973
2974 auto v = getVolume();
2975 auto t_w = getFTensor0IntegrationWeight();
2976 int row_nb_base_functions = row_data.getN().size2() / 3;
2977 auto t_row_base_fun = row_data.getFTensor1N<3>();
2978
2979 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
2980
2981 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2982 double a = v * t_w;
2983
2984 int rr = 0;
2985 for (; rr != row_nb_dofs / 3; ++rr) {
2986
2988 t_PRT(i, k) = t_row_base_fun(j) * t_h_domega(i, j, k);
2989
2990 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2991 auto t_m = get_ftensor2(K, 3 * rr, 0);
2992 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2993 t_m(i, j) -= (a * t_col_base_fun) * t_PRT(i, j);
2994 ++t_m;
2995 ++t_col_base_fun;
2996 }
2997
2998 ++t_row_base_fun;
2999 }
3000
3001 for (; rr != row_nb_base_functions; ++rr)
3002 ++t_row_base_fun;
3003 ++t_w;
3004 ++t_h_domega;
3005 }
3007}
3008
3011 EntData &col_data) {
3013
3020
3021 int nb_integration_pts = row_data.getN().size1();
3022 int row_nb_dofs = row_data.getIndices().size();
3023 int col_nb_dofs = col_data.getIndices().size();
3024
3025 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3027 &m(r, c + 0), &m(r, c + 1), &m(r, c + 2));
3028 };
3029
3030 auto v = getVolume();
3031 auto t_w = getFTensor0IntegrationWeight();
3032 int row_nb_base_functions = row_data.getN().size2() / 9;
3033 auto t_row_base_fun = row_data.getFTensor2N<3, 3>();
3034
3035 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
3036 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3037 double a = v * t_w;
3038
3039 int rr = 0;
3040 for (; rr != row_nb_dofs; ++rr) {
3041
3043 t_PRT(k) = t_row_base_fun(i, j) * t_h_domega(i, j, k);
3044
3045 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
3046 auto t_m = get_ftensor2(K, rr, 0);
3047 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3048 t_m(j) -= (a * t_col_base_fun) * t_PRT(j);
3049 ++t_m;
3050 ++t_col_base_fun;
3051 }
3052
3053 ++t_row_base_fun;
3054 }
3055
3056 for (; rr != row_nb_base_functions; ++rr)
3057 ++t_row_base_fun;
3058
3059 ++t_w;
3060 ++t_h_domega;
3061 }
3063}
3064
3066 EntData &data) {
3068
3069 if (tagSense != getSkeletonSense())
3071
3072 auto get_tag = [&](auto name) {
3073 auto &mob = getPtrFE()->mField.get_moab();
3074 Tag tag;
3075 CHK_MOAB_THROW(mob.tag_get_handle(name, tag), "get tag");
3076 return tag;
3077 };
3078
3079 auto get_tag_value = [&](auto &&tag, int dim) {
3080 auto &mob = getPtrFE()->mField.get_moab();
3081 auto face = getSidePtrFE()->getFEEntityHandle();
3082 std::vector<double> value(dim);
3083 CHK_MOAB_THROW(mob.tag_get_data(tag, &face, 1, value.data()), "set tag");
3084 return value;
3085 };
3086
3087 auto create_tag = [this](const std::string tag_name, const int size) {
3088 double def_VAL[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
3089 Tag th;
3090 CHKERR postProcMesh.tag_get_handle(tag_name.c_str(), size, MB_TYPE_DOUBLE,
3091 th, MB_TAG_CREAT | MB_TAG_SPARSE,
3092 def_VAL);
3093 return th;
3094 };
3095
3096 Tag th_cauchy_streess = create_tag("CauchyStress", 9);
3097 Tag th_detF = create_tag("detF", 1);
3098 Tag th_traction = create_tag("traction", 3);
3099 Tag th_disp_error = create_tag("DisplacementError", 1);
3100
3101 Tag th_energy = create_tag("Energy", 1);
3102
3103 auto t_w = getFTensor1FromMat<3>(dataAtPts->wL2AtPts);
3104 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
3105 auto t_approx_P = getFTensor2FromMat<3, 3>(dataAtPts->approxPAtPts);
3106
3107 auto t_normal = getFTensor1NormalsAtGaussPts();
3108 auto t_disp = getFTensor1FromMat<3>(dataAtPts->wH1AtPts);
3109
3110 // auto sense = getSkeletonSense();
3111
3112 auto next = [&]() {
3113 ++t_w;
3114 ++t_h;
3115 ++t_approx_P;
3116 ++t_normal;
3117 ++t_disp;
3118 };
3119
3120 if (dataAtPts->energyAtPts.size() == 0) {
3121 // that is for case that energy is not calculated
3122 dataAtPts->energyAtPts.resize(getGaussPts().size2());
3123 dataAtPts->energyAtPts.clear();
3124 }
3125 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
3126
3127 FTensor::Index<'i', 3> i;
3128 FTensor::Index<'j', 3> j;
3129 FTensor::Index<'k', 3> k;
3130 FTensor::Index<'l', 3> l;
3131
3132 auto set_float_precision = [](const double x) {
3133 if (std::abs(x) < std::numeric_limits<float>::epsilon())
3134 return 0.;
3135 else
3136 return x;
3137 };
3138
3139 // scalars
3140 auto save_scal_tag = [&](auto &th, auto v, const int gg) {
3142 v = set_float_precision(v);
3143 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1, &v);
3145 };
3146
3147 // vectors
3148 VectorDouble3 v(3);
3149 FTensor::Tensor1<FTensor::PackPtr<double *, 0>, 3> t_v(&v[0], &v[1], &v[2]);
3150 auto save_vec_tag = [&](auto &th, auto &t_d, const int gg) {
3152 t_v(i) = t_d(i);
3153 for (auto &a : v.data())
3154 a = set_float_precision(a);
3155 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
3156 &*v.data().begin());
3158 };
3159
3160 // tensors
3161
3162 MatrixDouble3by3 m(3, 3);
3164 &m(0, 0), &m(0, 1), &m(0, 2),
3165
3166 &m(1, 0), &m(1, 1), &m(1, 2),
3167
3168 &m(2, 0), &m(2, 1), &m(2, 2));
3169
3170 auto save_mat_tag = [&](auto &th, auto &t_d, const int gg) {
3172 t_m(i, j) = t_d(i, j);
3173 for (auto &v : m.data())
3174 v = set_float_precision(v);
3175 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
3176 &*m.data().begin());
3178 };
3179
3180 const auto nb_gauss_pts = getGaussPts().size2();
3181 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
3182
3183 FTensor::Tensor1<double, 3> t_traction;
3184 t_traction(i) = t_approx_P(i, j) * t_normal(j) / t_normal.l2();
3185 // vectors
3186 t_traction(i) *= tagSense;
3187 CHKERR save_vec_tag(th_traction, t_traction, gg);
3188
3189 double u_error = sqrt((t_disp(i) - t_w(i)) * (t_disp(i) - t_w(i)));
3190 CHKERR save_scal_tag(th_disp_error, u_error, gg);
3191 CHKERR save_scal_tag(th_energy, t_energy, gg);
3192
3193 const double jac = determinantTensor3by3(t_h);
3195 t_cauchy(i, j) = (1. / jac) * (t_approx_P(i, k) * t_h(j, k));
3196 CHKERR save_mat_tag(th_cauchy_streess, t_cauchy, gg);
3197 CHKERR postProcMesh.tag_set_data(th_detF, &mapGaussPts[gg], 1, &jac);
3198
3199 next();
3200 }
3201
3203}
3204
3206 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3207 std::vector<FieldSpace> spaces, std::string geom_field_name,
3208 boost::shared_ptr<Range> crack_front_edges_ptr) {
3210
3211 constexpr bool scale_l2 = false;
3212
3213 if (scale_l2) {
3214 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3215 "Scale L2 Ainsworth Legendre base is not implemented");
3216 }
3217
3218 CHKERR MoFEM::AddHOOps<2, 3, 3>::add(pipeline, spaces, geom_field_name);
3219
3221}
3222
3224 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3225 std::vector<FieldSpace> spaces, std::string geom_field_name,
3226 boost::shared_ptr<Range> crack_front_edges_ptr) {
3228
3229 constexpr bool scale_l2 = false;
3230
3231 if (scale_l2) {
3232 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3233 "Scale L2 Ainsworth Legendre base is not implemented");
3234 }
3235
3236 CHKERR MoFEM::AddHOOps<2, 2, 3>::add(pipeline, spaces, geom_field_name);
3237
3239}
3240
3242 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3243 std::vector<FieldSpace> spaces, std::string geom_field_name,
3244 boost::shared_ptr<Range> crack_front_edges_ptr,
3245 boost::shared_ptr<MatrixDouble> jac, boost::shared_ptr<VectorDouble> det,
3246 boost::shared_ptr<MatrixDouble> inv_jac) {
3248
3250 auto jac = boost::make_shared<MatrixDouble>();
3251 auto det = boost::make_shared<VectorDouble>();
3253 geom_field_name, jac));
3254 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3255 pipeline.push_back(
3257 }
3258
3259 constexpr bool scale_l2_ainsworth_legendre_base = false;
3260
3261 if (scale_l2_ainsworth_legendre_base) {
3262
3264 : public MoFEM::OpCalculateVectorFieldGradient<SPACE_DIM, SPACE_DIM> {
3265
3267
3268 OpCalculateVectorFieldGradient(const std::string &field_name,
3269 boost::shared_ptr<MatrixDouble> jac,
3270 boost::shared_ptr<Range> edges_ptr)
3271 : OP(field_name, jac), edgesPtr(edges_ptr) {}
3272
3273 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
3274
3275 auto ent = data.getFieldEntities().size()
3276 ? data.getFieldEntities()[0]->getEnt()
3277 : 0;
3278
3279 if (type == MBEDGE && edgesPtr->find(ent) != edgesPtr->end()) {
3280 return 0;
3281 } else {
3282 return OP::doWork(side, type, data);
3283 }
3284 };
3285
3286 private:
3287 boost::shared_ptr<Range> edgesPtr;
3288 };
3289
3290 auto jac = boost::make_shared<MatrixDouble>();
3291 auto det = boost::make_shared<VectorDouble>();
3292 pipeline.push_back(new OpCalculateVectorFieldGradient(
3293 geom_field_name, jac,
3294 EshelbianCore::setSingularity ? crack_front_edges_ptr
3295 : boost::make_shared<Range>()));
3296 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3297 pipeline.push_back(new OpScaleBaseBySpaceInverseOfMeasure(
3299 }
3300
3301 CHKERR MoFEM::AddHOOps<3, 3, 3>::add(pipeline, spaces, geom_field_name,
3302 jac, det, inv_jac);
3303
3305}
3306
3307/**
3308 * @brief Caluclate face material force and normal pressure at gauss points
3309 *
3310 * @param side
3311 * @param type
3312 * @param data
3313 * @return MoFEMErrorCode
3314 *
3315 * Reconstruct the full gradient \f$U=\nabla u\f$ on a surface from the symmetric part and the surface gradient.
3316 *
3317 * @details
3318 * Inputs:
3319 * - \c t_strain : \f$\varepsilon=\tfrac12(U+U^\top)\f$ (symmetric strain on S),
3320 * - \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$,
3321 * - \c t_normal : (possibly non‑unit) surface normal.
3322 *
3323 * Procedure (pointwise on S):
3324 * 1) Normalize the normal \f$\mathbf n=\mathbf N/\|\mathbf N\|\f$.
3325 * 2) Form the residual \f$R=\varepsilon-\operatorname{sym}(u^\Gamma)\f$, where
3326 * \f$\operatorname{sym}(A)=\tfrac12(A+A^\top)\f$.
3327 * 3) Recover the normal directional derivative (a vector)
3328 * \f$\mathbf v=\partial_{\mathbf n}u=2R\mathbf n-(\mathbf n^\top R\,\mathbf n)\,\mathbf n\f$.
3329 * 4) Assemble the full gradient
3330 * \f$U = u^\Gamma + \mathbf v\otimes \mathbf n\f$.
3331 *
3332 * Properties (sanity checks):
3333 * - \f$\tfrac12(U+U^\top)=\varepsilon\f$ (matches the given symmetric part),
3334 * - \f$U P = u^\Gamma\f$ (tangential/right-projected columns unchanged),
3335 * - Only the **normal column** is updated via \f$\mathbf v\otimes\mathbf n\f$.
3336 *
3337 * Mapping to variables in this snippet:
3338 * - \f$\varepsilon \leftrightarrow\f$ \c t_strain,
3339 * - \f$u^\Gamma \leftrightarrow\f$ \c t_grad_u_gamma,
3340 * - \f$\mathbf N \leftrightarrow\f$ \c t_normal (normalized into \c t_N),
3341 * - \f$R \leftrightarrow\f$ \c t_R,
3342 * - \f$U \leftrightarrow\f$ \c t_grad_u.
3343 *
3344 * @pre \c t_normal is nonzero; \c t_strain is symmetric.
3345 * @note All indices use Einstein summation; computation is local to the surface point.
3346 *
3347*/
3349 EntData &data) {
3351
3364
3365 dataAtPts->faceMaterialForceAtPts.resize(3, getGaussPts().size2(), false);
3366 dataAtPts->normalPressureAtPts.resize(getGaussPts().size2(), false);
3367 if (getNinTheLoop() == 0) {
3368 dataAtPts->faceMaterialForceAtPts.clear();
3369 dataAtPts->normalPressureAtPts.clear();
3370 }
3371 auto loop_size = getLoopSize();
3372 if (loop_size == 1) {
3373 auto numebered_fe_ptr = getSidePtrFE()->numeredEntFiniteElementPtr;
3374 auto pstatus = numebered_fe_ptr->getPStatus();
3375 if (pstatus & (PSTATUS_SHARED | PSTATUS_MULTISHARED)) {
3376 loop_size = 2;
3377 }
3378 }
3379
3381
3382 auto t_normal = getFTensor1NormalsAtGaussPts();
3383 auto t_T = getFTensor1FromMat<SPACE_DIM>(
3384 dataAtPts->faceMaterialForceAtPts); //< face material force
3385 auto t_p =
3386 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
3387 auto t_P = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->approxPAtPts);
3388 // auto t_grad_P = getFTensor3FromMat<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
3389 // dataAtPts->gradPAtPts);
3390 auto t_u_gamma =
3391 getFTensor1FromMat<SPACE_DIM>(dataAtPts->hybridDispAtPts);
3392 auto t_grad_u_gamma =
3393 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->gradHybridDispAtPts);
3394 auto t_strain =
3395 getFTensor2SymmetricFromMat<SPACE_DIM>(dataAtPts->logStretchTensorAtPts);
3396 auto t_omega = getFTensor1FromMat<3>(dataAtPts->rotAxisAtPts);
3397
3403
3404 auto next = [&]() {
3405 ++t_normal;
3406 ++t_P;
3407 // ++t_grad_P;
3408 ++t_omega;
3409 ++t_u_gamma;
3410 ++t_grad_u_gamma;
3411 ++t_strain;
3412 ++t_T;
3413 ++t_p;
3414 };
3415
3417 case GRIFFITH_FORCE:
3418 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3419 t_N(I) = t_normal(I);
3420 t_N.normalize();
3421
3422 t_A(i, j) = levi_civita(i, j, k) * t_omega(k);
3423 t_R(i, k) = t_kd(i, k) + t_A(i, k);
3424 t_grad_u(i, j) = t_R(i, j) + t_strain(i, j);
3425
3426 t_T(I) +=
3427 t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
3428 // note that works only for Hooke material, for nonlinear material we need
3429 // strain energy expressed by stress
3430 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2.) / loop_size;
3431
3432 t_p += t_N(I) * (t_N(J) * (t_grad_u_gamma(i, I) * t_P(i, J))) / loop_size;
3433
3434 next();
3435 }
3436 break;
3437 case GRIFFITH_SKELETON:
3438 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3439
3440 // Normalize the normal
3441 t_N(I) = t_normal(I);
3442 t_N.normalize();
3443
3444 // R = ε − sym(u^Γ)
3445 t_R(i, j) =
3446 t_strain(i, j) - 0.5 * (t_grad_u_gamma(i, j) + t_grad_u_gamma(j, i));
3447
3448 // U = u^Γ + [2 R N − (Nᵀ R N) N] ⊗ N
3449 t_grad_u(i, J) = t_grad_u_gamma(i, J) + (2 * t_R(i, K) * t_N(K) -
3450 (t_R(k, L) * t_N(k) * t_N(L)) * t_N(i)) *
3451 t_N(J);
3452
3453 t_T(I) += t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
3454 // note that works only for Hooke material, for nonlinear material we need
3455 // strain energy expressed by stress
3456 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2.) / loop_size;
3457
3458 // calculate nominal face pressure
3459 t_p += t_N(I) * (t_N(J) * (t_grad_u_gamma(i, I) * t_P(i, J))) / loop_size;
3460
3461 next();
3462 }
3463 break;
3464
3465 default:
3466 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3467 "Grffith energy release "
3468 "selector not implemented");
3469 };
3470
3471#ifndef NDEBUG
3472 auto side_fe_ptr = getSidePtrFE();
3473 auto side_fe_mi_ptr = side_fe_ptr->numeredEntFiniteElementPtr;
3474 auto pstatus = side_fe_mi_ptr->getPStatus();
3475 if (pstatus) {
3476 auto owner = side_fe_mi_ptr->getOwnerProc();
3477 MOFEM_LOG("SELF", Sev::noisy)
3478 << "OpFaceSideMaterialForce: owner proc is not 0, owner proc: " << owner
3479 << " " << getPtrFE()->mField.get_comm_rank() << " n in the loop "
3480 << getNinTheLoop() << " loop size " << getLoopSize();
3481 }
3482#endif // NDEBUG
3483
3485}
3486
3488 EntData &data) {
3490
3491#ifndef NDEBUG
3492 auto fe_mi_ptr = getFEMethod()->numeredEntFiniteElementPtr;
3493 auto pstatus = fe_mi_ptr->getPStatus();
3494 if (pstatus) {
3495 auto owner = fe_mi_ptr->getOwnerProc();
3496 MOFEM_LOG("SELF", Sev::noisy)
3497 << "OpFaceMaterialForce: owner proc is not 0, owner proc: " << owner
3498 << " " << getPtrFE()->mField.get_comm_rank();
3499 }
3500#endif // NDEBUG
3501
3503
3505 t_face_T(I) = 0.;
3506 double face_pressure = 0.;
3507 auto t_T = getFTensor1FromMat<SPACE_DIM>(
3508 dataAtPts->faceMaterialForceAtPts); //< face material force
3509 auto t_p =
3510 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
3511 auto t_w = getFTensor0IntegrationWeight();
3512 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3513 t_face_T(I) += t_w * t_T(I);
3514 face_pressure += t_w * t_p;
3515 ++t_w;
3516 ++t_T;
3517 ++t_p;
3518 }
3519 t_face_T(I) *= getMeasure();
3520 face_pressure *= getMeasure();
3521
3522 auto get_tag = [&](auto name, auto dim) {
3523 auto &moab = getPtrFE()->mField.get_moab();
3524 Tag tag;
3525 double def_val[] = {0., 0., 0.};
3526 CHK_MOAB_THROW(moab.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
3527 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
3528 "create tag");
3529 return tag;
3530 };
3531
3532 auto set_tag = [&](auto &&tag, auto ptr) {
3533 auto &moab = getPtrFE()->mField.get_moab();
3534 auto face = getPtrFE()->getFEEntityHandle();
3535 CHK_MOAB_THROW(moab.tag_set_data(tag, &face, 1, ptr), "set tag");
3536 };
3537
3538 set_tag(get_tag("MaterialForce", 3), &t_face_T(0));
3539 set_tag(get_tag("FacePressure", 1), &face_pressure);
3540
3542}
3543
3544
3545template <typename OP_PTR>
3546std::tuple<std::string, MatrixDouble> getAnalyticalExpr(OP_PTR op_ptr, MatrixDouble &analytical_expr,
3547 const std::string block_name) {
3548
3549 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
3550
3551 auto ts_time = op_ptr->getTStime();
3552 auto ts_time_step = op_ptr->getTStimeStep();
3555 ts_time_step = EshelbianCore::dynamicStep;
3556 }
3557
3558 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
3559 MatrixDouble m_ref_normals = op_ptr->getNormalsAtGaussPts();
3560
3561 auto v_analytical_expr =
3562 analytical_expr_function(ts_time_step, ts_time, nb_gauss_pts,
3563 m_ref_coords, m_ref_normals, block_name);
3564
3565#ifndef NDEBUG
3566 if (v_analytical_expr.size2() != nb_gauss_pts)
3568 "Wrong number of integration pts");
3569#endif // NDEBUG
3570
3571 return std::make_tuple(block_name, v_analytical_expr);
3572}
3573
3574//! [Analytical displacement function from python]
3575#ifdef ENABLE_PYTHON_BINDING
3576
3577 MoFEMErrorCode AnalyticalExprPython::analyticalExprInit(const std::string py_file) {
3579 try {
3580
3581 // create main module
3582 auto main_module = bp::import("__main__");
3583 mainNamespace = main_module.attr("__dict__");
3584 bp::exec_file(py_file.c_str(), mainNamespace, mainNamespace);
3585 // create a reference to python function
3586 analyticalDispFun = mainNamespace["analytical_disp"];
3587 analyticalTractionFun = mainNamespace["analytical_traction"];
3588 analyticalExternalStrainFun = mainNamespace["analytical_external_strain"];
3589
3590 } catch (bp::error_already_set const &) {
3591 // print all other errors to stderr
3592 PyErr_Print();
3594 }
3596 }
3597
3598 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalDisp(
3599
3600 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3601 np::ndarray nx, np::ndarray ny, np::ndarray nz,
3602 const std::string &block_name, np::ndarray &analytical_expr
3603
3604 ) {
3606 try {
3607
3608 // call python function
3609 analytical_expr = bp::extract<np::ndarray>(
3610 analyticalDispFun(delta_t, t, x, y, z, nx, ny, nz, block_name));
3611
3612 } catch (bp::error_already_set const &) {
3613 // print all other errors to stderr
3614 PyErr_Print();
3616 }
3618 }
3619
3620 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalTraction(
3621
3622 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3623 np::ndarray nx, np::ndarray ny, np::ndarray nz,
3624 const std::string& block_name, np::ndarray &analytical_expr
3625
3626 ) {
3628 try {
3629
3630 // call python function
3631 analytical_expr = bp::extract<np::ndarray>(
3632 analyticalTractionFun(delta_t, t, x, y, z, nx, ny, nz, block_name));
3633
3634 } catch (bp::error_already_set const &) {
3635 // print all other errors to stderr
3636 PyErr_Print();
3638 }
3640 }
3641
3642 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalExternalStrain(
3643
3644 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3645 const std::string& block_name, np::ndarray &analytical_expr
3646
3647 ) {
3649 try {
3650
3651 // call python function
3652 analytical_expr = bp::extract<np::ndarray>(
3653 analyticalExternalStrainFun(delta_t, t, x, y, z, block_name));
3654
3655 } catch (bp::error_already_set const &) {
3656 // print all other errors to stderr
3657 PyErr_Print();
3659 }
3661 }
3662
3663boost::weak_ptr<AnalyticalExprPython> AnalyticalExprPythonWeakPtr;
3664
3665inline np::ndarray convert_to_numpy(VectorDouble &data, int nb_gauss_pts,
3666 int id) {
3667 auto dtype = np::dtype::get_builtin<double>();
3668 auto size = bp::make_tuple(nb_gauss_pts);
3669 auto stride = bp::make_tuple(3 * sizeof(double));
3670 return (np::from_data(&data[id], dtype, size, stride, bp::object()));
3671};
3672#endif
3673//! Analytical displacement function from python]
3674
3676 int nb_gauss_pts,
3677 MatrixDouble &m_ref_coords,
3678 MatrixDouble &m_ref_normals,
3679 const std::string block_name) {
3680
3681#ifdef ENABLE_PYTHON_BINDING
3682 if (auto analytical_expr_ptr = AnalyticalExprPythonWeakPtr.lock()) {
3683
3684 VectorDouble v_ref_coords = m_ref_coords.data();
3685 VectorDouble v_ref_normals = m_ref_normals.data();
3686
3687 bp::list python_coords;
3688 bp::list python_normals;
3689
3690 for (int idx = 0; idx < 3; ++idx) {
3691 python_coords.append(convert_to_numpy(v_ref_coords, nb_gauss_pts, idx));
3692 python_normals.append(convert_to_numpy(v_ref_normals, nb_gauss_pts, idx));
3693 }
3694
3695 auto disp_block_name = "(.*)ANALYTICAL_DISPLACEMENT(.*)";
3696 auto traction_block_name = "(.*)ANALYTICAL_TRACTION(.*)";
3697
3698 std::regex reg_disp_name(disp_block_name);
3699 std::regex reg_traction_name(traction_block_name);
3700
3701 np::ndarray np_analytical_expr = np::empty(
3702 bp::make_tuple(nb_gauss_pts, 3), np::dtype::get_builtin<double>());
3703
3704 if (std::regex_match(block_name, reg_disp_name)) {
3705 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalDisp(
3706 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3707 bp::extract<np::ndarray>(python_coords[1]),
3708 bp::extract<np::ndarray>(python_coords[2]),
3709 bp::extract<np::ndarray>(python_normals[0]),
3710 bp::extract<np::ndarray>(python_normals[1]),
3711 bp::extract<np::ndarray>(python_normals[2]),
3712 block_name, np_analytical_expr),
3713 "Failed analytical_disp() python call");
3714 } else if (std::regex_match(block_name, reg_traction_name)) {
3715 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalTraction(
3716 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3717 bp::extract<np::ndarray>(python_coords[1]),
3718 bp::extract<np::ndarray>(python_coords[2]),
3719 bp::extract<np::ndarray>(python_normals[0]),
3720 bp::extract<np::ndarray>(python_normals[1]),
3721 bp::extract<np::ndarray>(python_normals[2]),
3722 block_name, np_analytical_expr),
3723 "Failed analytical_traction() python call");
3724 } else {
3726 "Unknown analytical block");
3727 }
3728
3729 double *analytical_expr_val_ptr =
3730 reinterpret_cast<double *>(np_analytical_expr.get_data());
3731
3732 MatrixDouble v_analytical_expr;
3733 v_analytical_expr.resize(3, nb_gauss_pts, false);
3734 for (size_t gg = 0; gg < nb_gauss_pts; ++gg) {
3735 for (int idx = 0; idx < 3; ++idx)
3736 v_analytical_expr(idx, gg) =
3737 *(analytical_expr_val_ptr + (3 * gg + idx));
3738 }
3739 return v_analytical_expr;
3740 } else {
3741 // Returns empty vector
3742 }
3743#endif
3744 return MatrixDouble();
3745}
3746
3748 int nb_gauss_pts,
3749 MatrixDouble &m_ref_coords,
3750 const std::string block_name) {
3751
3752#ifdef ENABLE_PYTHON_BINDING
3753 if (auto analytical_expr_ptr = AnalyticalExprPythonWeakPtr.lock()) {
3754
3755 VectorDouble v_ref_coords = m_ref_coords.data();
3756
3757 bp::list python_coords;
3758
3759 for (int idx = 0; idx < 3; ++idx) {
3760 python_coords.append(convert_to_numpy(v_ref_coords, nb_gauss_pts, idx));
3761 }
3762
3763 auto externalstrain_block_name = "(.*)ANALYTICAL_EXTERNALSTRAIN(.*)";
3764
3765 std::regex reg_externalstrain_name(externalstrain_block_name);
3766
3767 np::ndarray np_analytical_expr = np::empty(
3768 bp::make_tuple(nb_gauss_pts), np::dtype::get_builtin<double>());
3769
3770 if (std::regex_match(block_name, reg_externalstrain_name)) {
3771 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalExternalStrain(
3772 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3773 bp::extract<np::ndarray>(python_coords[1]),
3774 bp::extract<np::ndarray>(python_coords[2]), block_name,
3775 np_analytical_expr),
3776 "Failed analytical_external_strain() python call");
3777 } else {
3779 "Unknown analytical block");
3780 }
3781
3782 double *analytical_expr_val_ptr =
3783 reinterpret_cast<double *>(np_analytical_expr.get_data());
3784
3785 VectorDouble v_analytical_expr;
3786 v_analytical_expr.resize(nb_gauss_pts, false);
3787 for (size_t gg = 0; gg < nb_gauss_pts; ++gg)
3788 v_analytical_expr[gg] = *(analytical_expr_val_ptr + gg);
3789
3790 return v_analytical_expr;
3791 } else {
3792 // Returns empty vector
3793 }
3794#endif
3795 return VectorDouble();
3796}
3797
3799 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3800 boost::shared_ptr<MatrixDouble> vec, ScalarFun beta_coeff,
3801 boost::shared_ptr<Range> ents_ptr)
3802 : OP(broken_base_side_data, ents_ptr) {
3803 this->sourceVec = vec;
3804 this->betaCoeff = beta_coeff;
3805}
3806
3808 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3809 ScalarFun beta_coeff, boost::shared_ptr<Range> ents_ptr)
3810 : OP(broken_base_side_data, ents_ptr) {
3811 this->sourceVec = boost::shared_ptr<MatrixDouble>();
3812 this->betaCoeff = beta_coeff;
3813}
3814
3816OpBrokenBaseTimesBrokenDisp::doWork(int row_side, EntityType row_type,
3817 EntitiesFieldData::EntData &row_data) {
3819
3820 if (OP::entsPtr) {
3821 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
3823 }
3824
3825#ifndef NDEBUG
3826 if (!brokenBaseSideData) {
3827 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
3828 }
3829#endif // NDEBUG
3830
3831 auto do_work_rhs = [this](int row_side, EntityType row_type,
3832 EntitiesFieldData::EntData &row_data) {
3834 // get number of dofs on row
3835 OP::nbRows = row_data.getIndices().size();
3836 if (!OP::nbRows)
3838 // get number of integration points
3839 OP::nbIntegrationPts = OP::getGaussPts().size2();
3840 // get row base functions
3841 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
3842 // resize and clear the right hand side vector
3843 OP::locF.resize(OP::nbRows, false);
3844 OP::locF.clear();
3845 // integrate local vector
3846 CHKERR this->iNtegrate(row_data);
3847 // assemble local vector
3848 CHKERR this->aSsemble(row_data);
3850 };
3851
3852 switch (OP::opType) {
3853 case OP::OPSPACE:
3854 for (auto &bd : *brokenBaseSideData) {
3855 this->sourceVec =
3856 boost::shared_ptr<MatrixDouble>(brokenBaseSideData, &bd.getFlux());
3857 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData());
3858 this->sourceVec.reset();
3859 }
3860 break;
3861 default:
3863 (std::string("wrong op type ") +
3864 OpBaseDerivativesBase::OpTypeNames[OP::opType])
3865 .c_str());
3866 }
3867
3869}
3870
3872 const std::string row_field,
3873 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3874 ScalarFun beta_coeff, boost::shared_ptr<Range> ents_ptr)
3875 : OP(row_field, boost::shared_ptr<MatrixDouble>(), beta_coeff, ents_ptr),
3876 brokenBaseSideDataPtr(broken_base_side_data) {
3877 this->betaCoeff = beta_coeff;
3878}
3879
3883 for (auto &bd : (*brokenBaseSideDataPtr)) {
3884 this->sourceVec =
3885 boost::shared_ptr<MatrixDouble>(brokenBaseSideDataPtr, &bd.getFlux());
3886
3887#ifndef NDEBUG
3888 if (this->sourceVec->size1() != SPACE_DIM) {
3889 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3890 "Inconsistent size of the source vector");
3891 }
3892 if (this->sourceVec->size2() != OP::getGaussPts().size2()) {
3893 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3894 "Inconsistent size of the source vector");
3895 }
3896#endif // NDEBUG
3897
3898 CHKERR OP::iNtegrate(data);
3899
3900 this->sourceVec.reset();
3901 }
3903}
3904
3906 std::string row_field,
3907 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3908 ScalarFun beta, const bool assmb_transpose, const bool only_transpose,
3909 boost::shared_ptr<Range> ents_ptr)
3910 : OP(row_field, broken_base_side_data, assmb_transpose, only_transpose,
3911 ents_ptr) {
3912 this->betaCoeff = beta;
3913 this->sYmm = false;
3914 }
3915
3917 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
3918 ScalarFun beta, boost::shared_ptr<Range> ents_ptr)
3919 : OP(broken_base_side_data, ents_ptr) {
3920 this->sYmm = false;
3921 this->betaCoeff = beta;
3922}
3923
3925OpBrokenBaseBrokenBase::doWork(int row_side, EntityType row_type,
3926 EntitiesFieldData::EntData &row_data) {
3928
3929 if (OP::entsPtr) {
3930 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
3932 }
3933
3934#ifndef NDEBUG
3935 if (!brokenBaseSideData) {
3936 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
3937 }
3938#endif // NDEBUG
3939
3940 auto do_work_lhs = [this](int row_side, int col_side, EntityType row_type,
3941 EntityType col_type,
3943 EntitiesFieldData::EntData &col_data) {
3945
3946 auto check_if_assemble_transpose = [&] {
3947 if (this->sYmm) {
3948 if (OP::rowSide != OP::colSide || OP::rowType != OP::colType)
3949 return true;
3950 else
3951 return false;
3952 } else if (OP::assembleTranspose) {
3953 return true;
3954 }
3955 return false;
3956 };
3957
3958 OP::rowSide = row_side;
3959 OP::rowType = row_type;
3960 OP::colSide = col_side;
3961 OP::colType = col_type;
3962 OP::nbCols = col_data.getIndices().size();
3963 OP::locMat.resize(OP::nbRows, OP::nbCols, false);
3964 OP::locMat.clear();
3965 CHKERR this->iNtegrate(row_data, col_data);
3966 CHKERR this->aSsemble(row_data, col_data, check_if_assemble_transpose());
3968 };
3969
3970 switch (OP::opType) {
3971 case OP::OPSPACE:
3972
3973 for (auto &bd : *brokenBaseSideData) {
3974
3975#ifndef NDEBUG
3976 if (!bd.getData().getNSharedPtr(bd.getData().getBase())) {
3977 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3978 "base functions not set");
3979 }
3980#endif
3981
3982 OP::nbRows = bd.getData().getIndices().size();
3983 if (!OP::nbRows)
3985 OP::nbIntegrationPts = OP::getGaussPts().size2();
3986 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(bd.getData());
3987
3988 if (!OP::nbRows)
3990
3991 CHKERR do_work_lhs(
3992
3993 // side
3994 bd.getSide(), bd.getSide(),
3995
3996 // type
3997 bd.getType(), bd.getType(),
3998
3999 // row_data
4000 bd.getData(), bd.getData()
4001
4002 );
4003 }
4004
4005 break;
4006
4007 default:
4009 (std::string("wrong op type ") +
4010 OpBaseDerivativesBase::OpTypeNames[OP::opType])
4011 .c_str());
4012 }
4013
4015}
4016
4017} // namespace EshelbianPlasticity
Auxilary functions for Eshelbian plasticity.
Eshelbian plasticity interface.
Lie algebra implementation.
#define FTENSOR_INDEX(DIM, I)
constexpr double a
constexpr int SPACE_DIM
Kronecker Delta class symmetric.
Kronecker Delta class.
Tensor1< T, Tensor_Dim > normalize()
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ USER_BASE
user implemented approximation base
Definition definitions.h:68
@ NOBASE
Definition definitions.h:59
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ L2
field with C-1 continuity
Definition definitions.h:88
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_IMPOSSIBLE_CASE
Definition definitions.h:35
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
constexpr auto t_kd
boost::function< double(const double, const double, const double)> ScalarFun
Scalar function type.
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
MoFEM::TsCtx * ts_ctx
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
auto getMat(A &&t_val, B &&t_vec, Fun< double > f)
Get the Mat object.
auto getDiffMat(A &&t_val, B &&t_vec, Fun< double > f, Fun< double > d_f, const int nb)
Get the Diff Mat object.
VectorDouble analytical_externalstrain_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, const std::string block_name)
auto sort_eigen_vals(A &eig, B &eigen_vec)
static Tag get_tag(moab::Interface &moab, std::string tag_name, int size)
std::tuple< std::string, MatrixDouble > getAnalyticalExpr(OP_PTR op_ptr, MatrixDouble &analytical_expr, const std::string block_name)
static constexpr auto size_symm
MatrixDouble analytical_expr_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, MatrixDouble &m_ref_normals, const std::string block_name)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
VectorBoundedArray< double, 3 > VectorDouble3
Definition Types.hpp:92
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
UBlasVector< double > VectorDouble
Definition Types.hpp:68
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
MoFEMErrorCode computeEigenValuesSymmetric(const MatrixDouble &mat, VectorDouble &eig, MatrixDouble &eigen_vec)
compute eigenvalues of a symmetric matrix using lapack dsyev
static auto determinantTensor3by3(T &t)
Calculate the determinant of a 3x3 matrix or a tensor of rank 2.
constexpr IntegrationType I
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
FTensor::Index< 'm', 3 > m
const int N
Definition speed_test.cpp:3
static enum StretchSelector stretchSelector
static double dynamicTime
static PetscBool l2UserBaseScale
static int dynamicStep
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static PetscBool dynamicRelaxation
static enum SymmetrySelector symmetrySelector
static boost::function< double(const double)> f
static PetscBool setSingularity
static boost::function< double(const double)> d_f
static enum EnergyReleaseSelector energyReleaseSelector
static boost::function< double(const double)> inv_f
static auto diffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp: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)
Operator for linear form, usually to calculate values on right hand side.
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