v0.15.0
Loading...
Searching...
No Matches
EshelbianOperators.cpp
Go to the documentation of this file.
1/**
2 * \file EshelbianOperators.cpp
3 * \example 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
32inline MatrixDouble analytical_expr_function(double delta_t, double t,
33 int nb_gauss_pts,
34 MatrixDouble &m_ref_coords,
35 const std::string block_name);
36
37template <typename OP_PTR>
38auto getAnalyticalExpr(OP_PTR op_ptr, MatrixDouble &analytical_expr,
39 const std::string block_name) {
40
41 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
42
43 auto ts_time = op_ptr->getTStime();
44 auto ts_time_step = op_ptr->getTStimeStep();
47 ts_time_step = EshelbianCore::dynamicStep;
48 }
49
50 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
51
52 auto v_analytical_expr = analytical_expr_function(
53 ts_time_step, ts_time, nb_gauss_pts, m_ref_coords, block_name);
54
55#ifndef NDEBUG
56 if (v_analytical_expr.size2() != nb_gauss_pts)
58 "Wrong number of integration pts");
59#endif // NDEBUG
60
61 return std::make_tuple(block_name, v_analytical_expr);
62};
63
64MoFEMErrorCode OpCalculateEshelbyStress::doWork(int side, EntityType type,
65 EntData &data) {
70
71 int nb_integration_pts = getGaussPts().size2();
72
73 auto t_P = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->approxPAtPts);
74 auto t_F = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->hAtPts);
75 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
76
77 dataAtPts->SigmaAtPts.resize(SPACE_DIM * SPACE_DIM, nb_integration_pts,
78 false);
79 auto t_eshelby_stress =
80 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->SigmaAtPts);
81
83
84 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
85 t_eshelby_stress(i, j) = t_energy * t_kd(i, j) - t_F(m, i) * t_P(m, j);
86 ++t_energy;
87 ++t_P;
88 ++t_F;
89 ++t_eshelby_stress;
90 }
91
93}
94
96 EntityType type,
97 EntData &data) {
99
100 auto ts_ctx = getTSCtx();
101 int nb_integration_pts = getGaussPts().size2();
102
103 // space size indices
111
112 // sym size indices
114
115 auto t_L = symm_L_tensor();
116
117 dataAtPts->hAtPts.resize(9, nb_integration_pts, false);
118 dataAtPts->hdOmegaAtPts.resize(9 * 3, nb_integration_pts, false);
119 dataAtPts->hdLogStretchAtPts.resize(9 * 6, nb_integration_pts, false);
120
121 dataAtPts->leviKirchhoffAtPts.resize(3, nb_integration_pts, false);
122 dataAtPts->leviKirchhoffdOmegaAtPts.resize(9, nb_integration_pts, false);
123 dataAtPts->leviKirchhoffdLogStreatchAtPts.resize(3 * size_symm,
124 nb_integration_pts, false);
125 dataAtPts->leviKirchhoffPAtPts.resize(9 * 3, nb_integration_pts, false);
126
127 dataAtPts->adjointPdstretchAtPts.resize(9, nb_integration_pts, false);
128 dataAtPts->adjointPdUAtPts.resize(size_symm, nb_integration_pts, false);
129 dataAtPts->adjointPdUdPAtPts.resize(9 * size_symm, nb_integration_pts, false);
130 dataAtPts->adjointPdUdOmegaAtPts.resize(3 * size_symm, nb_integration_pts,
131 false);
132 dataAtPts->rotMatAtPts.resize(9, nb_integration_pts, false);
133 dataAtPts->stretchTensorAtPts.resize(6, nb_integration_pts, false);
134 dataAtPts->diffStretchTensorAtPts.resize(36, nb_integration_pts, false);
135 dataAtPts->eigenVals.resize(3, nb_integration_pts, false);
136 dataAtPts->eigenVecs.resize(9, nb_integration_pts, false);
137 dataAtPts->nbUniq.resize(nb_integration_pts, false);
138
139 dataAtPts->logStretch2H1AtPts.resize(6, nb_integration_pts, false);
140 dataAtPts->logStretchTotalTensorAtPts.resize(6, nb_integration_pts, false);
141
142 dataAtPts->internalStressAtPts.resize(9, nb_integration_pts, false);
143 dataAtPts->internalStressAtPts.clear();
144
145 // Calculated values
146 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
147 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
148 auto t_h_dlog_u =
149 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->hdLogStretchAtPts);
150 auto t_levi_kirchhoff = getFTensor1FromMat<3>(dataAtPts->leviKirchhoffAtPts);
151 auto t_levi_kirchhoff_domega =
152 getFTensor2FromMat<3, 3>(dataAtPts->leviKirchhoffdOmegaAtPts);
153 auto t_levi_kirchhoff_dstreach = getFTensor2FromMat<3, size_symm>(
154 dataAtPts->leviKirchhoffdLogStreatchAtPts);
155 auto t_levi_kirchhoff_dP =
156 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
157 auto t_approx_P_adjoint_dstretch =
158 getFTensor2FromMat<3, 3>(dataAtPts->adjointPdstretchAtPts);
159 auto t_approx_P_adjoint_log_du =
160 getFTensor1FromMat<size_symm>(dataAtPts->adjointPdUAtPts);
161 auto t_approx_P_adjoint_log_du_dP =
162 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
163 auto t_approx_P_adjoint_log_du_domega =
164 getFTensor2FromMat<3, size_symm>(dataAtPts->adjointPdUdOmegaAtPts);
165 auto t_R = getFTensor2FromMat<3, 3>(dataAtPts->rotMatAtPts);
166 auto t_u = getFTensor2SymmetricFromMat<3>(dataAtPts->stretchTensorAtPts);
167 auto t_diff_u =
168 getFTensor4DdgFromMat<3, 3, 1>(dataAtPts->diffStretchTensorAtPts);
169 auto t_eigen_vals = getFTensor1FromMat<3>(dataAtPts->eigenVals);
170 auto t_eigen_vecs = getFTensor2FromMat<3, 3>(dataAtPts->eigenVecs);
171 auto t_log_stretch_total =
172 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchTotalTensorAtPts);
173 auto t_log_u2_h1 =
174 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretch2H1AtPts);
175 auto &nbUniq = dataAtPts->nbUniq;
176 auto t_nb_uniq =
177 FTensor::Tensor0<FTensor::PackPtr<int *, 1>>(nbUniq.data().data());
178
179 // Field values
180 auto t_grad_h1 = getFTensor2FromMat<3, 3>(dataAtPts->wGradH1AtPts);
181 auto t_omega = getFTensor1FromMat<3>(dataAtPts->rotAxisAtPts);
182 auto t_approx_P = getFTensor2FromMat<3, 3>(dataAtPts->approxPAtPts);
183 auto t_log_u =
184 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchTensorAtPts);
185
186 auto next = [&]() {
187 // calculated values
188 ++t_h;
189 ++t_h_domega;
190 ++t_h_dlog_u;
191 ++t_levi_kirchhoff;
192 ++t_levi_kirchhoff_domega;
193 ++t_levi_kirchhoff_dstreach;
194 ++t_levi_kirchhoff_dP;
195 ++t_approx_P_adjoint_dstretch;
196 ++t_approx_P_adjoint_log_du;
197 ++t_approx_P_adjoint_log_du_dP;
198 ++t_approx_P_adjoint_log_du_domega;
199 ++t_R;
200 ++t_u;
201 ++t_diff_u;
202 ++t_eigen_vals;
203 ++t_eigen_vecs;
204 ++t_nb_uniq;
205 ++t_log_u2_h1;
206 ++t_log_stretch_total;
207 // field values
208 ++t_omega;
209 ++t_grad_h1;
210 ++t_approx_P;
211 ++t_log_u;
212 };
213
216
217 auto bound_eig = [&](auto &eig) {
219 const auto zero = std::exp(std::numeric_limits<double>::min_exponent);
220 const auto large = std::exp(std::numeric_limits<double>::max_exponent);
221 for (int ii = 0; ii != 3; ++ii) {
222 eig(ii) = std::min(std::max(zero, eig(ii)), large);
223 }
225 };
226
227 auto calculate_log_stretch = [&]() {
230 eigen_vec(i, j) = t_log_u(i, j);
231 if (computeEigenValuesSymmetric(eigen_vec, eig) != MB_SUCCESS) {
232 MOFEM_LOG("SELF", Sev::error) << "Failed to compute eigen values";
233 }
234 // CHKERR bound_eig(eig);
235 // rare case when two eigen values are equal
236 t_nb_uniq = get_uniq_nb<3>(&eig(0));
237 if (t_nb_uniq < 3) {
238 sort_eigen_vals(eig, eigen_vec);
239 }
240 t_eigen_vals(i) = eig(i);
241 t_eigen_vecs(i, j) = eigen_vec(i, j);
242 t_u(i, j) =
243 EigenMatrix::getMat(t_eigen_vals, t_eigen_vecs, EshelbianCore::f)(i, j);
244 auto get_t_diff_u = [&]() {
245 return EigenMatrix::getDiffMat(t_eigen_vals, t_eigen_vecs,
247 t_nb_uniq);
248 };
249 t_diff_u(i, j, k, l) = get_t_diff_u()(i, j, k, l);
251 t_Ldiff_u(i, j, L) = t_diff_u(i, j, m, n) * t_L(m, n, L);
252 return t_Ldiff_u;
253 };
254
255 auto calculate_total_stretch = [&](auto &t_h1) {
257
258 t_log_u2_h1(i, j) = 0;
259 t_log_stretch_total(i, j) = t_log_u(i, j);
260
263 t_R_h1(i, j) = t_kd(i, j);
264 t_inv_u_h1(i, j) = t_symm_kd(i, j);
265
266 return std::make_pair(t_R_h1, t_inv_u_h1);
267
268 } else {
269
272
274 t_C_h1(i, j) = t_h1(k, i) * t_h1(k, j);
275 eigen_vec(i, j) = t_C_h1(i, j);
276 if (computeEigenValuesSymmetric(eigen_vec, eig) != MB_SUCCESS) {
277 MOFEM_LOG("SELF", Sev::error) << "Failed to compute eigen values";
278 }
279
281 CHKERR bound_eig(eig);
282 }
283
284 t_log_u2_h1(i, j) =
285 EigenMatrix::getMat(eig, eigen_vec, EshelbianCore::inv_f)(i, j);
286 t_log_stretch_total(i, j) = t_log_u2_h1(i, j) / 2 + t_log_u(i, j);
287
288 auto f_inv_sqrt = [](auto e) { return 1. / std::sqrt(e); };
290 t_inv_u_h1(i, j) = EigenMatrix::getMat(eig, eigen_vec, f_inv_sqrt)(i, j);
292 t_R_h1(i, j) = t_h1(i, o) * t_inv_u_h1(o, j);
293
294 return std::make_pair(t_R_h1, t_inv_u_h1);
295 }
296 };
297
298 auto no_h1_loop = [&]() {
300
302 case LARGE_ROT:
303 break;
304 case SMALL_ROT:
305 break;
306 default:
307 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
308 "rotSelector should be large");
309 };
310
311 for (int gg = 0; gg != nb_integration_pts; ++gg) {
312
314
316 t_h1(i, j) = t_kd(i, j);
317
318 // calculate streach
319 auto t_Ldiff_u = calculate_log_stretch();
320
321 // calculate total stretch
322 auto [t_R_h1, t_inv_u_h1] = calculate_total_stretch(t_h1);
323
328
330
331 // rotation
333 case LARGE_ROT:
334 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
335 t_diff_R(i, j, k) =
336 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
337 // left
338 t_diff_Rr(i, j, l) = t_R(i, k) * levi_civita(k, j, l);
339 t_diff_diff_Rr(i, j, l, m) = t_diff_R(i, k, m) * levi_civita(k, j, l);
340 // right
341 t_diff_Rl(i, j, l) = levi_civita(i, k, l) * t_R(k, j);
342 t_diff_diff_Rl(i, j, l, m) = levi_civita(i, k, l) * t_diff_R(k, j, m);
343 break;
344
345 default:
346 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
347 "rotationSelector not handled");
348 }
349
350 constexpr double half_r = 1 / 2.;
351 constexpr double half_l = 1 / 2.;
352
353 // calculate gradient
354 t_h(i, k) = t_R(i, l) * t_u(l, k);
355
356 // Adjoint stress
357 t_approx_P_adjoint_dstretch(l, k) =
358 (t_R(i, l) * t_approx_P(i, k) + t_R(i, k) * t_approx_P(i, l));
359 t_approx_P_adjoint_dstretch(l, k) /= 2.;
360
361 t_approx_P_adjoint_log_du(L) =
362 t_approx_P_adjoint_dstretch(l, k) * t_Ldiff_u(l, k, L);
363
364 // Kirchhoff stress
365 t_levi_kirchhoff(m) =
366
367 half_r * (t_diff_Rr(i, l, m) * (t_u(l, k) * t_approx_P(i, k)) +
368 t_diff_Rr(i, k, m) * (t_u(l, k) * t_approx_P(i, l)))
369
370 +
371
372 half_l * (t_diff_Rl(i, l, m) * (t_u(l, k) * t_approx_P(i, k)) +
373 t_diff_Rl(i, k, m) * (t_u(l, k) * t_approx_P(i, l)));
374 t_levi_kirchhoff(m) /= 2.;
375
377
379 t_h_domega(i, k, m) = half_r * (t_diff_Rr(i, l, m) * t_u(l, k))
380
381 +
382
383 half_l * (t_diff_Rl(i, l, m) * t_u(l, k));
384 } else {
385 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
386 "symmetrySelector not handled");
387 }
388
389 t_h_dlog_u(i, k, L) = t_R(i, l) * t_Ldiff_u(l, k, L);
390
391 t_approx_P_adjoint_log_du_dP(i, k, L) = t_R(i, l) * t_Ldiff_u(l, k, L);
392
394 t_A(k, l, m) = t_diff_Rr(i, l, m) * t_approx_P(i, k) +
395 t_diff_Rr(i, k, m) * t_approx_P(i, l);
396 t_A(k, l, m) /= 2.;
398 t_B(k, l, m) = t_diff_Rl(i, l, m) * t_approx_P(i, k) +
399 t_diff_Rl(i, k, m) * t_approx_P(i, l);
400 t_B(k, l, m) /= 2.;
401
402 t_approx_P_adjoint_log_du_domega(m, L) =
403 half_r * (t_A(k, l, m) * t_Ldiff_u(k, l, L)) +
404 half_l * (t_B(k, l, m) * t_Ldiff_u(k, l, L));
405
406 t_levi_kirchhoff_domega(m, n) =
407 half_r *
408 (t_diff_diff_Rr(i, l, m, n) * (t_u(l, k) * t_approx_P(i, k)) +
409 t_diff_diff_Rr(i, k, m, n) * (t_u(l, k) * t_approx_P(i, l)))
410
411 +
412
413 half_l *
414 (t_diff_diff_Rl(i, l, m, n) * (t_u(l, k) * t_approx_P(i, k)) +
415 t_diff_diff_Rl(i, k, m, n) * (t_u(l, k) * t_approx_P(i, l)));
416 t_levi_kirchhoff_domega(m, n) /= 2.;
417 }
418
419 next();
420 }
421
423 };
424
425 auto large_loop = [&]() {
427
429 case LARGE_ROT:
430 break;
431 case SMALL_ROT:
432 break;
433 default:
434 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
435 "rotSelector should be large");
436 };
437
438 for (int gg = 0; gg != nb_integration_pts; ++gg) {
439
441
445 t_h1(i, j) = t_kd(i, j);
446 break;
447 case LARGE_ROT:
448 t_h1(i, j) = t_grad_h1(i, j) + t_kd(i, j);
449 break;
450 default:
451 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
452 "gradApproximator not handled");
453 };
454
455 // calculate streach
456 auto t_Ldiff_u = calculate_log_stretch();
457 // calculate total stretch
458 auto [t_R_h1, t_inv_u_h1] = calculate_total_stretch(t_h1);
459
461 t_h_u(l, k) = t_u(l, o) * t_h1(o, k);
463 t_Ldiff_h_u(l, k, L) = t_Ldiff_u(l, o, L) * t_h1(o, k);
464
469
471
472 // rotation
474 case LARGE_ROT:
475 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
476 t_diff_R(i, j, k) =
477 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
478 // left
479 t_diff_Rr(i, j, l) = t_R(i, k) * levi_civita(k, j, l);
480 t_diff_diff_Rr(i, j, l, m) = t_diff_R(i, k, m) * levi_civita(k, j, l);
481 // right
482 t_diff_Rl(i, j, l) = levi_civita(i, k, l) * t_R(k, j);
483 t_diff_diff_Rl(i, j, l, m) = levi_civita(i, k, l) * t_diff_R(k, j, m);
484 break;
485 case SMALL_ROT:
486 t_R(i, k) = t_kd(i, k) + levi_civita(i, k, l) * t_omega(l);
487 t_diff_R(i, j, k) = levi_civita(i, j, k);
488 // left
489 t_diff_Rr(i, j, l) = levi_civita(i, j, l);
490 t_diff_diff_Rr(i, j, l, m) = 0;
491 // right
492 t_diff_Rl(i, j, l) = levi_civita(i, j, l);
493 t_diff_diff_Rl(i, j, l, m) = 0;
494 break;
495
496 default:
497 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
498 "rotationSelector not handled");
499 }
500
501 constexpr double half_r = 1 / 2.;
502 constexpr double half_l = 1 / 2.;
503
504 // calculate gradient
505 t_h(i, k) = t_R(i, l) * t_h_u(l, k);
506
507 // Adjoint stress
508 t_approx_P_adjoint_dstretch(l, o) =
509 (t_R(i, l) * t_approx_P(i, k)) * t_h1(o, k);
510 t_approx_P_adjoint_log_du(L) =
511 t_approx_P_adjoint_dstretch(l, o) * t_Ldiff_u(l, o, L);
512
513 // Kirchhoff stress
514 t_levi_kirchhoff(m) =
515
516 half_r * ((t_diff_Rr(i, l, m) * (t_h_u(l, k)) * t_approx_P(i, k)))
517
518 +
519
520 half_l * ((t_diff_Rl(i, l, m) * (t_h_u(l, k)) * t_approx_P(i, k)));
521
523
525 t_h_domega(i, k, m) = half_r * (t_diff_Rr(i, l, m) * t_h_u(l, k))
526
527 +
528
529 half_l * (t_diff_Rl(i, l, m) * t_h_u(l, k));
530 } else {
531 t_h_domega(i, k, m) = t_diff_R(i, l, m) * t_h_u(l, k);
532 }
533
534 t_h_dlog_u(i, k, L) = t_R(i, l) * t_Ldiff_h_u(l, k, L);
535
536 t_approx_P_adjoint_log_du_dP(i, k, L) =
537 t_R(i, l) * t_Ldiff_h_u(l, k, L);
538
541 t_A(m, L, i, k) = t_diff_Rr(i, l, m) * t_Ldiff_h_u(l, k, L);
543 t_B(m, L, i, k) = t_diff_Rl(i, l, m) * t_Ldiff_h_u(l, k, L);
544
545 t_approx_P_adjoint_log_du_domega(m, L) =
546 half_r * (t_A(m, L, i, k) * t_approx_P(i, k))
547
548 +
549
550 half_l * (t_B(m, L, i, k) * t_approx_P(i, k));
551 } else {
553 t_A(m, L, i, k) = t_diff_R(i, l, m) * t_Ldiff_h_u(l, k, L);
554 t_approx_P_adjoint_log_du_domega(m, L) =
555 t_A(m, L, i, k) * t_approx_P(i, k);
556 }
557
558 t_levi_kirchhoff_dstreach(m, L) =
559 half_r *
560 (t_diff_Rr(i, l, m) * (t_Ldiff_h_u(l, k, L) * t_approx_P(i, k)))
561
562 +
563
564 half_l * (t_diff_Rl(i, l, m) *
565 (t_Ldiff_h_u(l, k, L) * t_approx_P(i, k)));
566
567 t_levi_kirchhoff_dP(m, i, k) =
568
569 half_r * (t_diff_Rr(i, l, m) * t_h_u(l, k))
570
571 +
572
573 half_l * (t_diff_Rl(i, l, m) * t_h_u(l, k));
574
575 t_levi_kirchhoff_domega(m, n) =
576 half_r *
577 (t_diff_diff_Rr(i, l, m, n) * (t_h_u(l, k) * t_approx_P(i, k)))
578
579 +
580
581 half_l *
582 (t_diff_diff_Rl(i, l, m, n) * (t_h_u(l, k) * t_approx_P(i, k)));
583 }
584
585 next();
586 }
587
589 };
590
591 auto moderate_loop = [&]() {
593
595 case LARGE_ROT:
596 break;
597 case SMALL_ROT:
598 break;
599 default:
600 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
601 "rotSelector should be large");
602 };
603
604 for (int gg = 0; gg != nb_integration_pts; ++gg) {
605
607
610 case MODERATE_ROT:
611 t_h1(i, j) = t_grad_h1(i, j) + t_kd(i, j);
612 break;
613 default:
614 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
615 "gradApproximator not handled");
616 };
617
618 // calculate streach
619 auto t_Ldiff_u = calculate_log_stretch();
620 // calculate total stretch
621 auto [t_R_h1, t_inv_u_h1] = calculate_total_stretch(t_h1);
622
624 t_h_u(l, k) = (t_symm_kd(l, o) + t_log_u(l, o)) * t_h1(o, k);
626 t_L_h(l, k, L) = t_L(l, o, L) * t_h1(o, k);
627
632
634
635 // rotation
637 case LARGE_ROT:
638 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
639 t_diff_R(i, j, k) =
640 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
641 // left
642 t_diff_Rr(i, j, l) = t_R(i, k) * levi_civita(k, j, l);
643 t_diff_diff_Rr(i, j, l, m) = t_diff_R(i, k, m) * levi_civita(k, j, l);
644 // right
645 t_diff_Rl(i, j, l) = levi_civita(i, k, l) * t_R(k, j);
646 t_diff_diff_Rl(i, j, l, m) = levi_civita(i, k, l) * t_diff_R(k, j, m);
647 break;
648 case SMALL_ROT:
649 t_R(i, k) = t_kd(i, k) + levi_civita(i, k, l) * t_omega(l);
650 t_diff_R(i, j, l) = levi_civita(i, j, l);
651 // left
652 t_diff_Rr(i, j, l) = levi_civita(i, j, l);
653 t_diff_diff_Rr(i, j, l, m) = 0;
654 // right
655 t_diff_Rl(i, j, l) = levi_civita(i, j, l);
656 t_diff_diff_Rl(i, j, l, m) = 0;
657 break;
658
659 default:
660 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
661 "rotationSelector not handled");
662 }
663
664 constexpr double half_r = 1 / 2.;
665 constexpr double half_l = 1 / 2.;
666
667 // calculate gradient
668 t_h(i, k) = t_R(i, l) * t_h_u(l, k);
669
670 // Adjoint stress
671 t_approx_P_adjoint_dstretch(l, o) =
672 (t_R(i, l) * t_approx_P(i, k)) * t_h1(o, k);
673
674 t_approx_P_adjoint_log_du(L) =
675 t_approx_P_adjoint_dstretch(l, o) * t_L(l, o, L);
676
677 // Kirchhoff stress
678 t_levi_kirchhoff(m) =
679
680 half_r * ((t_diff_Rr(i, l, m) * (t_h_u(l, k)) * t_approx_P(i, k)))
681
682 +
683
684 half_l * ((t_diff_Rl(i, l, m) * (t_h_u(l, k)) * t_approx_P(i, k)));
685
687
689 t_h_domega(i, k, m) = half_r * (t_diff_Rr(i, l, m) * t_h_u(l, k))
690
691 +
692
693 half_l * (t_diff_Rl(i, l, m) * t_h_u(l, k));
694 } else {
695 t_h_domega(i, k, m) = t_diff_R(i, l, m) * t_h_u(l, k);
696 }
697
698 t_h_dlog_u(i, k, L) = t_R(i, l) * t_L_h(l, k, L);
699
700 t_approx_P_adjoint_log_du_dP(i, k, L) = t_R(i, l) * t_L_h(l, k, L);
701
704 t_A(m, L, i, k) = t_diff_Rr(i, l, m) * t_L_h(l, k, L);
706 t_B(m, L, i, k) = t_diff_Rl(i, l, m) * t_L_h(l, k, L);
707 t_approx_P_adjoint_log_du_domega(m, L) =
708 half_r * (t_A(m, L, i, k) * t_approx_P(i, k))
709
710 +
711
712 half_l * (t_B(m, L, i, k) * t_approx_P(i, k));
713 } else {
715 t_A(m, L, i, k) = t_diff_R(i, l, m) * t_L_h(l, k, L);
716 t_approx_P_adjoint_log_du_domega(m, L) =
717 t_A(m, L, i, k) * t_approx_P(i, k);
718 }
719
720 t_levi_kirchhoff_dstreach(m, L) =
721 half_r * (t_diff_Rr(i, l, m) * (t_L_h(l, k, L) * t_approx_P(i, k)))
722
723 +
724
725 half_l * (t_diff_Rl(i, l, m) * (t_L_h(l, k, L) * t_approx_P(i, k)));
726
727 t_levi_kirchhoff_dP(m, i, k) =
728
729 half_r * (t_diff_Rr(i, l, m) * t_h_u(l, k))
730
731 +
732
733 half_l * (t_diff_Rl(i, l, m) * t_h_u(l, k));
734
735 t_levi_kirchhoff_domega(m, n) =
736 half_r *
737 (t_diff_diff_Rr(i, l, m, n) * (t_h_u(l, k) * t_approx_P(i, k)))
738
739 +
740
741 half_l *
742 (t_diff_diff_Rl(i, l, m, n) * (t_h_u(l, k) * t_approx_P(i, k)));
743 }
744
745 next();
746 }
747
749 };
750
751 auto small_loop = [&]() {
754 case SMALL_ROT:
755 break;
756 default:
757 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
758 "rotSelector should be small");
759 };
760
761 for (int gg = 0; gg != nb_integration_pts; ++gg) {
762
765 case SMALL_ROT:
766 t_h1(i, j) = t_kd(i, j);
767 break;
768 default:
769 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
770 "gradApproximator not handled");
771 };
772
773 // calculate streach
775
777 t_Ldiff_u(i, j, L) = calculate_log_stretch()(i, j, L);
778 } else {
779 t_u(i, j) = t_symm_kd(i, j) + t_log_u(i, j);
780 t_Ldiff_u(i, j, L) = t_L(i, j, L);
781 }
782 t_log_u2_h1(i, j) = 0;
783 t_log_stretch_total(i, j) = t_log_u(i, j);
784
786 t_h(i, j) = levi_civita(i, j, k) * t_omega(k) + t_u(i, j);
787
788 t_h_domega(i, j, k) = levi_civita(i, j, k);
789 t_h_dlog_u(i, j, L) = t_Ldiff_u(i, j, L);
790
791 // Adjoint stress
792 t_approx_P_adjoint_dstretch(i, j) = t_approx_P(i, j);
793 t_approx_P_adjoint_log_du(L) =
794 t_approx_P_adjoint_dstretch(i, j) * t_Ldiff_u(i, j, L);
795 t_approx_P_adjoint_log_du_dP(i, j, L) = t_Ldiff_u(i, j, L);
796 t_approx_P_adjoint_log_du_domega(m, L) = 0;
797
798 // Kirchhoff stress
799 t_levi_kirchhoff(k) = levi_civita(i, j, k) * t_approx_P(i, j);
800 t_levi_kirchhoff_dstreach(m, L) = 0;
801 t_levi_kirchhoff_dP(k, i, j) = levi_civita(i, j, k);
802 t_levi_kirchhoff_domega(m, n) = 0;
803
804 next();
805 }
806
808 };
809
812 CHKERR no_h1_loop();
813 break;
814 case LARGE_ROT:
815 CHKERR large_loop();
817 break;
818 case MODERATE_ROT:
819 CHKERR moderate_loop();
821 break;
822 case SMALL_ROT:
823 CHKERR small_loop();
825 break;
826 default:
827 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
828 "gradApproximator not handled");
829 break;
830 };
831
833}
834
836 EntData &data) {
840
841 auto N_InLoop = getNinTheLoop();
842 auto sensee = getSkeletonSense();
843 auto nb_gauss_pts = getGaussPts().size2();
844 auto t_normal = getFTensor1NormalsAtGaussPts();
845
846 auto t_sigma_ptr =
847 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->approxPAtPts);
848 if (N_InLoop == 0) {
849 dataAtPts->tractionAtPts.resize(SPACE_DIM, nb_gauss_pts, false);
850 dataAtPts->tractionAtPts.clear();
851 }
852 auto t_traction = getFTensor1FromMat<SPACE_DIM>(dataAtPts->tractionAtPts);
853
854 for (int gg = 0; gg != nb_gauss_pts; gg++) {
855 t_traction(i) = t_sigma_ptr(i, j) * sensee * (t_normal(j) / t_normal.l2());
856 ++t_traction;
857 ++t_sigma_ptr;
858 ++t_normal;
859 }
860
862}
863
865 EntData &data) {
867 if (blockEntities.find(getFEEntityHandle()) == blockEntities.end()) {
869 };
873 int nb_integration_pts = getGaussPts().size2();
874 auto t_w = getFTensor0IntegrationWeight();
875 auto t_traction = getFTensor1FromMat<SPACE_DIM>(dataAtPts->tractionAtPts);
876 auto t_coords = getFTensor1CoordsAtGaussPts();
877 auto t_spatial_disp = getFTensor1FromMat<SPACE_DIM>(dataAtPts->wL2AtPts);
878
879 FTensor::Tensor1<double, 3> t_coords_spatial{0., 0., 0.};
880 // Offset for center of mass. Can be added in the future.
881 FTensor::Tensor1<double, 3> t_off{0.0, 0.0, 0.0};
882 FTensor::Tensor1<double, 3> loc_reaction_forces{0., 0., 0.};
883 FTensor::Tensor1<double, 3> loc_moment_forces{0., 0., 0.};
884
885 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
886 loc_reaction_forces(i) += (t_traction(i)) * t_w * getMeasure();
887 t_coords_spatial(i) = t_coords(i) + t_spatial_disp(i);
888 // t_coords_spatial(i) -= t_off(i);
889 loc_moment_forces(i) +=
890 (FTensor::levi_civita<double>(i, j, k) * t_coords_spatial(j)) *
891 t_traction(k) * t_w * getMeasure();
892 ++t_coords;
893 ++t_spatial_disp;
894 ++t_w;
895 ++t_traction;
896 }
897
898 reactionVec[0] += loc_reaction_forces(0);
899 reactionVec[1] += loc_reaction_forces(1);
900 reactionVec[2] += loc_reaction_forces(2);
901 reactionVec[3] += loc_moment_forces(0);
902 reactionVec[4] += loc_moment_forces(1);
903 reactionVec[5] += loc_moment_forces(2);
904
906}
907
910 int nb_dofs = data.getIndices().size();
911 int nb_integration_pts = data.getN().size1();
912 auto v = getVolume();
913 auto t_w = getFTensor0IntegrationWeight();
914 auto t_div_P = getFTensor1FromMat<3>(dataAtPts->divPAtPts);
915 auto t_s_dot_w = getFTensor1FromMat<3>(dataAtPts->wL2DotAtPts);
916 if (dataAtPts->wL2DotDotAtPts.size1() == 0 &&
917 dataAtPts->wL2DotDotAtPts.size2() != nb_integration_pts) {
918 dataAtPts->wL2DotDotAtPts.resize(3, nb_integration_pts);
919 dataAtPts->wL2DotDotAtPts.clear();
920 }
921 auto t_s_dot_dot_w = getFTensor1FromMat<3>(dataAtPts->wL2DotDotAtPts);
922
923 auto piola_scale = dataAtPts->piolaScale;
924 auto alpha_w = alphaW / piola_scale;
925 auto alpha_rho = alphaRho / piola_scale;
926
927 int nb_base_functions = data.getN().size2();
928 auto t_row_base_fun = data.getFTensor0N();
929
930 FTensor::Index<'i', 3> i;
931 auto get_ftensor1 = [](auto &v) {
933 &v[2]);
934 };
935
936 for (int gg = 0; gg != nb_integration_pts; ++gg) {
937 double a = v * t_w;
938 auto t_nf = get_ftensor1(nF);
939 int bb = 0;
940 for (; bb != nb_dofs / 3; ++bb) {
941 t_nf(i) -= a * t_row_base_fun * t_div_P(i);
942 t_nf(i) += a * t_row_base_fun * alpha_w * t_s_dot_w(i);
943 t_nf(i) += a * t_row_base_fun * alpha_rho * t_s_dot_dot_w(i);
944 ++t_nf;
945 ++t_row_base_fun;
946 }
947 for (; bb != nb_base_functions; ++bb)
948 ++t_row_base_fun;
949 ++t_w;
950 ++t_div_P;
951 ++t_s_dot_w;
952 ++t_s_dot_dot_w;
953 }
954
956}
957
960 int nb_dofs = data.getIndices().size();
961 int nb_integration_pts = getGaussPts().size2();
962 auto v = getVolume();
963 auto t_w = getFTensor0IntegrationWeight();
964 auto t_levi_kirchhoff = getFTensor1FromMat<3>(dataAtPts->leviKirchhoffAtPts);
965 auto t_omega_grad_dot =
966 getFTensor2FromMat<3, 3>(dataAtPts->rotAxisGradDotAtPts);
967 int nb_base_functions = data.getN().size2();
968 auto t_row_base_fun = data.getFTensor0N();
969 auto t_row_grad_fun = data.getFTensor1DiffN<3>();
970 FTensor::Index<'i', 3> i;
971 FTensor::Index<'j', 3> j;
972 FTensor::Index<'k', 3> k;
973 auto get_ftensor1 = [](auto &v) {
975 &v[2]);
976 };
977 for (int gg = 0; gg != nb_integration_pts; ++gg) {
978 double a = v * t_w;
979 auto t_nf = get_ftensor1(nF);
980 int bb = 0;
981 for (; bb != nb_dofs / 3; ++bb) {
982 t_nf(k) -= (a * t_row_base_fun) * t_levi_kirchhoff(k);
983 t_nf(k) +=
984 (a * alphaOmega) * (t_row_grad_fun(i) * t_omega_grad_dot(k, i));
985 ++t_nf;
986 ++t_row_base_fun;
987 ++t_row_grad_fun;
988 }
989 for (; bb != nb_base_functions; ++bb) {
990 ++t_row_base_fun;
991 ++t_row_grad_fun;
992 }
993 ++t_w;
994 ++t_levi_kirchhoff;
995 ++t_omega_grad_dot;
996 }
998}
999
1002 int nb_dofs = data.getIndices().size();
1003 int nb_integration_pts = data.getN().size1();
1004 auto v = getVolume();
1005 auto t_w = getFTensor0IntegrationWeight();
1006
1007 int nb_base_functions = data.getN().size2() / 3;
1008 auto t_row_base_fun = data.getFTensor1N<3>();
1009 FTENSOR_INDEX(3, i);
1010 FTENSOR_INDEX(3, j);
1011 FTENSOR_INDEX(3, k);
1012 FTENSOR_INDEX(3, m);
1013 FTENSOR_INDEX(3, l);
1014
1015 auto get_ftensor1 = [](auto &v) {
1017 &v[2]);
1018 };
1019
1021
1022 auto t_R = getFTensor2FromMat<3, 3>(dataAtPts->rotMatAtPts);
1023 auto t_u = getFTensor2SymmetricFromMat<3>(dataAtPts->stretchTensorAtPts);
1024
1025 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1026 double a = v * t_w;
1027 auto t_nf = get_ftensor1(nF);
1028
1029 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1030
1031 int bb = 0;
1032 for (; bb != nb_dofs / 3; ++bb) {
1033 t_nf(i) -= a * (t_row_base_fun(k) * (t_R(i, l) * t_u(l, k)) / 2);
1034 t_nf(i) -= a * (t_row_base_fun(l) * (t_R(i, k) * t_u(l, k)) / 2);
1035 t_nf(i) += a * (t_row_base_fun(j) * t_kd(i, j));
1036 ++t_nf;
1037 ++t_row_base_fun;
1038 }
1039
1040 for (; bb != nb_base_functions; ++bb)
1041 ++t_row_base_fun;
1042
1043 ++t_w;
1044 ++t_R;
1045 ++t_u;
1046 }
1047
1048 } else {
1049
1050 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
1051
1052 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1053 double a = v * t_w;
1054 auto t_nf = get_ftensor1(nF);
1055
1056 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1058
1059 t_residuum(i, j) = t_h(i, j) - t_kd(i, j);
1060
1061 int bb = 0;
1062 for (; bb != nb_dofs / 3; ++bb) {
1063 t_nf(i) -= a * t_row_base_fun(j) * t_residuum(i, j);
1064 ++t_nf;
1065 ++t_row_base_fun;
1066 }
1067
1068 for (; bb != nb_base_functions; ++bb)
1069 ++t_row_base_fun;
1070
1071 ++t_w;
1072 ++t_h;
1073 }
1074 }
1075
1077}
1078
1081 int nb_dofs = data.getIndices().size();
1082 int nb_integration_pts = data.getN().size1();
1083 auto v = getVolume();
1084 auto t_w = getFTensor0IntegrationWeight();
1085
1086 int nb_base_functions = data.getN().size2() / 9;
1087 auto t_row_base_fun = data.getFTensor2N<3, 3>();
1088 FTENSOR_INDEX(3, i);
1089 FTENSOR_INDEX(3, j);
1090 FTENSOR_INDEX(3, k);
1091 FTENSOR_INDEX(3, m);
1092 FTENSOR_INDEX(3, l);
1093
1094 auto get_ftensor0 = [](auto &v) {
1096 };
1097
1099
1100 auto t_R = getFTensor2FromMat<3, 3>(dataAtPts->rotMatAtPts);
1101 auto t_u = getFTensor2SymmetricFromMat<3>(dataAtPts->stretchTensorAtPts);
1102
1103 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1104 double a = v * t_w;
1105 auto t_nf = get_ftensor0(nF);
1106
1107 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1108
1109 int bb = 0;
1110 for (; bb != nb_dofs; ++bb) {
1111 t_nf -= a * t_row_base_fun(i, k) * (t_R(i, l) * t_u(l, k)) / 2;
1112 t_nf -= a * t_row_base_fun(i, l) * (t_R(i, k) * t_u(l, k)) / 2;
1113 ++t_nf;
1114 ++t_row_base_fun;
1115 }
1116 for (; bb != nb_base_functions; ++bb) {
1117 ++t_row_base_fun;
1118 }
1119 ++t_w;
1120 ++t_R;
1121 ++t_u;
1122 }
1123
1124 } else {
1125
1126 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
1127
1128 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1129 double a = v * t_w;
1130 auto t_nf = get_ftensor0(nF);
1131
1132 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1134 t_residuum(i, j) = t_h(i, j);
1135
1136 int bb = 0;
1137 for (; bb != nb_dofs; ++bb) {
1138 t_nf -= a * t_row_base_fun(i, j) * t_residuum(i, j);
1139 ++t_nf;
1140 ++t_row_base_fun;
1141 }
1142 for (; bb != nb_base_functions; ++bb) {
1143 ++t_row_base_fun;
1144 }
1145 ++t_w;
1146 ++t_h;
1147 }
1148 }
1149
1151}
1152
1155 int nb_dofs = data.getIndices().size();
1156 int nb_integration_pts = data.getN().size1();
1157 auto v = getVolume();
1158 auto t_w = getFTensor0IntegrationWeight();
1159 auto t_w_l2 = getFTensor1FromMat<3>(dataAtPts->wL2AtPts);
1160 int nb_base_functions = data.getN().size2() / 3;
1161 auto t_row_diff_base_fun = data.getFTensor2DiffN<3, 3>();
1162 FTensor::Index<'i', 3> i;
1163 auto get_ftensor1 = [](auto &v) {
1165 &v[2]);
1166 };
1167
1168 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1169 double a = v * t_w;
1170 auto t_nf = get_ftensor1(nF);
1171 int bb = 0;
1172 for (; bb != nb_dofs / 3; ++bb) {
1173 double div_row_base = t_row_diff_base_fun(i, i);
1174 t_nf(i) -= a * div_row_base * t_w_l2(i);
1175 ++t_nf;
1176 ++t_row_diff_base_fun;
1177 }
1178 for (; bb != nb_base_functions; ++bb) {
1179 ++t_row_diff_base_fun;
1180 }
1181 ++t_w;
1182 ++t_w_l2;
1183 }
1184
1186}
1187
1190
1192
1193 double time = OpAssembleVolume::getFEMethod()->ts_t;
1196 }
1197 // get entity of tet
1199 // iterate over all block data
1200
1201 for (auto &ext_strain_block : (*externalStrainVecPtr)) {
1202 // check if finite element entity is part of the EXTERNALSTRAIN block
1203 if (ext_strain_block.ents.find(fe_ent) != ext_strain_block.ents.end()) {
1204
1205 double scale = 1;
1206 if (scalingMethodsMap.find(ext_strain_block.blockName) != scalingMethodsMap.end()) {
1207 scale *= scalingMethodsMap.at(ext_strain_block.blockName)->getScale(time);
1208 } else {
1209 MOFEM_LOG("SELF", Sev::warning)
1210 << "No scaling method found for " << ext_strain_block.blockName;
1211 }
1212
1213 // get ExternalStrain data
1214 double val = scale * ext_strain_block.val;
1215
1216 auto t_L = symm_L_tensor();
1217
1218 int nb_dofs = data.getIndices().size();
1219 int nb_integration_pts = data.getN().size1();
1220 auto v = getVolume();
1221 auto t_w = getFTensor0IntegrationWeight();
1222
1223 dataAtPts->externalStrainAtPts.resize(size_symm, nb_integration_pts, false);
1224 auto t_external_strain =
1225 getFTensor2SymmetricFromMat<3>(dataAtPts->externalStrainAtPts);
1227
1228 auto t_D =
1229 getFTensor4DdgFromPtr<3, 3, 0>(&*dataAtPts->matD.data().begin());
1230
1231 FTensor::Index<'i', 3> i;
1232 FTensor::Index<'j', 3> j;
1233 FTensor::Index<'k', 3> k;
1234 FTensor::Index<'l', 3> l;
1235 auto get_ftensor2 = [](auto &v) {
1237 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1238 };
1239
1240 int nb_base_functions = data.getN().size2();
1241 auto t_row_base_fun = data.getFTensor0N();
1242 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1243 t_external_strain(i, j) = -t_kd(i, j) * val;
1244 double a = v * t_w;
1245 auto t_nf = get_ftensor2(nF);
1246
1248 t_T(i, j) = t_D(i, j, k, l) * t_external_strain(k, l);
1249
1251 t_residual(L) = a * (t_L(i, j, L) * t_T(i, j));
1252
1253 int bb = 0;
1254 for (; bb != nb_dofs / 6; ++bb) {
1255 t_nf(L) += t_row_base_fun * t_residual(L);
1256 ++t_nf;
1257 ++t_row_base_fun;
1258 }
1259 for (; bb != nb_base_functions; ++bb)
1260 ++t_row_base_fun;
1261
1262 ++t_w;
1263 ++t_external_strain;
1264 }
1265 }
1266 }
1268}
1269
1270template <>
1272 EntData &data) {
1274
1275 int nb_integration_pts = getGaussPts().size2();
1276
1277 Tag tag;
1278 CHKERR getPtrFE() -> mField.get_moab().tag_get_handle(tagName.c_str(), tag);
1279 int tag_length;
1280 CHKERR getPtrFE() -> mField.get_moab().tag_get_length(tag, tag_length);
1281 if (tag_length != 9) {
1282 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1283 "Number of internal stress components should be 9 but is %d",
1284 tag_length);
1285 }
1286
1287 VectorDouble const_stress_vec(9);
1288 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1289 CHKERR getPtrFE() -> mField.get_moab().tag_get_data(
1290 tag, &fe_ent, 1, &*const_stress_vec.data().begin());
1291 auto t_const_stress = getFTensor1FromArray<9, 9>(const_stress_vec);
1292
1293 dataAtPts->internalStressAtPts.resize(tag_length, nb_integration_pts, false);
1294 dataAtPts->internalStressAtPts.clear();
1295 auto t_internal_stress =
1296 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1297
1298 FTensor::Index<'L', 9> L;
1299 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1300 t_internal_stress(L) = t_const_stress(L);
1301 ++t_internal_stress;
1302 }
1303
1305}
1306
1307template <>
1309 EntityType type,
1310 EntData &data) {
1312
1313 int nb_integration_pts = getGaussPts().size2();
1314
1315 Tag tag;
1316 CHKERR getPtrFE() -> mField.get_moab().tag_get_handle(tagName.c_str(), tag);
1317 int tag_length;
1318 CHKERR getPtrFE() -> mField.get_moab().tag_get_length(tag, tag_length);
1319 if (tag_length != 9) {
1320 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1321 "Number of internal stress components should be 9 but is %d",
1322 tag_length);
1323 }
1324
1325 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1326 const EntityHandle *vert_conn;
1327 int vert_num;
1328 CHKERR getPtrFE() -> mField.get_moab().get_connectivity(fe_ent, vert_conn,
1329 vert_num, true);
1330 VectorDouble vert_data(vert_num * tag_length);
1331 CHKERR getPtrFE() -> mField.get_moab().tag_get_data(tag, vert_conn, vert_num,
1332 &vert_data[0]);
1333
1334 dataAtPts->internalStressAtPts.resize(tag_length, nb_integration_pts, false);
1335 dataAtPts->internalStressAtPts.clear();
1336 auto t_internal_stress =
1337 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1338
1339 auto t_shape_n = data.getFTensor0N();
1340 int nb_shape_fn = data.getN(NOBASE).size2();
1341 FTensor::Index<'L', 9> L;
1342 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1343 auto t_vert_data = getFTensor1FromArray<9, 9>(vert_data);
1344 for (int bb = 0; bb != nb_shape_fn; ++bb) {
1345 t_internal_stress(L) += t_vert_data(L) * t_shape_n;
1346 ++t_vert_data;
1347 ++t_shape_n;
1348 }
1349 ++t_internal_stress;
1350 }
1351
1353}
1354
1355template <>
1358
1359 int nb_dofs = data.getIndices().size();
1360 int nb_integration_pts = data.getN().size1();
1361 auto v = getVolume();
1362 auto t_w = getFTensor0IntegrationWeight();
1363
1364 FTensor::Index<'i', 3> i;
1365 FTensor::Index<'j', 3> j;
1366
1367 auto get_ftensor2 = [](auto &v) {
1369 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1370 };
1371
1372 auto t_internal_stress =
1373 getFTensor2FromMat<3, 3>(dataAtPts->internalStressAtPts);
1374
1376 auto t_L = symm_L_tensor();
1377
1378 int nb_base_functions = data.getN().size2();
1379 auto t_row_base_fun = data.getFTensor0N();
1380 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1381 double a = v * t_w;
1382 auto t_nf = get_ftensor2(nF);
1383
1384 FTensor::Tensor2<double, 3, 3> t_symm_stress;
1385 t_symm_stress(i, j) =
1386 (t_internal_stress(i, j) + t_internal_stress(j, i)) / 2;
1387
1389 t_residual(L) = t_L(i, j, L) * t_symm_stress(i, j);
1390
1391 int bb = 0;
1392 for (; bb != nb_dofs / 6; ++bb) {
1393 t_nf(L) += a * t_row_base_fun * t_residual(L);
1394 ++t_nf;
1395 ++t_row_base_fun;
1396 }
1397 for (; bb != nb_base_functions; ++bb)
1398 ++t_row_base_fun;
1399
1400 ++t_w;
1401 ++t_internal_stress;
1402 }
1404}
1405
1406template <>
1409
1410 int nb_dofs = data.getIndices().size();
1411 int nb_integration_pts = data.getN().size1();
1412 auto v = getVolume();
1413 auto t_w = getFTensor0IntegrationWeight();
1414
1415 auto get_ftensor2 = [](auto &v) {
1417 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1418 };
1419
1420 auto t_internal_stress =
1421 getFTensor1FromMat<9>(dataAtPts->internalStressAtPts);
1422
1424 FTensor::Index<'M', size_symm> M;
1426 t_L = voigt_to_symm();
1427
1428 int nb_base_functions = data.getN().size2();
1429 auto t_row_base_fun = data.getFTensor0N();
1430 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1431 double a = v * t_w;
1432 auto t_nf = get_ftensor2(nF);
1433
1435 t_residual(L) = t_L(M, L) * t_internal_stress(M);
1436
1437 int bb = 0;
1438 for (; bb != nb_dofs / 6; ++bb) {
1439 t_nf(L) += a * t_row_base_fun * t_residual(L);
1440 ++t_nf;
1441 ++t_row_base_fun;
1442 }
1443 for (; bb != nb_base_functions; ++bb)
1444 ++t_row_base_fun;
1445
1446 ++t_w;
1447 ++t_internal_stress;
1448 }
1450}
1451
1452template <AssemblyType A>
1455 // get entity of face
1456 EntityHandle fe_ent = OP::getFEEntityHandle();
1457 // iterate over all boundary data
1458 for (auto &bc : (*bcDispPtr)) {
1459 // check if finite element entity is part of boundary condition
1460 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1461 int nb_dofs = data.getIndices().size();
1462
1463 int nb_integration_pts = OP::getGaussPts().size2();
1464 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1465 auto t_w = OP::getFTensor0IntegrationWeight();
1466 int nb_base_functions = data.getN().size2() / 3;
1467 auto t_row_base_fun = data.getFTensor1N<3>();
1468
1471
1472 double scale = 1;
1473 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1475 scale *= scalingMethodsMap.at(bc.blockName)
1476 ->getScale(EshelbianCore::dynamicTime);
1477 } else {
1478 scale *= scalingMethodsMap.at(bc.blockName)
1479 ->getScale(OP::getFEMethod()->ts_t);
1480 }
1481 } else {
1482 MOFEM_LOG("SELF", Sev::warning)
1483 << "No scaling method found for " << bc.blockName;
1484 }
1485
1486 // get bc data
1487 FTensor::Tensor1<double, 3> t_bc_disp(bc.vals[0], bc.vals[1], bc.vals[2]);
1488 t_bc_disp(i) *= scale;
1489
1490 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1491 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1492 int bb = 0;
1493 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1494 t_nf(i) +=
1495 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1496 ++t_nf;
1497 ++t_row_base_fun;
1498 }
1499 for (; bb != nb_base_functions; ++bb)
1500 ++t_row_base_fun;
1501
1502 ++t_w;
1503 ++t_normal;
1504 }
1505 }
1506 }
1508}
1509
1511 return OP::iNtegrate(data);
1512}
1513
1514template <AssemblyType A>
1517
1518 FTENSOR_INDEX(3, i);
1519 FTENSOR_INDEX(3, j);
1520 FTENSOR_INDEX(3, k);
1521
1522 double time = OP::getFEMethod()->ts_t;
1525 }
1526
1527 // get entity of face
1528 EntityHandle fe_ent = OP::getFEEntityHandle();
1529 // interate over all boundary data
1530 for (auto &bc : (*bcRotPtr)) {
1531 // check if finite element entity is part of boundary condition
1532 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1533 int nb_dofs = data.getIndices().size();
1534 int nb_integration_pts = OP::getGaussPts().size2();
1535 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1536 auto t_w = OP::getFTensor0IntegrationWeight();
1537
1538 int nb_base_functions = data.getN().size2() / 3;
1539 auto t_row_base_fun = data.getFTensor1N<3>();
1540
1541 auto get_ftensor1 = [](auto &v) {
1543 &v[2]);
1544 };
1545
1546 // Note: First three values of bc.vals are the center of rotation
1547 // 4th is rotation angle in radians, and remaining values are axis of
1548 // rotation. Also, if rotation axis is not provided, it defaults to the
1549 // normal vector of the face.
1550
1551 // get bc data
1552 FTensor::Tensor1<double, 3> t_center(bc.vals[0], bc.vals[1], bc.vals[2]);
1553
1554 auto get_rotation_angle = [&]() {
1555 double theta = bc.theta;
1556 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1557 theta *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1558 }
1559 return theta;
1560 };
1561
1562 auto get_rotation = [&](auto theta) {
1564 if (bc.vals.size() == 7) {
1565 t_omega(0) = bc.vals[4];
1566 t_omega(1) = bc.vals[5];
1567 t_omega(2) = bc.vals[6];
1568 } else {
1569 // Use gemetric face normal as rotation axis
1570 t_omega(i) = OP::getFTensor1Normal()(i);
1571 }
1572 t_omega.normalize();
1573 t_omega(i) *= theta;
1576 ? 0.
1577 : t_omega.l2());
1578 };
1579
1580 auto t_R = get_rotation(get_rotation_angle());
1581 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1582
1583 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1585 t_delta(i) = t_center(i) - t_coords(i);
1587 t_disp(i) = t_delta(i) - t_R(i, j) * t_delta(j);
1588
1589 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1590 int bb = 0;
1591 for (; bb != nb_dofs / 3; ++bb) {
1592 t_nf(i) += t_w * (t_row_base_fun(j) * t_normal(j)) * t_disp(i) * 0.5;
1593 ++t_nf;
1594 ++t_row_base_fun;
1595 }
1596 for (; bb != nb_base_functions; ++bb)
1597 ++t_row_base_fun;
1598
1599 ++t_w;
1600 ++t_normal;
1601 ++t_coords;
1602 }
1603 }
1604 }
1606}
1607
1609 return OP::iNtegrate(data);
1610}
1611
1612template <AssemblyType A>
1615
1616 double time = OP::getFEMethod()->ts_t;
1619 }
1620
1621 // get entity of face
1622 EntityHandle fe_ent = OP::getFEEntityHandle();
1623 // iterate over all boundary data
1624 for (auto &bc : (*bcDispPtr)) {
1625 // check if finite element entity is part of boundary condition
1626 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1627
1628 auto t_approx_P = getFTensor2FromMat<3, 3>(*piolaStressPtr);
1629 auto t_u = getFTensor1FromMat<3>(*hybridDispPtr);
1630 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1631 auto t_w = OP::getFTensor0IntegrationWeight();
1632
1635
1637
1638 double scale = 1;
1639 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1640 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1641 } else {
1642 MOFEM_LOG("SELF", Sev::warning)
1643 << "No scaling method found for " << bc.blockName;
1644 }
1645
1646 // get bc data
1647 double val = scale * bc.val;
1648
1649 int nb_dofs = data.getIndices().size();
1650 int nb_integration_pts = OP::getGaussPts().size2();
1651 int nb_base_functions = data.getN().size2();
1652 auto t_row_base = data.getFTensor0N();
1653 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1654
1656 t_N(i) = t_normal(i);
1657 t_N.normalize();
1658
1660 t_P(i, j) = t_N(i) * t_N(j);
1662 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
1663
1665 t_tracton(i) = t_approx_P(i, j) * t_N(j);
1666
1668 t_res(i) = t_Q(i, j) * t_tracton(j) + t_P(i, j) * 2* t_u(j) - t_N(i) * val;
1669
1670 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1671 int bb = 0;
1672 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1673 t_nf(i) += (t_w * t_row_base) * t_res(i);
1674 ++t_nf;
1675 ++t_row_base;
1676 }
1677 for (; bb != nb_base_functions; ++bb)
1678 ++t_row_base;
1679
1680 ++t_w;
1681 ++t_normal;
1682 ++t_u;
1683 ++t_approx_P;
1684 }
1685
1686 OP::locF *= OP::getMeasure();
1687 }
1688 }
1690}
1691
1692template <AssemblyType A>
1695 EntData &col_data) {
1697
1698 double time = OP::getFEMethod()->ts_t;
1701 }
1702
1703 int row_nb_dofs = row_data.getIndices().size();
1704 int col_nb_dofs = col_data.getIndices().size();
1705 auto &locMat = OP::locMat;
1706 locMat.resize(row_nb_dofs, col_nb_dofs, false);
1707 locMat.clear();
1708
1709 // get entity of face
1710 EntityHandle fe_ent = OP::getFEEntityHandle();
1711 // iterate over all boundary data
1712 for (auto &bc : (*bcDispPtr)) {
1713 // check if finite element entity is part of boundary condition
1714 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1715
1716 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1717 auto t_w = OP::getFTensor0IntegrationWeight();
1718
1721
1722 double scale = 1;
1723 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1724 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1725 } else {
1726 MOFEM_LOG("SELF", Sev::warning)
1727 << "No scaling method found for " << bc.blockName;
1728 }
1729
1730 int nb_integration_pts = OP::getGaussPts().size2();
1731 int row_nb_dofs = row_data.getIndices().size();
1732 int col_nb_dofs = col_data.getIndices().size();
1733 int nb_base_functions = row_data.getN().size2();
1734 auto t_row_base = row_data.getFTensor0N();
1735
1737
1738 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1739
1741 t_N(i) = t_normal(i);
1742 t_N.normalize();
1743
1745 t_P(i, j) = t_N(i) * t_N(j);
1746
1748 t_d_res(i, j) = 2.0 * t_P(i, j);
1749
1750 int rr = 0;
1751 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
1752 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
1753 locMat, SPACE_DIM * rr);
1754 auto t_col_base = col_data.getFTensor0N(gg, 0);
1755 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
1756 t_mat(i, j) += (t_w * t_row_base * t_col_base) * t_d_res(i, j);
1757 ++t_mat;
1758 ++t_col_base;
1759 }
1760 ++t_row_base;
1761 }
1762
1763 for (; rr != nb_base_functions; ++rr)
1764 ++t_row_base;
1765
1766 ++t_w;
1767 ++t_normal;
1768 }
1769
1770 locMat *= OP::getMeasure();
1771
1772 }
1773 }
1775}
1776
1777template <AssemblyType A>
1780 EntData &col_data) {
1782
1783 double time = OP::getFEMethod()->ts_t;
1786 }
1787
1788 int row_nb_dofs = row_data.getIndices().size();
1789 int col_nb_dofs = col_data.getIndices().size();
1790 auto &locMat = OP::locMat;
1791 locMat.resize(row_nb_dofs, col_nb_dofs, false);
1792 locMat.clear();
1793
1794 // get entity of face
1795 EntityHandle fe_ent = OP::getFEEntityHandle();
1796 // iterate over all boundary data
1797 for (auto &bc : (*bcDispPtr)) {
1798 // check if finite element entity is part of boundary condition
1799 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1800
1801 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1802 auto t_w = OP::getFTensor0IntegrationWeight();
1803
1807
1809
1810 double scale = 1;
1811 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1812 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1813 } else {
1814 MOFEM_LOG("SELF", Sev::warning)
1815 << "No scaling method found for " << bc.blockName;
1816 }
1817
1818 int nb_integration_pts = OP::getGaussPts().size2();
1819 int nb_base_functions = row_data.getN().size2();
1820 auto t_row_base = row_data.getFTensor0N();
1821
1822 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1823
1825 t_N(i) = t_normal(i);
1826 t_N.normalize();
1827
1829 t_P(i, j) = t_N(i) * t_N(j);
1831 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
1832
1834 t_d_res(i, j) = t_Q(i, j);
1835
1836 int rr = 0;
1837 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
1838 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
1839 OP::locMat, SPACE_DIM * rr);
1840 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1841 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
1842 t_mat(i, j) +=
1843 ((t_w * t_row_base) * (t_N(k) * t_col_base(k))) * t_d_res(i, j);
1844 ++t_mat;
1845 ++t_col_base;
1846 }
1847 ++t_row_base;
1848 }
1849
1850 for (; rr != nb_base_functions; ++rr)
1851 ++t_row_base;
1852
1853 ++t_w;
1854 ++t_normal;
1855 }
1856
1857 locMat *= OP::getMeasure();
1858 }
1859 }
1861}
1862
1864 return OP::iNtegrate(data);
1865}
1866
1868 EntData &col_data) {
1869 return OP::iNtegrate(row_data, col_data);
1870}
1871
1873 EntData &col_data) {
1874 return OP::iNtegrate(row_data, col_data);
1875}
1876
1877template <AssemblyType A>
1880
1881 double time = OP::getFEMethod()->ts_t;
1884 }
1885
1886 // get entity of face
1887 EntityHandle fe_ent = OP::getFEEntityHandle();
1888 // iterate over all boundary data
1889 for (auto &bc : (*bcDispPtr)) {
1890 // check if finite element entity is part of boundary condition
1891 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1892
1893 MatrixDouble analytical_expr;
1894 // placeholder to pass boundary block id to python
1895
1896 auto [block_name, v_analytical_expr] =
1897 getAnalyticalExpr(this, analytical_expr, bc.blockName);
1898
1899 int nb_dofs = data.getIndices().size();
1900
1901 int nb_integration_pts = OP::getGaussPts().size2();
1902 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1903 auto t_w = OP::getFTensor0IntegrationWeight();
1904 int nb_base_functions = data.getN().size2() / 3;
1905 auto t_row_base_fun = data.getFTensor1N<3>();
1906 auto t_coord = OP::getFTensor1CoordsAtGaussPts();
1907
1910
1911 // get bc data
1912 auto t_bc_disp = getFTensor1FromMat<3>(v_analytical_expr);
1913
1914 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1915 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1916
1917 int bb = 0;
1918 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1919 t_nf(i) +=
1920 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1921 ++t_nf;
1922 ++t_row_base_fun;
1923 }
1924 for (; bb != nb_base_functions; ++bb)
1925 ++t_row_base_fun;
1926
1927 ++t_bc_disp;
1928 ++t_coord;
1929 ++t_w;
1930 ++t_normal;
1931 }
1932 }
1933 }
1935}
1936
1938 return OP::iNtegrate(data);
1939}
1940
1943
1944 FTENSOR_INDEX(3, i);
1945
1946 int nb_dofs = data.getFieldData().size();
1947 int nb_integration_pts = getGaussPts().size2();
1948 int nb_base_functions = data.getN().size2();
1949
1950 double time = getFEMethod()->ts_t;
1953 }
1954
1955#ifndef NDEBUG
1956 if (this->locF.size() != nb_dofs)
1957 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1958 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
1959#endif // NDEBUG
1960
1961 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1963
1964 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
1965 auto t_row_base = data.getFTensor0N();
1966 auto t_w = getFTensor0IntegrationWeight();
1967 auto t_coords = getFTensor1CoordsAtGaussPts();
1968
1969 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
1970
1971 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1972
1973 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
1974 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
1975 int rr = 0;
1976 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1977 t_f(i) -= time_scale * t_w * t_row_base * tau * (t_val(i) * scale);
1978 ++t_row_base;
1979 ++t_f;
1980 }
1981
1982 for (; rr != nb_base_functions; ++rr)
1983 ++t_row_base;
1984 ++t_w;
1985 ++t_coords;
1986 }
1987 // Multiply by 2 since we integrate on triangle, and hybrid constrain is
1988 // multiplied by norm.
1989 this->locF *= 2. * getMeasure();
1991 };
1992
1993 // get entity of face
1994 EntityHandle fe_ent = getFEEntityHandle();
1995 for (auto &bc : *(bcData)) {
1996 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1997
1998 double time_scale = 1;
1999 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2000 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2001 }
2002
2003 int nb_dofs = data.getFieldData().size();
2004 if (nb_dofs) {
2005
2006 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
2007 auto calc_tau = [](double, double y, double) {
2008 y -= 44;
2009 y /= (60 - 44);
2010 return -y * (y - 1) / 0.25;
2011 };
2012 CHKERR integrate_rhs(bc, calc_tau, time_scale);
2013 } else {
2014 CHKERR integrate_rhs(
2015 bc, [](double, double, double) { return 1; }, time_scale);
2016 }
2017 }
2018 }
2019 }
2021}
2022
2025
2026 FTENSOR_INDEX(3, i);
2027
2028 int nb_dofs = data.getFieldData().size();
2029 int nb_integration_pts = getGaussPts().size2();
2030 int nb_base_functions = data.getN().size2();
2031
2032 double time = getFEMethod()->ts_t;
2035 }
2036
2037#ifndef NDEBUG
2038 if (this->locF.size() != nb_dofs)
2039 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2040 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
2041#endif // NDEBUG
2042
2043 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
2045
2046 auto val = bc.val;
2047 auto t_row_base = data.getFTensor0N();
2048 auto t_w = getFTensor0IntegrationWeight();
2049 auto t_coords = getFTensor1CoordsAtGaussPts();
2050 auto t_normal = getFTensor1NormalsAtGaussPts();
2051
2052 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2053
2054 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2055 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2056 auto t_val = FTensor::Tensor1<double, 3>();
2057 t_val(i) =
2058 (time_scale * t_w * tau * scale * val) * t_normal(i) / t_normal.l2();
2059
2060 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2061 int rr = 0;
2062 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2063 t_f(i) -= t_row_base * t_val(i);
2064 ++t_row_base;
2065 ++t_f;
2066 }
2067
2068 for (; rr != nb_base_functions; ++rr)
2069 ++t_row_base;
2070 ++t_w;
2071 ++t_coords;
2072 ++t_normal;
2073 }
2074 // Multiply by 2 since we integrate on triangle, and hybrid constrain is
2075 // multiplied by norm.
2076 this->locF *= 2. * getMeasure();
2078 };
2079
2080 // get entity of face
2081 EntityHandle fe_ent = getFEEntityHandle();
2082 for (auto &bc : *(bcData)) {
2083 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2084
2085 double time_scale = 1;
2086 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2087 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2088 }
2089
2090 int nb_dofs = data.getFieldData().size();
2091 if (nb_dofs) {
2092 CHKERR integrate_rhs(
2093 bc, [](double, double, double) { return 1; }, time_scale);
2094 }
2095 }
2096 }
2098}
2099
2102
2103 FTENSOR_INDEX(3, i);
2104
2105 int nb_dofs = data.getFieldData().size();
2106 int nb_integration_pts = getGaussPts().size2();
2107 int nb_base_functions = data.getN().size2();
2108
2109 double time = getFEMethod()->ts_t;
2112 }
2113
2114#ifndef NDEBUG
2115 if (this->locF.size() != nb_dofs)
2116 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2117 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
2118#endif // NDEBUG
2119
2120 // get entity of face
2121 EntityHandle fe_ent = getFEEntityHandle();
2122 for (auto &bc : *(bcData)) {
2123 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2124
2125 MatrixDouble analytical_expr;
2126 // placeholder to pass boundary block id to python
2127 auto [block_name, v_analytical_expr] =
2128 getAnalyticalExpr(this, analytical_expr, bc.blockName);
2129 auto t_val =
2130 getFTensor1FromMat<3>(v_analytical_expr);
2131 auto t_row_base = data.getFTensor0N();
2132 auto t_w = getFTensor0IntegrationWeight();
2133 auto t_coords = getFTensor1CoordsAtGaussPts();
2134
2135 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2136
2137 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2138
2139 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2140 int rr = 0;
2141 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2142 t_f(i) -= t_w * t_row_base * (t_val(i) * scale);
2143 ++t_row_base;
2144 ++t_f;
2145 }
2146
2147 for (; rr != nb_base_functions; ++rr)
2148 ++t_row_base;
2149 ++t_w;
2150 ++t_coords;
2151 ++t_val;
2152 }
2153 // Multiply by 2 since we integrate on triangle, and hybrid constrain is
2154 // multiplied by norm.
2155 this->locF *= 2. * getMeasure();
2156 }
2157 }
2159}
2160
2162 EntData &col_data) {
2164 int nb_integration_pts = row_data.getN().size1();
2165 int row_nb_dofs = row_data.getIndices().size();
2166 int col_nb_dofs = col_data.getIndices().size();
2167 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2169 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2));
2170 };
2171 FTensor::Index<'i', 3> i;
2172 auto v = getVolume();
2173 auto t_w = getFTensor0IntegrationWeight();
2174 int row_nb_base_functions = row_data.getN().size2();
2175 auto t_row_base_fun = row_data.getFTensor0N();
2176 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2177 double a = v * t_w;
2178 int rr = 0;
2179 for (; rr != row_nb_dofs / 3; ++rr) {
2180 auto t_col_diff_base_fun = col_data.getFTensor2DiffN<3, 3>(gg, 0);
2181 auto t_m = get_ftensor1(K, 3 * rr, 0);
2182 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2183 double div_col_base = t_col_diff_base_fun(i, i);
2184 t_m(i) -= a * t_row_base_fun * div_col_base;
2185 ++t_m;
2186 ++t_col_diff_base_fun;
2187 }
2188 ++t_row_base_fun;
2189 }
2190 for (; rr != row_nb_base_functions; ++rr)
2191 ++t_row_base_fun;
2192 ++t_w;
2193 }
2195}
2196
2198 EntData &col_data) {
2200
2201 if (alphaW < std::numeric_limits<double>::epsilon() &&
2202 alphaRho < std::numeric_limits<double>::epsilon())
2204
2205 const int nb_integration_pts = row_data.getN().size1();
2206 const int row_nb_dofs = row_data.getIndices().size();
2207 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2209 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2)
2210
2211 );
2212 };
2213 FTensor::Index<'i', 3> i;
2214
2215 auto v = getVolume();
2216 auto t_w = getFTensor0IntegrationWeight();
2217
2218 auto piola_scale = dataAtPts->piolaScale;
2219 auto alpha_w = alphaW / piola_scale;
2220 auto alpha_rho = alphaRho / piola_scale;
2221
2222 int row_nb_base_functions = row_data.getN().size2();
2223 auto t_row_base_fun = row_data.getFTensor0N();
2224
2225 double ts_scale = alpha_w * getTSa();
2226 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon())
2227 ts_scale += alpha_rho * getTSaa();
2228
2229 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2230 double a = v * t_w * ts_scale;
2231
2232 int rr = 0;
2233 for (; rr != row_nb_dofs / 3; ++rr) {
2234
2235 auto t_col_base_fun = row_data.getFTensor0N(gg, 0);
2236 auto t_m = get_ftensor1(K, 3 * rr, 0);
2237 for (int cc = 0; cc != row_nb_dofs / 3; ++cc) {
2238 const double b = a * t_row_base_fun * t_col_base_fun;
2239 t_m(i) += b;
2240 ++t_m;
2241 ++t_col_base_fun;
2242 }
2243
2244 ++t_row_base_fun;
2245 }
2246
2247 for (; rr != row_nb_base_functions; ++rr)
2248 ++t_row_base_fun;
2249
2250 ++t_w;
2251 }
2252
2254}
2255
2257 EntData &col_data) {
2259
2265
2266 int nb_integration_pts = row_data.getN().size1();
2267 int row_nb_dofs = row_data.getIndices().size();
2268 int col_nb_dofs = col_data.getIndices().size();
2269 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
2271
2272 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2273
2274 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2275
2276 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
2277
2278 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
2279
2280 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
2281
2282 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2));
2283 };
2284
2285 auto v = getVolume();
2286 auto t_w = getFTensor0IntegrationWeight();
2287
2288 int row_nb_base_functions = row_data.getN().size2();
2289 auto t_row_base_fun = row_data.getFTensor0N();
2290
2291 auto t_approx_P_adjoint_log_du_dP =
2292 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
2293
2294 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2295 double a = v * t_w;
2296 int rr = 0;
2297 for (; rr != row_nb_dofs / 6; ++rr) {
2298
2299 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
2300 auto t_m = get_ftensor3(K, 6 * rr, 0);
2301
2302 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2303 t_m(L, i) -=
2304 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(j)) *
2305 t_row_base_fun;
2306 ++t_col_base_fun;
2307 ++t_m;
2308 }
2309
2310 ++t_row_base_fun;
2311 }
2312 for (; rr != row_nb_base_functions; ++rr)
2313 ++t_row_base_fun;
2314 ++t_w;
2315 ++t_approx_P_adjoint_log_du_dP;
2316 }
2317
2319}
2320
2322 EntData &col_data) {
2324
2330
2331 int nb_integration_pts = row_data.getN().size1();
2332 int row_nb_dofs = row_data.getIndices().size();
2333 int col_nb_dofs = col_data.getIndices().size();
2334 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2336 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c), &m(r + 3, c), &m(r + 4, c),
2337 &m(r + 5, c));
2338 };
2339
2340 auto v = getVolume();
2341 auto t_w = getFTensor0IntegrationWeight();
2342 auto t_row_base_fun = row_data.getFTensor0N();
2343
2344 int row_nb_base_functions = row_data.getN().size2();
2345
2346 auto t_approx_P_adjoint_log_du_dP =
2347 getFTensor3FromMat<3, 3, size_symm>(dataAtPts->adjointPdUdPAtPts);
2348
2349 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2350 double a = v * t_w;
2351 int rr = 0;
2352 for (; rr != row_nb_dofs / 6; ++rr) {
2353 auto t_m = get_ftensor2(K, 6 * rr, 0);
2354 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
2355 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2356 t_m(L) -=
2357 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(i, j)) *
2358 t_row_base_fun;
2359 ++t_m;
2360 ++t_col_base_fun;
2361 }
2362 ++t_row_base_fun;
2363 }
2364 for (; rr != row_nb_base_functions; ++rr)
2365 ++t_row_base_fun;
2366 ++t_w;
2367 ++t_approx_P_adjoint_log_du_dP;
2368 }
2370}
2371
2373 EntData &col_data) {
2375
2377 auto t_L = symm_L_tensor();
2378
2379 int row_nb_dofs = row_data.getIndices().size();
2380 int col_nb_dofs = col_data.getIndices().size();
2381 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
2383
2384 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2385
2386 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2387
2388 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
2389
2390 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
2391
2392 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
2393
2394 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2)
2395
2396 );
2397 };
2398 FTensor::Index<'i', 3> i;
2399 FTensor::Index<'j', 3> j;
2400 FTensor::Index<'k', 3> k;
2401 FTensor::Index<'m', 3> m;
2402 FTensor::Index<'n', 3> n;
2403
2404 auto v = getVolume();
2405 auto t_w = getFTensor0IntegrationWeight();
2406 auto t_approx_P_adjoint_log_du_domega =
2407 getFTensor2FromMat<3, size_symm>(dataAtPts->adjointPdUdOmegaAtPts);
2408
2409 int row_nb_base_functions = row_data.getN().size2();
2410 auto t_row_base_fun = row_data.getFTensor0N();
2411
2412 int nb_integration_pts = row_data.getN().size1();
2413
2414 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2415 double a = v * t_w;
2416
2417 int rr = 0;
2418 for (; rr != row_nb_dofs / 6; ++rr) {
2419 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2420 auto t_m = get_ftensor3(K, 6 * rr, 0);
2421 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2422 double v = a * t_row_base_fun * t_col_base_fun;
2423 t_m(L, k) -= v * t_approx_P_adjoint_log_du_domega(k, L);
2424 ++t_m;
2425 ++t_col_base_fun;
2426 }
2427 ++t_row_base_fun;
2428 }
2429
2430 for (; rr != row_nb_base_functions; ++rr)
2431 ++t_row_base_fun;
2432
2433 ++t_w;
2434 ++t_approx_P_adjoint_log_du_domega;
2435 }
2436
2438}
2439
2441 EntData &col_data) {
2443 int nb_integration_pts = getGaussPts().size2();
2444 int row_nb_dofs = row_data.getIndices().size();
2445 int col_nb_dofs = col_data.getIndices().size();
2446 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2448 size_symm>{
2449
2450 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2), &m(r + 0, c + 3),
2451 &m(r + 0, c + 4), &m(r + 0, c + 5),
2452
2453 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2), &m(r + 1, c + 3),
2454 &m(r + 1, c + 4), &m(r + 1, c + 5),
2455
2456 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2), &m(r + 2, c + 3),
2457 &m(r + 2, c + 4), &m(r + 2, c + 5)
2458
2459 };
2460 };
2461
2464
2465 auto v = getVolume();
2466 auto t_w = getFTensor0IntegrationWeight();
2467 auto t_levi_kirchhoff_du = getFTensor2FromMat<3, size_symm>(
2468 dataAtPts->leviKirchhoffdLogStreatchAtPts);
2469 int row_nb_base_functions = row_data.getN().size2();
2470 auto t_row_base_fun = row_data.getFTensor0N();
2471 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2472 double a = v * t_w;
2473 int rr = 0;
2474 for (; rr != row_nb_dofs / 3; ++rr) {
2475 auto t_m = get_ftensor2(K, 3 * rr, 0);
2476 const double b = a * t_row_base_fun;
2477 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2478 for (int cc = 0; cc != col_nb_dofs / size_symm; ++cc) {
2479 t_m(k, L) -= (b * t_col_base_fun) * t_levi_kirchhoff_du(k, L);
2480 ++t_m;
2481 ++t_col_base_fun;
2482 }
2483 ++t_row_base_fun;
2484 }
2485 for (; rr != row_nb_base_functions; ++rr) {
2486 ++t_row_base_fun;
2487 }
2488 ++t_w;
2489 ++t_levi_kirchhoff_du;
2490 }
2492}
2493
2495 EntData &col_data) {
2497
2504
2505 int nb_integration_pts = getGaussPts().size2();
2506 int row_nb_dofs = row_data.getIndices().size();
2507 int col_nb_dofs = col_data.getIndices().size();
2508 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2510
2511 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2512
2513 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2514
2515 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2516
2517 );
2518 };
2519
2520 auto v = getVolume();
2521 auto t_w = getFTensor0IntegrationWeight();
2522
2523 int row_nb_base_functions = row_data.getN().size2();
2524 auto t_row_base_fun = row_data.getFTensor0N();
2525 auto t_levi_kirchhoff_dP =
2526 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
2527
2528 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2529 double a = v * t_w;
2530 int rr = 0;
2531 for (; rr != row_nb_dofs / 3; ++rr) {
2532 double b = a * t_row_base_fun;
2533 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
2534 auto t_m = get_ftensor2(K, 3 * rr, 0);
2535 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2536 t_m(m, i) -= b * (t_levi_kirchhoff_dP(m, i, k) * t_col_base_fun(k));
2537 ++t_m;
2538 ++t_col_base_fun;
2539 }
2540 ++t_row_base_fun;
2541 }
2542 for (; rr != row_nb_base_functions; ++rr) {
2543 ++t_row_base_fun;
2544 }
2545
2546 ++t_w;
2547 ++t_levi_kirchhoff_dP;
2548 }
2550}
2551
2553 EntData &col_data) {
2555 int nb_integration_pts = getGaussPts().size2();
2556 int row_nb_dofs = row_data.getIndices().size();
2557 int col_nb_dofs = col_data.getIndices().size();
2558
2559 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2561 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c));
2562 };
2563
2564 FTENSOR_INDEX(3, i);
2565 FTENSOR_INDEX(3, k);
2566 FTENSOR_INDEX(3, m);
2567
2568 auto v = getVolume();
2569 auto t_w = getFTensor0IntegrationWeight();
2570 auto t_levi_kirchoff_dP =
2571 getFTensor3FromMat<3, 3, 3>(dataAtPts->leviKirchhoffPAtPts);
2572
2573 int row_nb_base_functions = row_data.getN().size2();
2574 auto t_row_base_fun = row_data.getFTensor0N();
2575
2576 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2577 double a = v * t_w;
2578 int rr = 0;
2579 for (; rr != row_nb_dofs / 3; ++rr) {
2580 double b = a * t_row_base_fun;
2581 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
2582 auto t_m = get_ftensor1(K, 3 * rr, 0);
2583 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2584 t_m(m) -= b * (t_levi_kirchoff_dP(m, i, k) * t_col_base_fun(i, k));
2585 ++t_m;
2586 ++t_col_base_fun;
2587 }
2588 ++t_row_base_fun;
2589 }
2590
2591 for (; rr != row_nb_base_functions; ++rr) {
2592 ++t_row_base_fun;
2593 }
2594 ++t_w;
2595 ++t_levi_kirchoff_dP;
2596 }
2598}
2599
2601 EntData &col_data) {
2603 int nb_integration_pts = getGaussPts().size2();
2604 int row_nb_dofs = row_data.getIndices().size();
2605 int col_nb_dofs = col_data.getIndices().size();
2606 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2608
2609 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2610
2611 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2612
2613 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2614
2615 );
2616 };
2617 FTensor::Index<'i', 3> i;
2618 FTensor::Index<'j', 3> j;
2619 FTensor::Index<'k', 3> k;
2620 FTensor::Index<'l', 3> l;
2621 FTensor::Index<'m', 3> m;
2622 FTensor::Index<'n', 3> n;
2623
2625
2626 auto v = getVolume();
2627 auto ts_a = getTSa();
2628 auto t_w = getFTensor0IntegrationWeight();
2629 auto t_levi_kirchhoff_domega =
2630 getFTensor2FromMat<3, 3>(dataAtPts->leviKirchhoffdOmegaAtPts);
2631 int row_nb_base_functions = row_data.getN().size2();
2632 auto t_row_base_fun = row_data.getFTensor0N();
2633 auto t_row_grad_fun = row_data.getFTensor1DiffN<3>();
2634 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2635 double a = v * t_w;
2636 double c = a * alphaOmega * ts_a;
2637 int rr = 0;
2638 for (; rr != row_nb_dofs / 3; ++rr) {
2639 auto t_m = get_ftensor2(K, 3 * rr, 0);
2640 const double b = a * t_row_base_fun;
2641 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2642 auto t_col_grad_fun = col_data.getFTensor1DiffN<3>(gg, 0);
2643 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2644 t_m(k, l) -= (b * t_col_base_fun) * t_levi_kirchhoff_domega(k, l);
2645 t_m(k, l) += t_kd(k, l) * (c * (t_row_grad_fun(i) * t_col_grad_fun(i)));
2646 ++t_m;
2647 ++t_col_base_fun;
2648 ++t_col_grad_fun;
2649 }
2650 ++t_row_base_fun;
2651 ++t_row_grad_fun;
2652 }
2653 for (; rr != row_nb_base_functions; ++rr) {
2654 ++t_row_base_fun;
2655 ++t_row_grad_fun;
2656 }
2657 ++t_w;
2658 ++t_levi_kirchhoff_domega;
2659 }
2661}
2662
2664 EntData &col_data) {
2666 if (dataAtPts->matInvD.size1() == size_symm &&
2667 dataAtPts->matInvD.size2() == size_symm) {
2668 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2669 } else {
2670 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2671 }
2673};
2674
2675template <int S>
2677 EntData &col_data) {
2679
2680 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2682
2683 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2684
2685 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2686
2687 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2688
2689 );
2690 };
2691
2692 int nb_integration_pts = getGaussPts().size2();
2693 int row_nb_dofs = row_data.getIndices().size();
2694 int col_nb_dofs = col_data.getIndices().size();
2695
2696 auto v = getVolume();
2697 auto t_w = getFTensor0IntegrationWeight();
2698 int row_nb_base_functions = row_data.getN().size2() / 3;
2699
2704
2705 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2706 &*dataAtPts->matInvD.data().begin());
2707
2708 auto t_row_base = row_data.getFTensor1N<3>();
2709 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2710 double a = v * t_w;
2711
2712 int rr = 0;
2713 for (; rr != row_nb_dofs / 3; ++rr) {
2714 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2715 auto t_m = get_ftensor2(K, 3 * rr, 0);
2716 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2717 t_m(i, k) -= a * t_row_base(j) * (t_inv_D(i, j, k, l) * t_col_base(l));
2718 ++t_m;
2719 ++t_col_base;
2720 }
2721
2722 ++t_row_base;
2723 }
2724
2725 for (; rr != row_nb_base_functions; ++rr)
2726 ++t_row_base;
2727
2728 ++t_w;
2729 ++t_inv_D;
2730 }
2732}
2733
2736 EntData &col_data) {
2738 if (dataAtPts->matInvD.size1() == size_symm &&
2739 dataAtPts->matInvD.size2() == size_symm) {
2740 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2741 } else {
2742 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2743 }
2745};
2746
2747template <int S>
2750 EntData &col_data) {
2752
2753 int nb_integration_pts = getGaussPts().size2();
2754 int row_nb_dofs = row_data.getIndices().size();
2755 int col_nb_dofs = col_data.getIndices().size();
2756
2757 auto v = getVolume();
2758 auto t_w = getFTensor0IntegrationWeight();
2759 int row_nb_base_functions = row_data.getN().size2() / 9;
2760
2765
2766 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2767 &*dataAtPts->matInvD.data().begin());
2768
2769 auto t_row_base = row_data.getFTensor2N<3, 3>();
2770 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2771 double a = v * t_w;
2772
2773 int rr = 0;
2774 for (; rr != row_nb_dofs; ++rr) {
2775 auto t_col_base = col_data.getFTensor2N<3, 3>(gg, 0);
2776 for (int cc = 0; cc != col_nb_dofs; ++cc) {
2777 K(rr, cc) -=
2778 a * (t_row_base(i, j) * (t_inv_D(i, j, k, l) * t_col_base(k, l)));
2779 ++t_col_base;
2780 }
2781
2782 ++t_row_base;
2783 }
2784
2785 for (; rr != row_nb_base_functions; ++rr)
2786 ++t_row_base;
2787 ++t_w;
2788 ++t_inv_D;
2789 }
2791}
2792
2794 EntData &col_data) {
2796 if (dataAtPts->matInvD.size1() == size_symm &&
2797 dataAtPts->matInvD.size2() == size_symm) {
2798 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
2799 } else {
2800 MoFEMFunctionReturnHot(integrateImpl<size_symm>(row_data, col_data));
2801 }
2803};
2804
2805template <int S>
2808 EntData &col_data) {
2810
2811 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2813
2814 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2)
2815
2816 );
2817 };
2818
2819 int nb_integration_pts = getGaussPts().size2();
2820 int row_nb_dofs = row_data.getIndices().size();
2821 int col_nb_dofs = col_data.getIndices().size();
2822
2823 auto v = getVolume();
2824 auto t_w = getFTensor0IntegrationWeight();
2825 int row_nb_base_functions = row_data.getN().size2() / 9;
2826
2833
2834 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, S>(
2835 &*dataAtPts->matInvD.data().begin());
2836
2837 auto t_row_base = row_data.getFTensor2N<3, 3>();
2838 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2839 double a = v * t_w;
2840
2841 auto t_m = get_ftensor1(K, 0, 0);
2842
2843 int rr = 0;
2844 for (; rr != row_nb_dofs; ++rr) {
2845 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2846 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2847 t_m(k) -= a * (t_row_base(i, j) * t_inv_D(i, j, k, l)) * t_col_base(l);
2848 ++t_col_base;
2849 ++t_m;
2850 }
2851
2852 ++t_row_base;
2853 }
2854
2855 for (; rr != row_nb_base_functions; ++rr)
2856 ++t_row_base;
2857 ++t_w;
2858 ++t_inv_D;
2859 }
2861}
2862
2864 EntData &col_data) {
2866
2873
2874 int nb_integration_pts = row_data.getN().size1();
2875 int row_nb_dofs = row_data.getIndices().size();
2876 int col_nb_dofs = col_data.getIndices().size();
2877
2878 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2880
2881 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
2882
2883 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
2884
2885 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
2886
2887 );
2888 };
2889
2890 auto v = getVolume();
2891 auto t_w = getFTensor0IntegrationWeight();
2892 int row_nb_base_functions = row_data.getN().size2() / 3;
2893 auto t_row_base_fun = row_data.getFTensor1N<3>();
2894
2895 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
2896 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2897 double a = v * t_w;
2898
2899 int rr = 0;
2900 for (; rr != row_nb_dofs / 3; ++rr) {
2901
2903 t_PRT(i, k) = t_row_base_fun(j) * t_h_domega(i, j, k);
2904
2905 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2906 auto t_m = get_ftensor2(K, 3 * rr, 0);
2907 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2908 t_m(i, j) -= (a * t_col_base_fun) * t_PRT(i, j);
2909 ++t_m;
2910 ++t_col_base_fun;
2911 }
2912
2913 ++t_row_base_fun;
2914 }
2915
2916 for (; rr != row_nb_base_functions; ++rr)
2917 ++t_row_base_fun;
2918 ++t_w;
2919 ++t_h_domega;
2920 }
2922}
2923
2926 EntData &col_data) {
2928
2935
2936 int nb_integration_pts = row_data.getN().size1();
2937 int row_nb_dofs = row_data.getIndices().size();
2938 int col_nb_dofs = col_data.getIndices().size();
2939
2940 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
2942 &m(r, c + 0), &m(r, c + 1), &m(r, c + 2));
2943 };
2944
2945 auto v = getVolume();
2946 auto t_w = getFTensor0IntegrationWeight();
2947 int row_nb_base_functions = row_data.getN().size2() / 9;
2948 auto t_row_base_fun = row_data.getFTensor2N<3, 3>();
2949
2950 auto t_h_domega = getFTensor3FromMat<3, 3, 3>(dataAtPts->hdOmegaAtPts);
2951 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2952 double a = v * t_w;
2953
2954 int rr = 0;
2955 for (; rr != row_nb_dofs; ++rr) {
2956
2958 t_PRT(k) = t_row_base_fun(i, j) * t_h_domega(i, j, k);
2959
2960 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2961 auto t_m = get_ftensor2(K, rr, 0);
2962 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2963 t_m(j) -= (a * t_col_base_fun) * t_PRT(j);
2964 ++t_m;
2965 ++t_col_base_fun;
2966 }
2967
2968 ++t_row_base_fun;
2969 }
2970
2971 for (; rr != row_nb_base_functions; ++rr)
2972 ++t_row_base_fun;
2973
2974 ++t_w;
2975 ++t_h_domega;
2976 }
2978}
2979
2981 EntData &data) {
2983
2984 if (tagSense != getSkeletonSense())
2986
2987 auto get_tag = [&](auto name) {
2988 auto &mob = getPtrFE()->mField.get_moab();
2989 Tag tag;
2990 CHK_MOAB_THROW(mob.tag_get_handle(name, tag), "get tag");
2991 return tag;
2992 };
2993
2994 auto get_tag_value = [&](auto &&tag, int dim) {
2995 auto &mob = getPtrFE()->mField.get_moab();
2996 auto face = getSidePtrFE()->getFEEntityHandle();
2997 std::vector<double> value(dim);
2998 CHK_MOAB_THROW(mob.tag_get_data(tag, &face, 1, value.data()), "set tag");
2999 return value;
3000 };
3001
3002 auto create_tag = [this](const std::string tag_name, const int size) {
3003 double def_VAL[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
3004 Tag th;
3005 CHKERR postProcMesh.tag_get_handle(tag_name.c_str(), size, MB_TYPE_DOUBLE,
3006 th, MB_TAG_CREAT | MB_TAG_SPARSE,
3007 def_VAL);
3008 return th;
3009 };
3010
3011 Tag th_cauchy_streess = create_tag("CauchyStress", 9);
3012 Tag th_detF = create_tag("detF", 1);
3013 Tag th_traction = create_tag("traction", 3);
3014 Tag th_disp_error = create_tag("DisplacementError", 1);
3015
3016 Tag th_energy = create_tag("Energy", 1);
3017
3018 auto t_w = getFTensor1FromMat<3>(dataAtPts->wL2AtPts);
3019 auto t_h = getFTensor2FromMat<3, 3>(dataAtPts->hAtPts);
3020 auto t_approx_P = getFTensor2FromMat<3, 3>(dataAtPts->approxPAtPts);
3021
3022 auto t_normal = getFTensor1NormalsAtGaussPts();
3023 auto t_disp = getFTensor1FromMat<3>(dataAtPts->wH1AtPts);
3024
3025 auto next = [&]() {
3026 ++t_w;
3027 ++t_h;
3028 ++t_approx_P;
3029 ++t_normal;
3030 ++t_disp;
3031 };
3032
3033 if (dataAtPts->energyAtPts.size() == 0) {
3034 // that is for case that energy is not calculated
3035 dataAtPts->energyAtPts.resize(getGaussPts().size2());
3036 dataAtPts->energyAtPts.clear();
3037 }
3038 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
3039
3040 FTensor::Index<'i', 3> i;
3041 FTensor::Index<'j', 3> j;
3042 FTensor::Index<'k', 3> k;
3043 FTensor::Index<'l', 3> l;
3044
3045 auto set_float_precision = [](const double x) {
3046 if (std::abs(x) < std::numeric_limits<float>::epsilon())
3047 return 0.;
3048 else
3049 return x;
3050 };
3051
3052 // scalars
3053 auto save_scal_tag = [&](auto &th, auto v, const int gg) {
3055 v = set_float_precision(v);
3056 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1, &v);
3058 };
3059
3060 // vectors
3061 VectorDouble3 v(3);
3062 FTensor::Tensor1<FTensor::PackPtr<double *, 0>, 3> t_v(&v[0], &v[1], &v[2]);
3063 auto save_vec_tag = [&](auto &th, auto &t_d, const int gg) {
3065 t_v(i) = t_d(i);
3066 for (auto &a : v.data())
3067 a = set_float_precision(a);
3068 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
3069 &*v.data().begin());
3071 };
3072
3073 // tensors
3074
3075 MatrixDouble3by3 m(3, 3);
3077 &m(0, 0), &m(0, 1), &m(0, 2),
3078
3079 &m(1, 0), &m(1, 1), &m(1, 2),
3080
3081 &m(2, 0), &m(2, 1), &m(2, 2));
3082
3083 auto save_mat_tag = [&](auto &th, auto &t_d, const int gg) {
3085 t_m(i, j) = t_d(i, j);
3086 for (auto &v : m.data())
3087 v = set_float_precision(v);
3088 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
3089 &*m.data().begin());
3091 };
3092
3093 const auto nb_gauss_pts = getGaussPts().size2();
3094 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
3095
3096 FTensor::Tensor1<double, 3> t_traction;
3097 t_traction(i) = t_approx_P(i, j) * t_normal(j) / t_normal.l2();
3098 // vectors
3099 CHKERR save_vec_tag(th_traction, t_traction, gg);
3100
3101 double u_error = sqrt((t_disp(i) - t_w(i)) * (t_disp(i) - t_w(i)));
3102 CHKERR save_scal_tag(th_disp_error, u_error, gg);
3103 CHKERR save_scal_tag(th_energy, t_energy, gg);
3104
3105 const double jac = determinantTensor3by3(t_h);
3107 t_cauchy(i, j) = (1. / jac) * (t_approx_P(i, k) * t_h(j, k));
3108 CHKERR save_mat_tag(th_cauchy_streess, t_cauchy, gg);
3109 CHKERR postProcMesh.tag_set_data(th_detF, &mapGaussPts[gg], 1, &jac);
3110
3111 next();
3112 }
3113
3115}
3116
3118 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3119 std::vector<FieldSpace> spaces, std::string geom_field_name,
3120 boost::shared_ptr<Range> crack_front_edges_ptr) {
3122
3123 constexpr bool scale_l2 = false;
3124
3125 if (scale_l2) {
3126
3128 : public MoFEM::OpGetHONormalsOnFace<SPACE_DIM> {
3129
3131
3132 OpGetHONormalsOnFace(std::string &field_name,
3133 boost::shared_ptr<Range> edges_ptr)
3134 : OP(field_name), edgesPtr(edges_ptr) {}
3135
3136 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
3137
3138 auto ent = data.getFieldEntities().size()
3139 ? data.getFieldEntities()[0]->getEnt()
3140 : 0;
3141
3142 if (type == MBEDGE && edgesPtr->find(ent) != edgesPtr->end()) {
3143 return 0;
3144 } else {
3145 return OP::doWork(side, type, data);
3146 }
3147 };
3148
3149 private:
3150 boost::shared_ptr<Range> edgesPtr;
3151 };
3152
3153 auto jac = boost::make_shared<MatrixDouble>();
3154 auto det = boost::make_shared<VectorDouble>();
3155 pipeline.push_back(new OpGetHONormalsOnFace(
3156 geom_field_name, EshelbianCore::setSingularity
3157 ? crack_front_edges_ptr
3158 : boost::make_shared<Range>()));
3159 pipeline.push_back(new OpCalculateHOJacForFaceEmbeddedIn3DSpace(jac));
3160 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3161 pipeline.push_back(new OpScaleBaseBySpaceInverseOfMeasure(
3163 }
3164
3165 CHKERR MoFEM::AddHOOps<2, 3, 3>::add(pipeline, spaces, geom_field_name);
3166
3168}
3169
3171 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3172 std::vector<FieldSpace> spaces, std::string geom_field_name,
3173 boost::shared_ptr<Range> crack_front_edges_ptr) {
3175
3176 constexpr bool scale_l2 = false;
3177
3178 if (scale_l2) {
3179 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3180 "Scale L2 Ainsworth Legendre base is not implemented");
3181 }
3182
3183 CHKERR MoFEM::AddHOOps<2, 2, 3>::add(pipeline, spaces, geom_field_name);
3184
3186}
3187
3189 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
3190 std::vector<FieldSpace> spaces, std::string geom_field_name,
3191 boost::shared_ptr<Range> crack_front_edges_ptr) {
3193
3195 auto jac = boost::make_shared<MatrixDouble>();
3196 auto det = boost::make_shared<VectorDouble>();
3198 geom_field_name, jac));
3199 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3200 pipeline.push_back(
3202 }
3203
3204 constexpr bool scale_l2_ainsworth_legendre_base = false;
3205
3206 if (scale_l2_ainsworth_legendre_base) {
3207
3209 : public MoFEM::OpCalculateVectorFieldGradient<SPACE_DIM, SPACE_DIM> {
3210
3212
3213 OpCalculateVectorFieldGradient(const std::string &field_name,
3214 boost::shared_ptr<MatrixDouble> jac,
3215 boost::shared_ptr<Range> edges_ptr)
3216 : OP(field_name, jac), edgesPtr(edges_ptr) {}
3217
3218 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
3219
3220 auto ent = data.getFieldEntities().size()
3221 ? data.getFieldEntities()[0]->getEnt()
3222 : 0;
3223
3224 if (type == MBEDGE && edgesPtr->find(ent) != edgesPtr->end()) {
3225 return 0;
3226 } else {
3227 return OP::doWork(side, type, data);
3228 }
3229 };
3230
3231 private:
3232 boost::shared_ptr<Range> edgesPtr;
3233 };
3234
3235 auto jac = boost::make_shared<MatrixDouble>();
3236 auto det = boost::make_shared<VectorDouble>();
3237 pipeline.push_back(new OpCalculateVectorFieldGradient(
3238 geom_field_name, jac,
3239 EshelbianCore::setSingularity ? crack_front_edges_ptr
3240 : boost::make_shared<Range>()));
3241 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
3242 pipeline.push_back(new OpScaleBaseBySpaceInverseOfMeasure(
3244 }
3245
3246 CHKERR MoFEM::AddHOOps<3, 3, 3>::add(pipeline, spaces, geom_field_name,
3247 nullptr, nullptr, nullptr);
3248
3250}
3251
3253 EntData &data) {
3255
3261
3262 dataAtPts->faceMaterialForceAtPts.resize(3, getGaussPts().size2(), false);
3263 dataAtPts->normalPressureAtPts.resize(getGaussPts().size2(), false);
3264 if (getNinTheLoop() == 0) {
3265 dataAtPts->faceMaterialForceAtPts.clear();
3266 dataAtPts->normalPressureAtPts.clear();
3267 }
3268 auto loop_size = getLoopSize();
3269 if (loop_size == 1) {
3270 auto numebered_fe_ptr = getSidePtrFE()->numeredEntFiniteElementPtr;
3271 auto pstatus = numebered_fe_ptr->getPStatus();
3272 if (pstatus & (PSTATUS_SHARED | PSTATUS_MULTISHARED)) {
3273 loop_size = 2;
3274 }
3275 }
3276
3278
3279 auto t_normal = getFTensor1NormalsAtGaussPts();
3280 auto t_T = getFTensor1FromMat<SPACE_DIM>(
3281 dataAtPts->faceMaterialForceAtPts); //< face material force
3282 auto t_p =
3283 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
3284 auto t_P = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->approxPAtPts);
3285 auto t_grad_u_gamma =
3286 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->gradHybridDispAtPts);
3287 auto t_strain =
3288 getFTensor2SymmetricFromMat<SPACE_DIM>(dataAtPts->logStretchTensorAtPts);
3289
3291 case GRIFFITH_FORCE:
3292 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3294 t_N(I) = t_normal(I);
3295 t_N.normalize();
3296
3298 t_grad_u(i, j) =
3299 (t_grad_u_gamma(i, j) - t_grad_u_gamma(j, i)) / 2. + t_strain(i, j);
3300 t_T(I) += t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
3301 // note that works only for Hooke material,
3302 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2) / loop_size;
3303
3304 t_p += t_N(I) *
3305 (t_N(J) * ((t_kd(i, I) + t_grad_u_gamma(i, I)) * t_P(i, J))) /
3306 loop_size;
3307
3308 ++t_normal;
3309 ++t_P;
3310 ++t_grad_u_gamma;
3311 ++t_strain;
3312 ++t_T;
3313 ++t_p;
3314 }
3315 break;
3316 case GRIFFITH_SKELETON:
3317 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3319 t_N(I) = t_normal(I);
3320 t_N.normalize();
3321
3322 t_T(I) += t_N(J) * (t_grad_u_gamma(i, I) * t_P(i, J)) / loop_size;
3323
3324 t_p += t_N(I) *
3325 (t_N(J) * ((t_kd(i, I) + t_grad_u_gamma(i, I)) * t_P(i, J))) /
3326 loop_size;
3327
3328 ++t_normal;
3329 ++t_P;
3330 ++t_grad_u_gamma;
3331 ++t_T;
3332 ++t_p;
3333 }
3334 break;
3335
3336 default:
3337 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3338 "Grffith energy release "
3339 "selector not implemented");
3340 };
3341
3342#ifndef NDEBUG
3343 auto side_fe_ptr = getSidePtrFE();
3344 auto side_fe_mi_ptr = side_fe_ptr->numeredEntFiniteElementPtr;
3345 auto pstatus = side_fe_mi_ptr->getPStatus();
3346 if (pstatus) {
3347 auto owner = side_fe_mi_ptr->getOwnerProc();
3348 MOFEM_LOG("SELF", Sev::noisy)
3349 << "OpFaceSideMaterialForce: owner proc is not 0, owner proc: " << owner
3350 << " " << getPtrFE()->mField.get_comm_rank() << " n in the loop "
3351 << getNinTheLoop() << " loop size " << getLoopSize();
3352 }
3353#endif // NDEBUG
3354
3356}
3357
3359 EntData &data) {
3361
3362#ifndef NDEBUG
3363 auto fe_mi_ptr = getFEMethod()->numeredEntFiniteElementPtr;
3364 auto pstatus = fe_mi_ptr->getPStatus();
3365 if (pstatus) {
3366 auto owner = fe_mi_ptr->getOwnerProc();
3367 MOFEM_LOG("SELF", Sev::noisy)
3368 << "OpFaceMaterialForce: owner proc is not 0, owner proc: " << owner
3369 << " " << getPtrFE()->mField.get_comm_rank();
3370 }
3371#endif // NDEBUG
3372
3374
3376 t_face_T(I) = 0.;
3377 double face_pressure = 0.;
3378 auto t_T = getFTensor1FromMat<SPACE_DIM>(
3379 dataAtPts->faceMaterialForceAtPts); //< face material force
3380 auto t_p =
3381 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
3382 auto t_w = getFTensor0IntegrationWeight();
3383 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
3384 t_face_T(I) += t_w * t_T(I);
3385 face_pressure += t_w * t_p;
3386 ++t_w;
3387 ++t_T;
3388 ++t_p;
3389 }
3390 t_face_T(I) *= getMeasure();
3391 face_pressure *= getMeasure();
3392
3393 auto get_tag = [&](auto name, auto dim) {
3394 auto &moab = getPtrFE()->mField.get_moab();
3395 Tag tag;
3396 double def_val[] = {0., 0., 0.};
3397 CHK_MOAB_THROW(moab.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
3398 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
3399 "create tag");
3400 return tag;
3401 };
3402
3403 auto set_tag = [&](auto &&tag, auto ptr) {
3404 auto &moab = getPtrFE()->mField.get_moab();
3405 auto face = getPtrFE()->getFEEntityHandle();
3406 CHK_MOAB_THROW(moab.tag_set_data(tag, &face, 1, ptr), "set tag");
3407 };
3408
3409 set_tag(get_tag("MaterialForce", 3), &t_face_T(0));
3410 set_tag(get_tag("FacePressure", 1), &face_pressure);
3411
3413}
3414
3415//! [Analytical displacement function from python]
3416#ifdef ENABLE_PYTHON_BINDING
3417
3418 MoFEMErrorCode AnalyticalExprPython::analyticalExprInit(const std::string py_file) {
3420 try {
3421
3422 // create main module
3423 auto main_module = bp::import("__main__");
3424 mainNamespace = main_module.attr("__dict__");
3425 bp::exec_file(py_file.c_str(), mainNamespace, mainNamespace);
3426 // create a reference to python function
3427 analyticalDispFun = mainNamespace["analytical_disp"];
3428 analyticalTractionFun = mainNamespace["analytical_traction"];
3429
3430 } catch (bp::error_already_set const &) {
3431 // print all other errors to stderr
3432 PyErr_Print();
3434 }
3436 }
3437
3438 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalDisp(
3439
3440 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3441 const std::string& block_name, np::ndarray &analytical_expr
3442
3443 ) {
3445 try {
3446
3447 // call python function
3448 analytical_expr = bp::extract<np::ndarray>(
3449 analyticalDispFun(delta_t, t, x, y, z, block_name));
3450
3451 } catch (bp::error_already_set const &) {
3452 // print all other errors to stderr
3453 PyErr_Print();
3455 }
3457 }
3458
3459 MoFEMErrorCode AnalyticalExprPython::evalAnalyticalTraction(
3460
3461 double delta_t, double t, np::ndarray x, np::ndarray y, np::ndarray z,
3462 const std::string& block_name, np::ndarray &analytical_expr
3463
3464 ) {
3466 try {
3467
3468 // call python function
3469 analytical_expr = bp::extract<np::ndarray>(
3470 analyticalTractionFun(delta_t, t, x, y, z, block_name));
3471
3472 } catch (bp::error_already_set const &) {
3473 // print all other errors to stderr
3474 PyErr_Print();
3476 }
3478 }
3479
3480boost::weak_ptr<AnalyticalExprPython> AnalyticalExprPythonWeakPtr;
3481
3482inline np::ndarray convert_to_numpy(VectorDouble &data, int nb_gauss_pts,
3483 int id) {
3484 auto dtype = np::dtype::get_builtin<double>();
3485 auto size = bp::make_tuple(nb_gauss_pts);
3486 auto stride = bp::make_tuple(3 * sizeof(double));
3487 return (np::from_data(&data[id], dtype, size, stride, bp::object()));
3488};
3489#endif
3490//! Analytical displacement function from python]
3491
3492
3493inline MatrixDouble analytical_expr_function(double delta_t, double t,
3494 int nb_gauss_pts,
3495 MatrixDouble &m_ref_coords,
3496 const std::string block_name) {
3497
3498#ifdef ENABLE_PYTHON_BINDING
3499 if (auto analytical_expr_ptr = AnalyticalExprPythonWeakPtr.lock()) {
3500
3501 VectorDouble v_ref_coords = m_ref_coords.data();
3502
3503 bp::list python_coords;
3504
3505 for (int idx = 0; idx < 3; ++idx) {
3506 python_coords.append(convert_to_numpy(v_ref_coords, nb_gauss_pts, idx));
3507 }
3508
3509 np::ndarray np_analytical_expr = np::empty(bp::make_tuple(nb_gauss_pts, 3),
3510 np::dtype::get_builtin<double>());
3511
3512 auto disp_block_name = "(.*)ANALYTICAL_DISPLACEMENT(.*)";
3513 auto traction_block_name = "(.*)ANALYTICAL_TRACTION(.*)";
3514
3515 std::regex reg_disp_name(disp_block_name);
3516 std::regex reg_traction_name(traction_block_name);
3517 if (std::regex_match(block_name, reg_disp_name)) {
3518 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalDisp(
3519 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3520 bp::extract<np::ndarray>(python_coords[1]),
3521 bp::extract<np::ndarray>(python_coords[2]), block_name,
3522 np_analytical_expr),
3523 "Failed analytical_disp() python call");
3524 }
3525 else if (std::regex_match(block_name, reg_traction_name)) {
3526 CHK_MOAB_THROW(analytical_expr_ptr->evalAnalyticalTraction(
3527 delta_t, t, bp::extract<np::ndarray>(python_coords[0]),
3528 bp::extract<np::ndarray>(python_coords[1]),
3529 bp::extract<np::ndarray>(python_coords[2]), block_name,
3530 np_analytical_expr),
3531 "Failed analytical_traction() python call");
3532 } else {
3534 "Unknown analytical block");
3535 }
3536
3537 double *analytical_expr_val_ptr =
3538 reinterpret_cast<double *>(np_analytical_expr.get_data());
3539
3540 MatrixDouble v_analytical_expr;
3541 v_analytical_expr.resize(3, nb_gauss_pts, false);
3542 for (size_t gg = 0; gg < nb_gauss_pts; ++gg) {
3543 for (int idx = 0; idx < 3; ++idx)
3544 v_analytical_expr(idx, gg) = *(analytical_expr_val_ptr + (3 * gg + idx));
3545 }
3546 return v_analytical_expr;
3547 }
3548#endif
3549 return MatrixDouble();
3550}
3551
3552} // 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_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
#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.
auto sort_eigen_vals(A &eig, B &eigen_vec)
MatrixDouble analytical_expr_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, const std::string block_name)
[Analytical displacement function from python]
static constexpr auto size_symm
auto getAnalyticalExpr(OP_PTR op_ptr, MatrixDouble &analytical_expr, 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
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.
OpCalculateHOJacForFaceImpl< 3 > OpCalculateHOJacForFaceEmbeddedIn3DSpace
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
double scale
Definition plastic.cpp:123
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
FTensor::Index< 'm', 3 > m
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
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 dofs values
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 dofs on entity.
EntityHandle getFEEntityHandle() const
Return finite element entity handle.
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Calculate normals at Gauss points of triangle element.
Scale base functions by inverses of measure of element.
PetscReal ts_t
time
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode iNtegrate(EntData &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)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
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)
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)