v0.16.0
Loading...
Searching...
No Matches
EshelbianOperators.cpp
Go to the documentation of this file.
1/**
2 * \file EshelbianOperators.cpp
3 * \example
4 * mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianOperators.cpp
5 *
6 * \brief Implementation of operators
7 */
8
9#include <MoFEM.hpp>
10using namespace MoFEM;
11
13
14#include <boost/math/constants/constants.hpp>
15
16#include <EshelbianAux.hpp>
17
18#include <lapack_wrap.h>
19
20#include <Lie.hpp>
21#include <MatrixFunction.hpp>
22
23namespace EshelbianPlasticity {
24
26 VectorPtr external_pressure_ptr,
27 boost::shared_ptr<ExternalStrainVec> external_strain_vec_ptr,
28 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv)
29 : VolUserDataOperator(H1, OPLAST),
30 externalPressurePtr(std::move(external_pressure_ptr)),
31 externalStrainVecPtr(std::move(external_strain_vec_ptr)),
32 scalingMethodsMap(std::move(smv)) {
33 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
34 doEntities[MBVERTEX] = true;
35}
36
38 EntData &) {
40
42 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
43 "External-pressure integration-point vector is null");
44 }
45
46 const int nb_integration_pts = getGaussPts().size2();
47 externalPressurePtr->resize(nb_integration_pts, false);
48 externalPressurePtr->clear();
51 }
52
53 double time = 0;
54 double time_step = 0;
57 time_step = EshelbianCore::physicalDt;
58 } else if ((getFEMethod()->data_ctx & PetscData::CtxSetTime).any()) {
59 time = getTStime();
60 time_step = getTStimeStep();
61 }
62 const EntityHandle fe_ent = getFEEntityHandle();
63 const std::regex analytical_pattern("(.*)ANALYTICAL_EXTERNALSTRAIN(.*)");
64
65 for (const auto &block : *externalStrainVecPtr) {
66 if (block.ents.find(fe_ent) == block.ents.end()) {
67 continue;
68 }
69 if (!std::isfinite(block.bulkModulusK)) {
70 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
71 "External-strain bulk modulus is not finite in block %s",
72 block.blockName.c_str());
73 }
74
75 VectorDouble external_strain(nb_integration_pts);
76 if (std::regex_match(block.blockName, analytical_pattern)) {
77 auto reference_coordinates = getCoordsAtGaussPts();
78 external_strain = analytical_externalstrain_function(
79 time_step, time, nb_integration_pts, reference_coordinates,
80 block.blockName);
81 } else {
82 double scale = 1;
83 if (const auto it = scalingMethodsMap.find(block.blockName);
84 it != scalingMethodsMap.end()) {
85 if (!it->second) {
86 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
87 "Scaling method is null for external-strain block %s",
88 block.blockName.c_str());
89 }
90 scale = it->second->getScale(time);
91 } else {
92 MOFEM_LOG("EP", Sev::warning)
93 << "No scaling method found for " << block.blockName;
94 }
95 std::fill(external_strain.begin(), external_strain.end(),
96 scale * block.val);
97 }
98
99 if (external_strain.size() != nb_integration_pts) {
100 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
101 "Wrong number of analytical external-strain integration points");
102 }
103 for (int gg = 0; gg != nb_integration_pts; ++gg) {
104 const double q = 3 * block.bulkModulusK * external_strain[gg];
105 if (!std::isfinite(q)) {
106 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
107 "External pressure q is not finite in block %s",
108 block.blockName.c_str());
109 }
110 (*externalPressurePtr)[gg] += q;
111 if (!std::isfinite((*externalPressurePtr)[gg])) {
112 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
113 "Accumulated external pressure q is not finite in block %s",
114 block.blockName.c_str());
115 }
116 }
117 }
118
120}
121
123 EntData &data) {
128
129 int nb_integration_pts = getGaussPts().size2();
130
131 auto t_P = dataAtPts->getFTensorApproxP(getGaussPts().size2());
132 auto t_F = dataAtPts->getFTensorSmallH(getGaussPts().size2());
133 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
134
135 auto get_eshelby_stress =
137 DL>::size(dataAtPts->SigmaAtPts, nb_integration_pts);
138 auto t_eshelby_stress = get_eshelby_stress();
139
141
142 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
143 t_eshelby_stress(i, j) = t_energy * t_kd(i, j) - t_F(m, i) * t_P(m, j);
144 ++t_energy;
145 ++t_P;
146 ++t_F;
147 ++t_eshelby_stress;
148 }
149
151}
152
153template <typename TInvD, typename TRotation, typename TDiffRotation,
154 typename TStress>
155auto getDiffSpatialGradientDR(TInvD &t_d_u_d_b, TRotation &t_R,
156 TDiffRotation &t_diff_R, TStress &t_P) {
157 FTENSOR_INDEXES(SPACE_DIM, i, j, k, l, m, n);
159 t_d_rotated_p_d_omega;
160 t_d_rotated_p_d_omega(i, j, k) = t_diff_R(n, i, k) * t_P(n, j);
161
163 t_d_b_d_omega(i, j, k) =
164 (t_d_rotated_p_d_omega(i, j, k) || t_d_rotated_p_d_omega(j, i, k)) / 2.;
165
167 t_d_u_d_omega(i, j, k) = t_d_u_d_b(i, j, l, m) * t_d_b_d_omega(l, m, k);
168
170 t_d_h_d_omega(i, j, k) = t_R(i, l) * t_d_u_d_omega(j, l, k);
171
172 return std::make_tuple(t_d_b_d_omega, t_d_u_d_omega, t_d_h_d_omega);
173}
174
176 EntityType type,
177 EntData &data) {
179
180 auto ts_ctx = getTSCtx();
181 int nb_integration_pts = getGaussPts().size2();
182
183 // space size indices
191
192 // sym size indices
194
196
198 *dataAtPts->getStretchTensorAtPts(), nb_integration_pts);
199 MatrixSizeHelper<GetFTensor4DdgFromMatType<3, 3, -1, DL>, DL>::size(
200 *dataAtPts->getDiffStretchTensorAtPts(), nb_integration_pts);
201 MatrixSizeHelper<GetFTensor2FromMatType<3, 3, -1, DL>, DL>::size(
202 *dataAtPts->getStretchH1AtPts(), nb_integration_pts);
203 MatrixSizeHelper<GetFTensor4FromMatType<3, 3, 3, 3, -1, DL>, DL>::size(
204 *dataAtPts->getDiffStretchH1AtPts(), nb_integration_pts);
205 MatrixSizeHelper<GetFTensor2FromMatType<3, 3, -1, DL>, DL>::size(
206 *dataAtPts->getAdjointPdstretchAtPts(), nb_integration_pts);
208 *dataAtPts->getAdjointPdUAtPts(), nb_integration_pts);
209 MatrixSizeHelper<GetFTensor3FromMatType<3, 3, size_symm, -1, DL>, DL>::size(
210 *dataAtPts->getAdjointPdUdPAtPts(), nb_integration_pts);
212 *dataAtPts->getAdjointPdUdOmegaAtPts(), nb_integration_pts);
213
214 MatrixSizeHelper<GetFTensor2FromMatType<3, 3, -1, DL>, DL>::size(
215 *dataAtPts->getDeformationGradient(), nb_integration_pts);
216 MatrixSizeHelper<GetFTensor3FromMatType<3, 3, 3, -1, DL>, DL>::size(
217 dataAtPts->hdOmegaAtPts, nb_integration_pts);
218 MatrixSizeHelper<GetFTensor3FromMatType<3, 3, size_symm, -1, DL>, DL>::size(
219 dataAtPts->hdLogStretchAtPts, nb_integration_pts);
220
221 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::size(
222 dataAtPts->leviKirchhoffAtPts, nb_integration_pts);
223 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::size(
224 dataAtPts->leviKirchhoff0AtPts, nb_integration_pts);
225 MatrixSizeHelper<GetFTensor2FromMatType<3, 3, -1, DL>, DL>::size(
226 dataAtPts->leviKirchhoffdOmegaAtPts, nb_integration_pts);
228 dataAtPts->leviKirchhoffdLogStreatchAtPts, nb_integration_pts);
229 MatrixSizeHelper<GetFTensor3FromMatType<3, 3, 3, -1, DL>, DL>::size(
230 dataAtPts->leviKirchhoffPAtPts, nb_integration_pts);
231
232 MatrixSizeHelper<GetFTensor2FromMatType<3, 3, -1, DL>, DL>::size(
233 dataAtPts->rotMatAtPts, nb_integration_pts);
234 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::size(
235 *dataAtPts->getEigenVals(), nb_integration_pts);
236 MatrixSizeHelper<GetFTensor2FromMatType<3, 3, -1, DL>, DL>::size(
237 *dataAtPts->getEigenVecs(), nb_integration_pts);
238 dataAtPts->nbUniq.resize(nb_integration_pts, false);
239 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::size(
240 dataAtPts->eigenValsC, nb_integration_pts);
241 MatrixSizeHelper<GetFTensor2FromMatType<3, 3, -1, DL>, DL>::size(
242 dataAtPts->eigenVecsC, nb_integration_pts);
243 dataAtPts->nbUniqC.resize(nb_integration_pts, false);
244
246 dataAtPts->logStretch2H1AtPts, nb_integration_pts);
248 dataAtPts->logStretchTotalTensorAtPts, nb_integration_pts);
249
250 MatrixSizeHelper<GetFTensor2FromMatType<3, 3, -1, DL>, DL>::size(
251 dataAtPts->internalStressAtPts, nb_integration_pts);
252 dataAtPts->internalStressAtPts.clear();
253
254 // Calculated values
255 auto t_h = dataAtPts->getFTensorSmallH(getGaussPts().size2());
256 auto t_h_domega = dataAtPts->getFTensorSmallHdOmega(getGaussPts().size2());
257 auto t_h_dlog_u =
258 dataAtPts->getFTensorSmallHdLogStretch(getGaussPts().size2());
259 auto t_levi_kirchhoff =
260 dataAtPts->getFTensorLeviKirchhoff(getGaussPts().size2());
261 auto t_levi_kirchhoff0 =
262 dataAtPts->getFTensorLeviKirchhoff0(getGaussPts().size2());
263 auto t_levi_kirchhoff_domega =
264 dataAtPts->getFTensorLeviKirchhoffdOmega(getGaussPts().size2());
265 auto t_levi_kirchhoff_dstreach =
266 dataAtPts->getFTensorLeviKirchhoffdLogStretch(getGaussPts().size2());
267 auto t_levi_kirchhoff_dP =
268 dataAtPts->getFTensorLeviKirchhoffP(getGaussPts().size2());
269 auto t_approx_P_adjoint_dstretch =
270 dataAtPts->getFTensorAdjointPdstretch(getGaussPts().size2());
271 auto t_approx_P_adjoint_log_du =
272 dataAtPts->getFTensorAdjointPdU(getGaussPts().size2());
273 auto t_approx_P_adjoint_log_du_dP =
274 dataAtPts->getFTensorAdjointPdUdP(getGaussPts().size2());
275 auto t_approx_P_adjoint_log_du_domega =
276 dataAtPts->getFTensorAdjointPdUdOmega(getGaussPts().size2());
277 auto t_R = dataAtPts->getFTensorRotMat(getGaussPts().size2());
278 auto t_u = dataAtPts->getFTensorStretch(getGaussPts().size2());
279 auto t_diff_u = dataAtPts->getFTensorDiffStretch(getGaussPts().size2());
280 auto t_eigen_vals = dataAtPts->getFTensorEigenVals(getGaussPts().size2());
281 auto t_eigen_vecs = dataAtPts->getFTensorEigenVecs(getGaussPts().size2());
282 auto &nbUniq = dataAtPts->nbUniq;
283 auto t_nb_uniq =
284 FTensor::Tensor0<FTensor::PackPtr<int *, 1>>(nbUniq.data().data());
285 auto t_eigen_vals_C = dataAtPts->getFTensorEigenValsC(nb_integration_pts);
286 auto t_eigen_vecs_C = dataAtPts->getFTensorEigenVecsC(nb_integration_pts);
287 auto &nbUniqC = dataAtPts->nbUniqC;
288 auto t_nb_uniq_C =
289 FTensor::Tensor0<FTensor::PackPtr<int *, 1>>(nbUniqC.data().data());
290
291 auto t_u_h1 = dataAtPts->getFTensorStretchH1(getGaussPts().size2());
292 auto t_diff_u_h1 = dataAtPts->getFTensorDiffStretchH1(getGaussPts().size2());
293 auto t_log_stretch_total =
294 dataAtPts->getFTensorLogStretchTotal(getGaussPts().size2());
295 auto t_log_u2_h1 = dataAtPts->getFTensorLogStretch2H1(getGaussPts().size2());
296
297 // Field values
298 auto t_grad_h1 = dataAtPts->getFTensorSmallWGradH1(getGaussPts().size2());
299 auto t_omega = dataAtPts->getFTensorRotAxis(getGaussPts().size2());
300 auto t_approx_P = dataAtPts->getFTensorApproxP(getGaussPts().size2());
301 auto t_approx_P0 = dataAtPts->getFTensorApproxP0(getGaussPts().size2());
302 auto t_log_u = dataAtPts->getFTensorLogStretch(getGaussPts().size2());
303
304 // Rot axis 0
305 auto t_omega0 = dataAtPts->getFTensorRotAxis0(getGaussPts().size2());
306 auto t_log_u0 = dataAtPts->getFTensorLogStretch0(getGaussPts().size2());
307
308 auto next = [&]() {
309 // calculated values
310 ++t_h;
311 ++t_h_domega;
312 ++t_h_dlog_u;
313 ++t_levi_kirchhoff;
314 ++t_levi_kirchhoff0;
315 ++t_levi_kirchhoff_domega;
316 ++t_levi_kirchhoff_dstreach;
317 ++t_levi_kirchhoff_dP;
318 ++t_approx_P_adjoint_dstretch;
319 ++t_approx_P_adjoint_log_du;
320 ++t_approx_P_adjoint_log_du_dP;
321 ++t_approx_P_adjoint_log_du_domega;
322 ++t_R;
323 ++t_u;
324 ++t_diff_u;
325 ++t_eigen_vals;
326 ++t_eigen_vecs;
327 ++t_nb_uniq;
328 ++t_eigen_vals_C;
329 ++t_eigen_vecs_C;
330 ++t_nb_uniq_C;
331 ++t_u_h1;
332 ++t_diff_u_h1;
333 ++t_log_u2_h1;
334 ++t_log_stretch_total;
335 // field values
336 ++t_omega;
337 ++t_omega0;
338 ++t_grad_h1;
339 ++t_approx_P;
340 ++t_approx_P0;
341 ++t_log_u;
342 ++t_log_u0;
343 };
344
347 constexpr auto t_diff_sym = FTensor::DiffSymmetrize<double>();
348
349 auto calculate_stretch_from_log = [&](auto &t_log_u_src, auto &t_u_dst,
350 auto &t_eigen_vals_dst,
351 auto &t_eigen_vecs_dst,
352 int &nb_uniq_dst) {
356 eigen_vec(i, j) = t_log_u_src(i, j);
357 if (computeEigenValuesSymmetric(eigen_vec, eig) != MB_SUCCESS) {
358 MOFEM_LOG("SELF", Sev::error) << "Failed to compute eigen values";
359 }
360 // CHKERR bound_eig(eig);
361 // rare case when two eigen values are equal
362 nb_uniq_dst = getUniqNb<3>(eig);
363 if (nb_uniq_dst < 3) {
364 CHKERR sortEigenVals<3>(eig, eigen_vec);
365 }
366 t_eigen_vals_dst(i) = eig(i);
367 t_eigen_vecs_dst(i, j) = eigen_vec(i, j);
368 t_u_dst(i, j) = EigenMatrix::getMat(t_eigen_vals_dst, t_eigen_vecs_dst,
371 };
372
373 auto calculate_log_stretch = [&]() {
375 int nb_uniq_val = 0;
376 CHKERR calculate_stretch_from_log(t_log_u, t_u, t_eigen_vals, t_eigen_vecs,
377 nb_uniq_val);
378 t_nb_uniq = nb_uniq_val;
379 auto get_t_diff_u = [&]() {
380 return EigenMatrix::getDiffMat(t_eigen_vals, t_eigen_vecs,
382 t_nb_uniq);
383 };
384 t_diff_u(i, j, k, l) = get_t_diff_u()(i, j, k, l);
386 t_Ldiff_u(i, j, L) = t_diff_u(i, j, m, n) * t_L(m, n, L);
388 };
389
390 auto calculate_total_stretch = [&](auto &t_h1) {
392 if (EshelbianCore::gradApproximator == NO_H1_CONFIGURATION) {
393
394 t_log_u2_h1(i, j) = 0;
395 t_log_stretch_total(i, j) = t_log_u(i, j);
396
397 } else {
398
400 FTensor::Tensor1<double, 3> t_coordinate_stretch;
402
404 t_C_h1(i, j) = t_h1(k, i) * t_h1(k, j);
405 t_eigen_vec(i, j) = t_C_h1(i, j);
406 if (computeEigenValuesSymmetric(t_eigen_vec, t_eig_C) != MB_SUCCESS) {
407 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
408 "Failed to compute eigenvalues of F_H1^T F_H1");
409 }
410 // rare case when two eigen values are equal
411 t_nb_uniq_C = getUniqNb<3>(t_eig_C);
412 if (t_nb_uniq_C < 3) {
413 CHKERR sortEigenVals<3>(t_eig_C, t_eigen_vec);
414 }
415 for (int aa = 0; aa != 3; ++aa) {
416 if (!std::isfinite(t_eig_C(aa)) || t_eig_C(aa) <= 0.) {
417 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
418 "F_H1^T F_H1 must be positive definite; eigenvalue %d is "
419 "%g",
420 aa, t_eig_C(aa));
421 }
422 const double principal_stretch = std::sqrt(t_eig_C(aa));
423 const double coordinate_stretch =
424 EshelbianCore::inv_f(principal_stretch);
425 if (!std::isfinite(coordinate_stretch)) {
426 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP,
427 "Non-finite H1 coordinate stretch for principal stretch %g",
428 principal_stretch);
429 }
430 t_coordinate_stretch(aa) = coordinate_stretch;
431 }
432 t_eigen_vals_C(i) = t_eig_C(i);
433 t_eigen_vecs_C(i, j) = t_eigen_vec(i, j);
434
435 t_log_u2_h1(i, j) =
436 EigenMatrix::getMat(t_coordinate_stretch, t_eigen_vec,
437 [](const double v) { return v; })(i, j);
438 // The hand-coded Hencky formulation uses additive stretch coordinates.
439 // For logarithmic coordinates this is log(U_H1) + log(U_increment).
440 t_log_stretch_total(i, j) = t_log_u2_h1(i, j) + t_log_u(i, j);
441 }
443 };
444
445 auto no_h1_loop = [&]() {
447
449 case LARGE_ROT:
450 break;
451 case SMALL_ROT:
452 break;
453 default:
454 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
455 "no_h1_loop is only implemented for LARGE_ROT");
456 };
457
458 for (int gg = 0; gg != nb_integration_pts; ++gg) {
459
461
463 t_h1(i, j) = t_kd(i, j);
464
465 // calculate streach
466 CHKERR calculate_log_stretch();
469 t_u0(i, j) = t_u(i, j);
470 } else {
471 FTensor::Tensor1<double, 3> t_eigen_vals_0;
472 FTensor::Tensor2<double, 3, 3> t_eigen_vecs_0;
473 int nb_uniq_0 = 0;
474 CHKERR calculate_stretch_from_log(t_log_u0, t_u0, t_eigen_vals_0,
475 t_eigen_vecs_0, nb_uniq_0);
476 }
477 // calculate total stretch
478 CHKERR calculate_total_stretch(t_h1);
479
480 t_u_h1(i, j) = t_u(i, j);
481 t_diff_u_h1(i, j, k, l) = t_diff_u(i, j, k, l);
483 t_Ldiff_u(i, j, L) = t_diff_u(i, j, m, n) * t_L(m, n, L);
484
487
488 auto large_rot = [&]() {
489 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
490 t_diff_R(i, j, k) =
491 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
492 t_diff_diff_R(i, j, k, l) =
493 LieGroups::SO3::diffDiffExp(t_omega, t_omega.l2())(i, j, k, l);
494
496 t_diff_R0(i, j, k) =
497 LieGroups::SO3::diffExp(t_omega0, t_omega0.l2())(i, j, k);
498
499 t_h(i, k) = t_R(i, l) * t_u(l, k);
500
502 t_rotated_P(l, k) = t_R(i, l) * t_approx_P(i, k);
503 t_approx_P_adjoint_dstretch(l, k) =
504 t_diff_sym(l, k, i, j) * t_rotated_P(i, j);
505 t_approx_P_adjoint_log_du(L) =
506 t_approx_P_adjoint_dstretch(l, k) * t_Ldiff_u(l, k, L);
507
508 t_levi_kirchhoff(m) =
509 t_diff_R(i, l, m) * (t_u(l, k) * t_approx_P(i, k));
510 t_levi_kirchhoff0(m) =
511 t_diff_R0(i, l, m) * (t_u0(l, k) * t_approx_P0(i, k));
512
514 t_h_domega(i, k, m) = t_diff_R(i, l, m) * t_u(l, k);
515 t_h_dlog_u(i, k, L) = t_R(i, l) * t_Ldiff_u(l, k, L);
516
517 t_approx_P_adjoint_log_du_dP(i, k, L) =
518 t_R(i, l) * t_Ldiff_u(l, k, L);
519
521 t_A(k, l, m) = t_diff_R(i, l, m) * t_approx_P(i, k);
522 t_approx_P_adjoint_log_du_domega(m, L) =
523 t_A(k, l, m) * t_Ldiff_u(k, l, L);
524
525 t_levi_kirchhoff_dstreach(m, L) =
526 t_diff_R(i, l, m) * (t_Ldiff_u(l, k, L) * t_approx_P(i, k));
527 t_levi_kirchhoff_dP(m, i, k) = t_diff_R(i, l, m) * t_u(l, k);
528 t_levi_kirchhoff_domega(m, n) =
529 t_diff_diff_R(i, l, m, n) * (t_u(l, k) * t_approx_P(i, k));
530
533 auto t_d_u_d_b = GetFTensor4DdgFromMatImpl<
534 SPACE_DIM, SPACE_DIM, -1, DL, MatrixDouble>::get(
535 dataAtPts->matInvD, gg, 0);
536 auto [t_d_b_d_omega, t_d_u_d_omega, t_d_h_d_omega] =
537 getDiffSpatialGradientDR(t_d_u_d_b, t_R, t_diff_R,
538 t_approx_P);
539
540 t_h_domega(i, k, m) += t_d_h_d_omega(i, k, m);
542 t_d_u_contract_p;
543 t_d_u_contract_p(i, l, n) =
544 t_d_u_d_omega(l, k, n) * t_approx_P(i, k);
545 t_levi_kirchhoff_domega(m, n) +=
546 t_diff_R(i, l, m) * t_d_u_contract_p(i, l, n);
547
548 if constexpr (EshelbianCore::symmetrySelector > SYMMETRIC) {
550 SPACE_DIM>
551 t_d_b_d_p;
552 t_d_b_d_p(i, j, k, l) =
553 t_diff_sym(i, j, m, l) * t_R(k, m);
555 SPACE_DIM>
556 t_d_u_d_p;
557 t_d_u_d_p(i, j, k, l) =
558 t_d_u_d_b(i, j, m, n) * t_d_b_d_p(m, n, k, l);
559 t_levi_kirchhoff_dP(m, k, l) +=
560 t_d_u_d_p(i, j, k, l) * t_d_b_d_omega(i, j, m);
561 }
562 }
563 }
564 };
565
566 auto moderate_rot = [&](auto &t_omega0) {
567 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
568 "moderate_rot is not implemented yet");
569 };
570
571 auto small_rot = [&]() {
572 t_u_h1(i, j) = t_u(i, j);
573 t_diff_u_h1(i, j, k, l) = t_diff_u(i, j, k, l);
575 t_Ldiff_u(i, j, L) = t_diff_u(i, j, m, n) * t_L(m, n, L);
576
577 t_R(i, j) = t_kd(i, j) + levi_civita(i, j, k) * t_omega(k);
578 t_h(i, j) = levi_civita(i, j, k) * t_omega(k) + t_u(i, j);
579
580 t_h_domega(i, j, k) = levi_civita(i, j, k);
581 t_h_dlog_u(i, j, L) = t_Ldiff_u(i, j, L);
582
583 // Adjoint stress
585 t_rotated_P(i, j) = t_R(k, i) * t_approx_P(k, j);
586 t_approx_P_adjoint_dstretch(i, j) =
587 t_diff_sym(i, j, k, l) * t_rotated_P(k, l);
588 t_approx_P_adjoint_log_du(L) =
589 t_approx_P_adjoint_dstretch(i, j) * t_Ldiff_u(i, j, L);
590 t_approx_P_adjoint_log_du_dP(i, j, L) = t_Ldiff_u(i, j, L);
591 t_approx_P_adjoint_log_du_domega(m, L) = 0;
592
593 // Kirchhoff stress
594 t_levi_kirchhoff(k) = levi_civita(i, j, k) * t_approx_P(i, j);
595 t_levi_kirchhoff0(k) = levi_civita(i, j, k) * t_approx_P0(i, j);
596 t_levi_kirchhoff_dstreach(m, L) = 0;
597 t_levi_kirchhoff_dP(k, i, j) = levi_civita(i, j, k);
598 t_levi_kirchhoff_domega(m, n) = 0;
599 };
600
601 // rotation
603 case LARGE_ROT:
604 large_rot();
605 break;
606 case MODERATE_ROT:
607 moderate_rot(t_omega0);
608 break;
609 case SMALL_ROT:
610 small_rot();
611 break;
612 default:
613 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
614 "rotationSelector not handled");
615 }
616
617 next();
618 }
619
621 };
622
623 auto large_loop = [&]() {
625
627 case LARGE_ROT:
628 break;
629 case SMALL_ROT:
630 break;
631 default:
632 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
633 "rotSelector should be large or small");
634 };
635
636 for (int gg = 0; gg != nb_integration_pts; ++gg) {
637
639
642 case LARGE_ROT:
643 t_h1(i, j) = t_grad_h1(i, j) + t_kd(i, j);
644 break;
645 default:
646 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
647 "Selected grad approximator not handled");
648 };
649
650 // calculate streach
651 CHKERR calculate_log_stretch();
654 t_u0(i, j) = t_u(i, j);
655 } else {
656 FTensor::Tensor1<double, 3> t_eigen_vals_0;
657 FTensor::Tensor2<double, 3, 3> t_eigen_vecs_0;
658 int nb_uniq_0 = 0;
659 CHKERR calculate_stretch_from_log(t_log_u0, t_u0, t_eigen_vals_0,
660 t_eigen_vecs_0, nb_uniq_0);
661 }
662 // calculate total stretch
663 CHKERR calculate_total_stretch(t_h1);
664
665 t_u_h1(l, k) = t_u(l, o) * t_h1(o, k);
667 t_u_h10(l, k) = t_u0(l, o) * t_h1(o, k);
668 t_diff_u_h1(i, j, k, l) = t_diff_u(i, o, k, l) * t_h1(o, j);
670 t_Ldiff_u_h1(l, k, L) = t_diff_u_h1(l, k, i, j) * t_L(i, j, L);
671
675
676 // rotation
678 case SMALL_ROT:
679 t_R(i, k) = t_kd(i, k) + levi_civita(i, k, l) * t_omega(l);
680 t_diff_R(i, j, k) = levi_civita(i, j, k);
681 t_diff_R0(i, j, k) = levi_civita(i, j, k);
682 t_diff_diff_R(i, j, l, m) = 0;
683 break;
684 case LARGE_ROT:
685 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
686 t_diff_R(i, j, k) =
687 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
688 t_diff_R0(i, j, k) =
689 LieGroups::SO3::diffExp(t_omega0, t_omega0.l2())(i, j, k);
690 t_diff_diff_R(i, j, k, l) =
691 LieGroups::SO3::diffDiffExp(t_omega, t_omega.l2())(i, j, k, l);
692 break;
693
694 default:
695 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
696 "rotationSelector not handled");
697 }
698
699 // calculate gradient
700 t_h(i, k) = t_R(i, l) * t_u_h1(l, k);
701
702 // Adjoint stress
704 t_rotated_P(l, o) =
705 (t_R(i, l) * t_approx_P(i, k)) * t_h1(o, k);
706 t_approx_P_adjoint_dstretch(l, o) =
707 t_diff_sym(l, o, i, j) * t_rotated_P(i, j);
708 t_approx_P_adjoint_log_du(L) =
709 t_R(i, l) * t_approx_P(i, k) * t_Ldiff_u_h1(l, k, L);
710
711 // Kirchhoff stress
712 t_levi_kirchhoff(m) = t_diff_R(i, l, m) * t_u_h1(l, k) * t_approx_P(i, k);
713 t_levi_kirchhoff0(m) =
714 t_diff_R0(i, l, m) * t_u_h10(l, k) * t_approx_P0(i, k);
715
717
718 t_h_domega(i, k, m) = t_diff_R(i, l, m) * t_u_h1(l, k);
719 t_h_dlog_u(i, k, L) = t_R(i, l) * t_Ldiff_u_h1(l, k, L);
720
721 t_approx_P_adjoint_log_du_dP(i, k, L) =
722 t_R(i, l) * t_Ldiff_u_h1(l, k, L);
723
725 t_A(m, L, i, k) = t_diff_R(i, l, m) * t_Ldiff_u_h1(l, k, L);
726 t_approx_P_adjoint_log_du_domega(m, L) =
727 t_A(m, L, i, k) * t_approx_P(i, k);
728
729 t_levi_kirchhoff_dstreach(m, L) =
730 t_diff_R(i, l, m) * (t_Ldiff_u_h1(l, k, L) * t_approx_P(i, k));
731
732 t_levi_kirchhoff_dP(m, i, k) = t_diff_R(i, l, m) * t_u_h1(l, k);
733 t_levi_kirchhoff_domega(m, n) =
734 t_diff_diff_R(i, l, m, n) * (t_u_h1(l, k) * t_approx_P(i, k));
735 }
736
737 next();
738 }
739
741 };
742
743 auto moderate_loop = [&]() {
745
747 case LARGE_ROT:
748 break;
749 case SMALL_ROT:
750 break;
751 default:
752 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
753 "rotSelector should be large or small");
754 };
755
756 for (int gg = 0; gg != nb_integration_pts; ++gg) {
757
759
762 case MODERATE_ROT:
763 t_h1(i, j) = t_grad_h1(i, j) + t_kd(i, j);
764 break;
765 default:
766 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
767 "Selected grad approximator not handled");
768 };
769
770 // calculate streach
771 CHKERR calculate_log_stretch();
772 // calculate total stretch
773 CHKERR calculate_total_stretch(t_h1);
774
775 auto t_diff = FTensor::DiffTensor<double>();
776
777 t_u_h1(l, k) = (t_kd(l, o) + t_log_u(l, o)) * t_h1(o, k);
779 t_u_h10(l, k) = (t_kd(l, o) + t_log_u0(l, o)) * t_h1(o, k);
780 t_diff_u_h1(i, j, k, l) = t_diff(i, o, k, l) * t_h1(o, j);
782 t_Ldiff_u_h1(l, k, L) = t_diff_u_h1(l, k, i, j) * t_L(i, j, L);
783
787
788 // rotation
790 case SMALL_ROT:
791 t_R(i, k) = t_kd(i, k) + levi_civita(i, k, l) * t_omega(l);
792 t_diff_R(i, j, k) = levi_civita(i, j, k);
793 t_diff_R0(i, j, k) = levi_civita(i, j, k);
794 t_diff_diff_R(i, j, l, m) = 0;
795 break;
796 case LARGE_ROT:
797 t_R(i, j) = LieGroups::SO3::exp(t_omega, t_omega.l2())(i, j);
798 t_diff_R(i, j, k) =
799 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
800 t_diff_R0(i, j, k) =
801 LieGroups::SO3::diffExp(t_omega0, t_omega0.l2())(i, j, k);
802 t_diff_diff_R(i, j, k, l) =
803 LieGroups::SO3::diffDiffExp(t_omega, t_omega.l2())(i, j, k, l);
804 break;
805
806 default:
807 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
808 "rotationSelector not handled");
809 }
810
811 // calculate gradient
812 t_h(i, k) = t_R(i, l) * t_u_h1(l, k);
813
814 // Adjoint stress
816 t_rotated_P(l, o) =
817 (t_R(i, l) * t_approx_P(i, k)) * t_h1(o, k);
818 t_approx_P_adjoint_dstretch(l, o) =
819 t_diff_sym(l, o, i, j) * t_rotated_P(i, j);
820 t_approx_P_adjoint_log_du(L) =
821 t_R(i, l) * t_approx_P(i, k) * t_Ldiff_u_h1(l, k, L);
822
823 // Kirchhoff stress
824 t_levi_kirchhoff(m) = t_diff_R(i, l, m) * t_u_h1(l, k) * t_approx_P(i, k);
825 t_levi_kirchhoff0(m) =
826 t_diff_R0(i, l, m) * t_u_h10(l, k) * t_approx_P0(i, k);
827
829
830 t_h_domega(i, k, m) = t_diff_R(i, l, m) * t_u_h1(l, k);
831 t_h_dlog_u(i, k, L) = t_R(i, l) * t_Ldiff_u_h1(l, k, L);
832
833 t_approx_P_adjoint_log_du_dP(i, k, L) =
834 t_R(i, l) * t_Ldiff_u_h1(l, k, L);
835
837 t_A(m, L, i, k) = t_diff_R(i, l, m) * t_Ldiff_u_h1(l, k, L);
838 t_approx_P_adjoint_log_du_domega(m, L) =
839 t_A(m, L, i, k) * t_approx_P(i, k);
840
841 t_levi_kirchhoff_dstreach(m, L) =
842 t_diff_R(i, l, m) * (t_Ldiff_u_h1(l, k, L) * t_approx_P(i, k));
843
844 t_levi_kirchhoff_dP(m, i, k) = t_diff_R(i, l, m) * t_u_h1(l, k);
845 t_levi_kirchhoff_domega(m, n) =
846 t_diff_diff_R(i, l, m, n) * (t_u_h1(l, k) * t_approx_P(i, k));
847 }
848
849 next();
850 }
851
853 };
854
855 auto small_loop = [&]() {
858 case SMALL_ROT:
859 break;
860 default:
861 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
862 "rotSelector should be small");
863 };
864
865 for (int gg = 0; gg != nb_integration_pts; ++gg) {
866
869 case SMALL_ROT:
870 t_h1(i, j) = t_kd(i, j);
871 break;
872 default:
873 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
874 "gradApproximator not handled");
875 };
876
878 if (EshelbianCore::stretchSelector > LINEAR) {
879 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
880 "stretchSelector should be linear for small loop");
881 } else {
882 t_u(i, j) = t_symm_kd(i, j) + t_log_u(i, j);
883 t_u_h1(i, j) = t_u(i, j);
884 t_diff_u_h1(i, j, k, l) =
885 (t_kd(i, k) * t_kd(j, l) + t_kd(i, l) * t_kd(j, k));
886 t_diff_u_h1(i, j, k, l) /= 2.;
887 t_Ldiff_u(i, j, L) = t_L(i, j, L);
888 }
889 t_log_u2_h1(i, j) = 0;
890 t_log_stretch_total(i, j) = t_log_u(i, j);
891
892 t_R(i, j) = t_kd(i, j) + levi_civita(i, j, k) * t_omega(k);
893 t_h(i, j) = levi_civita(i, j, k) * t_omega(k) + t_u(i, j);
894
895 t_h_domega(i, j, k) = levi_civita(i, j, k);
896 t_h_dlog_u(i, j, L) = t_Ldiff_u(i, j, L);
897
898 // Adjoint stress
899 t_approx_P_adjoint_dstretch(i, j) =
900 t_diff_sym(i, j, k, l) * t_approx_P(k, l);
901 t_approx_P_adjoint_log_du(L) =
902 t_approx_P_adjoint_dstretch(i, j) * t_Ldiff_u(i, j, L);
903 t_approx_P_adjoint_log_du_dP(i, j, L) = t_Ldiff_u(i, j, L);
904 t_approx_P_adjoint_log_du_domega(m, L) = 0;
905
906 // Kirchhoff stress
907 t_levi_kirchhoff(k) = levi_civita(i, j, k) * t_approx_P(i, j);
908 t_levi_kirchhoff0(k) = levi_civita(i, j, k) * t_approx_P0(i, j);
909 t_levi_kirchhoff_dstreach(m, L) = 0;
910 t_levi_kirchhoff_dP(k, i, j) = levi_civita(i, j, k);
911 t_levi_kirchhoff_domega(m, n) = 0;
912
913 next();
914 }
915
917 };
918
920 case NO_H1_CONFIGURATION:
921 CHKERR no_h1_loop();
922 break;
923 case LARGE_ROT:
924 CHKERR large_loop();
926 break;
927 case MODERATE_ROT:
928 CHKERR moderate_loop();
930 break;
931 case SMALL_ROT:
932 CHKERR small_loop();
934 break;
935 default:
936 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
937 "gradApproximator not handled");
938 break;
939 };
940
942}
943
945 EntData &data) {
948
949 auto n_in_the_loop = getNinTheLoop();
950 auto loop_size = getLoopSize();
951 auto sense = getSkeletonSense();
952 auto nb_gauss_pts = getGaussPts().size2();
953 auto t_normal = getFTensor1NormalsAtGaussPts();
954
955 auto t_sigma = dataAtPts->getFTensorApproxP(getGaussPts().size2());
956 auto get_tracion =
958 dataAtPts->tractionAtPts, nb_gauss_pts);
959 if (!n_in_the_loop) {
960 dataAtPts->tractionAtPts.clear();
961 }
962
963 auto t_traction = get_tracion();
964 for (int gg = 0; gg != nb_gauss_pts; gg++) {
965 t_traction(i) +=
966 t_sigma(i, j) * sense * (t_normal(j) / t_normal.l2()) / loop_size;
967 ++t_traction;
968 ++t_sigma;
969 ++t_normal;
970 }
971
973}
974
976 EntData &data) {
978 if (blockEntities.find(getFEEntityHandle()) == blockEntities.end()) {
980 };
984 int nb_integration_pts = getGaussPts().size2();
985 auto t_w = getFTensor0IntegrationWeight();
986 auto t_traction = dataAtPts->getFTensorTraction(nb_integration_pts);
987 auto t_coords = getFTensor1CoordsAtGaussPts();
988 auto t_spatial_disp = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
989
990 FTensor::Tensor1<double, 3> t_coords_spatial{0., 0., 0.};
991 // Offset for center of mass. Can be added in the future.
992 FTensor::Tensor1<double, 3> t_off{0.0, 0.0, 0.0};
993 FTensor::Tensor1<double, 3> loc_reaction_forces{0., 0., 0.};
994 FTensor::Tensor1<double, 3> loc_moment_forces{0., 0., 0.};
995
996 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
997 double a = t_w * getMeasure();
998 loc_reaction_forces(i) += a*t_traction(i);
999 t_coords_spatial(i) = t_coords(i) + t_spatial_disp(i);
1000 // t_coords_spatial(i) -= t_off(i);
1001 loc_moment_forces(i) +=
1002 (a * (FTensor::levi_civita<double>(i, j, k) * t_coords_spatial(j))) *
1003 t_traction(k);
1004 ++t_coords;
1005 ++t_spatial_disp;
1006 ++t_w;
1007 ++t_traction;
1008 }
1009
1010 reactionVec[0] += loc_reaction_forces(0);
1011 reactionVec[1] += loc_reaction_forces(1);
1012 reactionVec[2] += loc_reaction_forces(2);
1013 reactionVec[3] += loc_moment_forces(0);
1014 reactionVec[4] += loc_moment_forces(1);
1015 reactionVec[5] += loc_moment_forces(2);
1016
1018}
1019
1022 int nb_dofs = data.getIndices().size();
1023 int nb_integration_pts = data.getN().size1();
1024 auto v = getVolume();
1025 auto t_w = getFTensor0IntegrationWeight();
1026 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1027 auto t_s_dot_w = dataAtPts->getFTensorSmallWL2Dot(nb_integration_pts);
1028 auto w_l2_dot_dot_at_pts = dataAtPts->getSmallWL2DotDotAtPts();
1029 const bool reset_w_l2_dot_dot =
1030 w_l2_dot_dot_at_pts->size1() != nb_integration_pts ||
1031 w_l2_dot_dot_at_pts->size2() != 3;
1032 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::size(
1033 *w_l2_dot_dot_at_pts, nb_integration_pts);
1034 if (reset_w_l2_dot_dot) {
1035 w_l2_dot_dot_at_pts->clear();
1036 }
1037 auto t_s_dot_dot_w = dataAtPts->getFTensorSmallWL2DotDot(nb_integration_pts);
1038
1039 auto piola_scale = dataAtPts->piolaScale;
1040 auto alpha_w = alphaW / piola_scale;
1041 auto alpha_rho = alphaRho / piola_scale;
1042
1043 int nb_base_functions = data.getN().size2();
1044 auto t_row_base_fun = data.getFTensor0N();
1045
1046 FTensor::Index<'i', 3> i;
1047 auto get_ftensor1 = [](auto &v) {
1049 &v[2]);
1050 };
1051
1052 auto next = [&]() {
1053 ++t_w;
1054 ++t_div_P;
1055 ++t_s_dot_w;
1056 ++t_s_dot_dot_w;
1057 };
1058
1059 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1060 double a = v * t_w;
1061 auto t_nf = get_ftensor1(nF);
1062 int bb = 0;
1063 for (; bb != nb_dofs / 3; ++bb) {
1064 t_nf(i) -= a * t_row_base_fun * t_div_P(i);
1065 t_nf(i) += a * t_row_base_fun * alpha_w * t_s_dot_w(i);
1066 t_nf(i) += a * t_row_base_fun * alpha_rho * t_s_dot_dot_w(i);
1067 ++t_nf;
1068 ++t_row_base_fun;
1069 }
1070 for (; bb != nb_base_functions; ++bb)
1071 ++t_row_base_fun;
1072 next();
1073 }
1074
1076}
1077
1080 int nb_dofs = data.getIndices().size();
1081 int nb_integration_pts = getGaussPts().size2();
1082 auto v = getVolume();
1083 auto t_w = getFTensor0IntegrationWeight();
1084 auto t_levi_kirchhoff =
1085 dataAtPts->getFTensorLeviKirchhoff(nb_integration_pts);
1086 auto t_levi_kirchhoff0 =
1087 dataAtPts->getFTensorLeviKirchhoff0(nb_integration_pts);
1088 auto t_omega = dataAtPts->getFTensorRotAxis(nb_integration_pts);
1089 auto t_omega_grad = dataAtPts->getFTensorRotAxisGrad(nb_integration_pts);
1090 auto t_omega_dot = dataAtPts->getFTensorRotAxisDot(nb_integration_pts);
1091 auto t_omega_grad_dot =
1092 dataAtPts->getFTensorRotAxisGradDot(nb_integration_pts);
1093 int nb_base_functions = data.getN().size2();
1094 auto t_row_base_fun = data.getFTensor0N();
1095 auto t_row_grad_fun = data.getFTensor1DiffN<3>();
1096 FTensor::Index<'i', 3> i;
1097 FTensor::Index<'j', 3> j;
1098 FTensor::Index<'k', 3> k;
1099 auto get_ftensor1 = [](auto &v) {
1101 &v[2]);
1102 };
1103 // auto time_step = getTStimeStep();
1104
1105 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1106
1107 auto nrm_levi_kirchhoff0 = t_levi_kirchhoff0.l2();
1108
1109 double a = v * t_w;
1110 auto t_nf = get_ftensor1(nF);
1111 int bb = 0;
1112 for (; bb != nb_dofs / 3; ++bb) {
1113 t_nf(k) -= (a * t_row_base_fun) * t_levi_kirchhoff(k);
1114 t_nf(k) +=
1115 (a * (alphaR + alphaR0 * nrm_levi_kirchhoff0)) *
1116 (t_row_base_fun * t_omega(k));
1117 t_nf(k) += (a * (alphaOmega + alphaOmega0 * nrm_levi_kirchhoff0)) *
1118 (t_row_grad_fun(i) * t_omega_grad(k, i));
1119 t_nf(k) +=
1120 (a * (alphaViscousR + alphaViscousR0 * nrm_levi_kirchhoff0)
1121 /*/ time_step*/) *
1122 (t_row_base_fun * t_omega_dot(k));
1123 t_nf(k) +=
1124 (a * (alphaViscousOmega + alphaViscousOmega0 * nrm_levi_kirchhoff0)
1125 /*/ time_step*/) *
1126 (t_row_grad_fun(i) * t_omega_grad_dot(k, i));
1127 ++t_nf;
1128 ++t_row_base_fun;
1129 ++t_row_grad_fun;
1130 }
1131 for (; bb != nb_base_functions; ++bb) {
1132 ++t_row_base_fun;
1133 ++t_row_grad_fun;
1134 }
1135 ++t_w;
1136 ++t_levi_kirchhoff;
1137 ++t_omega;
1138 ++t_omega_grad;
1139 ++t_omega_dot;
1140 ++t_omega_grad_dot;
1141 ++t_levi_kirchhoff0;
1142 }
1144}
1145
1148 int nb_dofs = data.getIndices().size();
1149 int nb_integration_pts = data.getN().size1();
1150 auto v = getVolume();
1151 auto t_w = getFTensor0IntegrationWeight();
1152
1153 int nb_base_functions = data.getN().size2() / 3;
1154 auto t_row_base_fun = data.getFTensor1N<3>();
1155 FTENSOR_INDEX(3, i);
1156 FTENSOR_INDEX(3, j);
1157 FTENSOR_INDEX(3, k);
1158 FTENSOR_INDEX(3, m);
1159 FTENSOR_INDEX(3, l);
1160
1161 auto get_ftensor1 = [](auto &v) {
1163 &v[2]);
1164 };
1165
1166 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
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
1172 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1174
1175 t_residuum(i, j) = t_h(i, j) - t_kd(i, j);
1176
1177 int bb = 0;
1178 for (; bb != nb_dofs / 3; ++bb) {
1179 t_nf(i) -= a * t_row_base_fun(j) * t_residuum(i, j);
1180 ++t_nf;
1181 ++t_row_base_fun;
1182 }
1183
1184 for (; bb != nb_base_functions; ++bb)
1185 ++t_row_base_fun;
1186
1187 ++t_w;
1188 ++t_h;
1189 }
1190
1192}
1193
1196 int nb_dofs = data.getIndices().size();
1197 int nb_integration_pts = data.getN().size1();
1198 auto v = getVolume();
1199 auto t_w = getFTensor0IntegrationWeight();
1200
1201 int nb_base_functions = data.getN().size2() / 9;
1202 auto t_row_base_fun = data.getFTensor2N<3, 3>();
1203 FTENSOR_INDEX(3, i);
1204 FTENSOR_INDEX(3, j);
1205 FTENSOR_INDEX(3, k);
1206 FTENSOR_INDEX(3, m);
1207 FTENSOR_INDEX(3, l);
1208
1209 auto get_ftensor0 = [](auto &v) {
1211 };
1212
1213 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1214
1215 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1216 double a = v * t_w;
1217 auto t_nf = get_ftensor0(nF);
1218
1219 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1221 t_residuum(i, j) = t_h(i, j);
1222
1223 int bb = 0;
1224 for (; bb != nb_dofs; ++bb) {
1225 t_nf -= a * t_row_base_fun(i, j) * t_residuum(i, j);
1226 ++t_nf;
1227 ++t_row_base_fun;
1228 }
1229 for (; bb != nb_base_functions; ++bb) {
1230 ++t_row_base_fun;
1231 }
1232 ++t_w;
1233 ++t_h;
1234 }
1235
1237}
1238
1241 int nb_dofs = data.getIndices().size();
1242 int nb_integration_pts = data.getN().size1();
1243 auto v = getVolume();
1244 auto t_w = getFTensor0IntegrationWeight();
1245 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1246 int nb_base_functions = data.getN().size2() / 3;
1247 auto t_row_diff_base_fun = data.getFTensor2DiffN<3, 3>();
1248 FTensor::Index<'i', 3> i;
1249 auto get_ftensor1 = [](auto &v) {
1251 &v[2]);
1252 };
1253
1254 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1255 double a = v * t_w;
1256 auto t_nf = get_ftensor1(nF);
1257 int bb = 0;
1258 for (; bb != nb_dofs / 3; ++bb) {
1259 double div_row_base = t_row_diff_base_fun(i, i);
1260 t_nf(i) -= a * div_row_base * t_w_l2(i);
1261 ++t_nf;
1262 ++t_row_diff_base_fun;
1263 }
1264 for (; bb != nb_base_functions; ++bb) {
1265 ++t_row_diff_base_fun;
1266 }
1267 ++t_w;
1268 ++t_w_l2;
1269 }
1270
1272}
1273
1274template <>
1276 EntData &data) {
1278
1279 int nb_integration_pts = getGaussPts().size2();
1280
1281 Tag tag;
1282 CHKERR getPtrFE() -> mField.get_moab().tag_get_handle(tagName.c_str(), tag);
1283 int tag_length;
1284 CHKERR getPtrFE() -> mField.get_moab().tag_get_length(tag, tag_length);
1285 if (tag_length != 9) {
1286 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1287 "Number of internal stress components should be 9 but is %d",
1288 tag_length);
1289 }
1290
1291 VectorDouble const_stress_vec(9);
1292 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1293 CHKERR getPtrFE() -> mField.get_moab().tag_get_data(
1294 tag, &fe_ent, 1, &*const_stress_vec.data().begin());
1295 auto t_const_stress = getFTensor1FromArray<9, 9>(const_stress_vec);
1296
1297 auto get_internal_stress =
1298 MatrixSizeHelper<GetFTensor1FromMatType<9, -1, DL>, DL>::size(
1299 dataAtPts->internalStressAtPts, nb_integration_pts);
1300 dataAtPts->internalStressAtPts.clear();
1301 auto t_internal_stress = get_internal_stress();
1302
1303 FTensor::Index<'L', 9> L;
1304 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1305 t_internal_stress(L) = t_const_stress(L);
1306 ++t_internal_stress;
1307 }
1308
1310}
1311
1312template <>
1314 EntData &data) {
1316
1317 int nb_integration_pts = getGaussPts().size2();
1318
1319 Tag tag;
1320 CHKERR getPtrFE() -> mField.get_moab().tag_get_handle(tagName.c_str(), tag);
1321 int tag_length;
1322 CHKERR getPtrFE() -> mField.get_moab().tag_get_length(tag, tag_length);
1323 if (tag_length != 9) {
1324 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1325 "Number of internal stress components should be 9 but is %d",
1326 tag_length);
1327 }
1328
1329 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1330 const EntityHandle *vert_conn;
1331 int vert_num;
1332 CHKERR getPtrFE() -> mField.get_moab().get_connectivity(fe_ent, vert_conn,
1333 vert_num, true);
1334 VectorDouble vert_data(vert_num * tag_length);
1335 CHKERR getPtrFE() -> mField.get_moab().tag_get_data(tag, vert_conn, vert_num,
1336 &vert_data[0]);
1337
1338 auto get_internal_stress =
1339 MatrixSizeHelper<GetFTensor1FromMatType<9, -1, DL>, DL>::size(
1340 dataAtPts->internalStressAtPts, nb_integration_pts);
1341 dataAtPts->internalStressAtPts.clear();
1342 auto t_internal_stress = get_internal_stress();
1343
1344 auto t_shape_n = data.getFTensor0N();
1345 int nb_shape_fn = data.getN(NOBASE).size2();
1346 FTensor::Index<'L', 9> L;
1347 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1348 auto t_vert_data = getFTensor1FromArray<9, 9>(vert_data);
1349 for (int bb = 0; bb != nb_shape_fn; ++bb) {
1350 t_internal_stress(L) += t_vert_data(L) * t_shape_n;
1351 ++t_vert_data;
1352 ++t_shape_n;
1353 }
1354 ++t_internal_stress;
1355 }
1356
1358}
1359
1360template <>
1364
1365 int nb_dofs = data.getIndices().size();
1366 int nb_integration_pts = data.getN().size1();
1367 auto v = getVolume();
1368 auto t_w = getFTensor0IntegrationWeight();
1369
1370 FTensor::Index<'i', 3> i;
1371 FTensor::Index<'j', 3> j;
1372
1373 auto get_ftensor2 = [](auto &v) {
1375 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1376 };
1377
1378 auto t_internal_stress =
1379 dataAtPts->getFTensorInternalStress(nb_integration_pts);
1380
1381 const double time = EshelbianCore::physicalTimeFlg
1383 : getFEMethod()->ts_t;
1384
1385 // default scaling is constant
1386 double scale = scalingMethodPtr->getScale(time);
1387
1390
1391 int nb_base_functions = data.getN().size2();
1392 auto t_row_base_fun = data.getFTensor0N();
1393 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1394 double a = v * t_w;
1395 auto t_nf = get_ftensor2(nF);
1396
1397 FTensor::Tensor2<double, 3, 3> t_symm_stress;
1398 t_symm_stress(i, j) =
1399 (t_internal_stress(i, j) + t_internal_stress(j, i)) / 2;
1400
1402 t_residual(L) = t_L(i, j, L) * (scale * t_symm_stress(i, j));
1403
1404 int bb = 0;
1405 for (; bb != nb_dofs / 6; ++bb) {
1406 t_nf(L) += a * t_row_base_fun * t_residual(L);
1407 ++t_nf;
1408 ++t_row_base_fun;
1409 }
1410 for (; bb != nb_base_functions; ++bb)
1411 ++t_row_base_fun;
1412
1413 ++t_w;
1414 ++t_internal_stress;
1415 }
1417}
1418
1419template <>
1422
1423 int nb_dofs = data.getIndices().size();
1424 int nb_integration_pts = data.getN().size1();
1425 auto v = getVolume();
1426 auto t_w = getFTensor0IntegrationWeight();
1427
1428 auto get_ftensor2 = [](auto &v) {
1430 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1431 };
1432
1433 auto t_internal_stress =
1434 dataAtPts->getFTensorInternalStressVec(nb_integration_pts);
1435
1439 t_L = voigt_to_symm();
1440
1441 const double time = EshelbianCore::physicalTimeFlg
1443 : getFEMethod()->ts_t;
1444
1445 // default is constant
1446 double scale = scalingMethodPtr->getScale(time);
1447
1448 int nb_base_functions = data.getN().size2();
1449 auto t_row_base_fun = data.getFTensor0N();
1450 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1451 double a = v * t_w;
1452 auto t_nf = get_ftensor2(nF);
1453
1455 t_residual(L) = t_L(M, L) * (scale * t_internal_stress(M));
1456
1457 int bb = 0;
1458 for (; bb != nb_dofs / 6; ++bb) {
1459 t_nf(L) += a * t_row_base_fun * t_residual(L);
1460 ++t_nf;
1461 ++t_row_base_fun;
1462 }
1463 for (; bb != nb_base_functions; ++bb)
1464 ++t_row_base_fun;
1465
1466 ++t_w;
1467 ++t_internal_stress;
1468 }
1470}
1471
1472template <AssemblyType A>
1475 // get entity of face
1476 EntityHandle fe_ent = OP::getFEEntityHandle();
1477 // iterate over all boundary data
1478 for (auto &bc : (*bcDispPtr)) {
1479 // check if finite element entity is part of boundary condition
1480 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1481 int nb_dofs = data.getIndices().size();
1482
1483 int nb_integration_pts = OP::getGaussPts().size2();
1484 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1485 auto t_w = OP::getFTensor0IntegrationWeight();
1486 int nb_base_functions = data.getN().size2() / 3;
1487 auto t_row_base_fun = data.getFTensor1N<3>();
1488
1491
1492 double scale = 1;
1493 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1495 scale *= scalingMethodsMap.at(bc.blockName)
1497 } else {
1498 scale *= scalingMethodsMap.at(bc.blockName)
1499 ->getScale(OP::getFEMethod()->ts_t);
1500 }
1501 } else {
1502 MOFEM_LOG("SELF", Sev::warning)
1503 << "No scaling method found for " << bc.blockName;
1504 }
1505
1506 // get bc data
1507 FTensor::Tensor1<double, 3> t_bc_disp(bc.vals[0], bc.vals[1], bc.vals[2]);
1508 t_bc_disp(i) *= scale;
1509
1510 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1511 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1512 int bb = 0;
1513 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1514 t_nf(i) +=
1515 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
1516 ++t_nf;
1517 ++t_row_base_fun;
1518 }
1519 for (; bb != nb_base_functions; ++bb)
1520 ++t_row_base_fun;
1521
1522 ++t_w;
1523 ++t_normal;
1524 }
1525 }
1526 }
1528}
1529
1531 return OP::iNtegrate(data);
1532}
1533
1536 // get entity of face
1537 EntityHandle fe_ent = OP::getFEEntityHandle();
1538 // iterate over all boundary data
1539 for (auto &bc : (*bcDispPtr)) {
1540 // check if finite element entity is part of boundary condition
1541 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1542 int nb_dofs = data.getIndices().size();
1543
1544 int nb_integration_pts = OP::getGaussPts().size2();
1545 auto t_w = OP::getFTensor0IntegrationWeight();
1546 int nb_base_functions = data.getN().size2();
1547 auto t_row_base_fun = data.getFTensor0N();
1548#ifndef NDEBUG
1549 if (!this->sourceVec) {
1550 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1551 "Source vector for OpTauStabilizationDispRhsBc is not set");
1552 }
1553 if (data.getN().size1() != nb_integration_pts) {
1554 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1555 "Number of integration points in data should be %d but is %d",
1556 nb_integration_pts, (int)data.getN().size1());
1557 }
1558 if (nb_base_functions < nb_dofs / SPACE_DIM) {
1559 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1560 "Number of base functions in data should be %d but is %d",
1561 nb_base_functions, (int)data.getN().size2() / SPACE_DIM);
1562 }
1563
1564#endif
1565
1566 auto t_disp_val =
1567 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
1568 *this->sourceVec, nb_integration_pts)();
1569
1572
1573 double scale = 1;
1574 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1576 scale *= scalingMethodsMap.at(bc.blockName)
1578 } else {
1579 scale *= scalingMethodsMap.at(bc.blockName)
1580 ->getScale(OP::getFEMethod()->ts_t);
1581 }
1582 } else {
1583 MOFEM_LOG("SELF", Sev::warning)
1584 << "No scaling method found for " << bc.blockName;
1585 }
1586
1587 // get bc data
1588 FTensor::Tensor1<double, 3> t_bc_disp(bc.vals[0], bc.vals[1], bc.vals[2]);
1589 t_bc_disp(i) *= scale;
1590
1591 auto area = getMeasure();
1592 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1593 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1594 auto tau_scale =
1595 area * t_w * OP::betaCoeff(t_coords(0), t_coords(1), t_coords(2));
1597 for (int ii = 0; ii != SPACE_DIM; ++ii)
1598 t_bc_residual(ii) =
1599 bc.flags[ii] ? t_disp_val(ii) - t_bc_disp(ii) : 0.;
1600 auto t_nf = getFTensor1FromPtr<3, 3>(OP::locF.data().data());
1601 int bb = 0;
1602 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1603 t_nf(i) +=
1604 (tau_scale * t_row_base_fun) * t_bc_residual(i);
1605 ++t_nf;
1606 ++t_row_base_fun;
1607 }
1608 for (; bb != nb_base_functions; ++bb)
1609 ++t_row_base_fun;
1610
1611 ++t_w;
1612 ++t_coords;
1613 ++t_disp_val;
1614 }
1615 }
1616 }
1617
1619}
1620
1622 EntData &col_data) {
1624 // get entity of face
1625 EntityHandle fe_ent = OP::getFEEntityHandle();
1626 // iterate over all boundary data
1627 for (auto &bc : (*bcDispPtr)) {
1628 // check if finite element entity is part of boundary condition
1629 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1630 int nb_dofs = row_data.getIndices().size();
1631
1632 int nb_integration_pts = OP::getGaussPts().size2();
1633 auto t_w = OP::getFTensor0IntegrationWeight();
1634 int nb_base_functions = row_data.getN().size2();
1635 auto t_row_base_fun = row_data.getFTensor0N();
1636
1639
1641 for (int ii = 0; ii != SPACE_DIM; ++ii)
1642 t_bc_mask(ii) = bc.flags[ii] ? 1. : 0.;
1643
1644 auto get_t_vec = [&](const int rr) {
1645 std::array<double *, SPACE_DIM> ptrs;
1646 for (auto i = 0; i != SPACE_DIM; ++i)
1647 ptrs[i] = &OP::locMat(rr + i, i);
1649 SPACE_DIM>(ptrs);
1650 };
1651
1652 auto area = getMeasure();
1653 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1654 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1655 auto tau_scale =
1656 area * t_w * OP::betaCoeff(t_coords(0), t_coords(1), t_coords(2));
1657 int rr = 0;
1658 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1659 auto t_mat = get_t_vec(SPACE_DIM * rr);
1660 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
1661 for (int cc = 0; cc != nb_dofs / SPACE_DIM; ++cc) {
1662 t_mat(i) +=
1663 tau_scale * (t_row_base_fun * t_col_base_fun) * t_bc_mask(i);
1664 ++t_col_base_fun;
1665 ++t_mat;
1666 }
1667 ++t_row_base_fun;
1668 }
1669 for (; rr != nb_base_functions; ++rr)
1670 ++t_row_base_fun;
1671
1672 ++t_w;
1673 ++t_coords;
1674 }
1675 }
1676 }
1677
1679}
1680
1683
1684 EntityHandle fe_ent = OP::getFEEntityHandle();
1685 for (auto &bc : (*bcDispPtr)) {
1686 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1688 auto analytical_data = getAnalyticalExpr(this, analytical_expr, bc.blockName);
1689 auto &v_analytical_expr = std::get<1>(analytical_data);
1690
1691 int nb_dofs = data.getIndices().size();
1692 int nb_integration_pts = OP::getGaussPts().size2();
1693 auto t_w = OP::getFTensor0IntegrationWeight();
1694 int nb_base_functions = data.getN().size2();
1695 auto t_row_base_fun = data.getFTensor0N();
1696
1697#ifndef NDEBUG
1698 if (!this->sourceVec) {
1699 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1700 "Source vector for OpTauStabilizationOpAnalyticalDispBc is not "
1701 "set");
1702 }
1703 if (data.getN().size1() != nb_integration_pts) {
1704 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1705 "Number of integration points in data should be %d but is %d",
1706 nb_integration_pts, (int)data.getN().size1());
1707 }
1708 if (nb_base_functions < nb_dofs / SPACE_DIM) {
1709 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1710 "Number of base functions in data should be at least %d but is "
1711 "%d",
1712 nb_dofs / SPACE_DIM, nb_base_functions);
1713 }
1714#endif
1715
1716 auto t_disp_val =
1717 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
1718 *this->sourceVec, nb_integration_pts)();
1719 auto t_bc_disp = getFTensor1FromMat<3, -1, DL>(v_analytical_expr);
1720
1722
1723 auto area = getMeasure();
1724 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1725 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1726 auto tau_scale =
1727 area * t_w * OP::betaCoeff(t_coords(0), t_coords(1), t_coords(2));
1729 for (int ii = 0; ii != SPACE_DIM; ++ii)
1730 t_bc_residual(ii) =
1731 bc.flags[ii] ? t_disp_val(ii) - t_bc_disp(ii) : 0.;
1732 auto t_nf = getFTensor1FromPtr<3, 3>(OP::locF.data().data());
1733 int bb = 0;
1734 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1735 t_nf(i) +=
1736 (tau_scale * t_row_base_fun) * t_bc_residual(i);
1737 ++t_nf;
1738 ++t_row_base_fun;
1739 }
1740 for (; bb != nb_base_functions; ++bb)
1741 ++t_row_base_fun;
1742
1743 ++t_w;
1744 ++t_coords;
1745 ++t_disp_val;
1746 ++t_bc_disp;
1747 }
1748 }
1749 }
1750
1752}
1753
1755 EntData &row_data, EntData &col_data) {
1757
1758 EntityHandle fe_ent = OP::getFEEntityHandle();
1759 for (auto &bc : (*bcDispPtr)) {
1760 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1761 int nb_dofs = row_data.getIndices().size();
1762 int nb_integration_pts = OP::getGaussPts().size2();
1763 auto t_w = OP::getFTensor0IntegrationWeight();
1764 int nb_base_functions = row_data.getN().size2();
1765 auto t_row_base_fun = row_data.getFTensor0N();
1766
1769 for (int ii = 0; ii != SPACE_DIM; ++ii)
1770 t_bc_mask(ii) = bc.flags[ii] ? 1. : 0.;
1771
1772 auto get_t_vec = [&](const int rr) {
1773 std::array<double *, SPACE_DIM> ptrs;
1774 for (auto i = 0; i != SPACE_DIM; ++i)
1775 ptrs[i] = &OP::locMat(rr + i, i);
1777 SPACE_DIM>(ptrs);
1778 };
1779
1780 auto area = getMeasure();
1781 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1782 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1783 auto tau_scale =
1784 area * t_w * OP::betaCoeff(t_coords(0), t_coords(1), t_coords(2));
1785 int rr = 0;
1786 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1787 auto t_mat = get_t_vec(SPACE_DIM * rr);
1788 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
1789 for (int cc = 0; cc != nb_dofs / SPACE_DIM; ++cc) {
1790 t_mat(i) +=
1791 tau_scale * (t_row_base_fun * t_col_base_fun) * t_bc_mask(i);
1792 ++t_col_base_fun;
1793 ++t_mat;
1794 }
1795 ++t_row_base_fun;
1796 }
1797 for (; rr != nb_base_functions; ++rr)
1798 ++t_row_base_fun;
1799
1800 ++t_w;
1801 ++t_coords;
1802 }
1803 }
1804 }
1805
1807}
1808
1809template <AssemblyType A>
1812
1813 FTENSOR_INDEX(3, i);
1814 FTENSOR_INDEX(3, j);
1815 FTENSOR_INDEX(3, k);
1816
1817 double time = OP::getFEMethod()->ts_t;
1820 }
1821
1822 // get entity of face
1823 EntityHandle fe_ent = OP::getFEEntityHandle();
1824 // interate over all boundary data
1825 for (auto &bc : (*bcRotPtr)) {
1826 // check if finite element entity is part of boundary condition
1827 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1828 int nb_dofs = data.getIndices().size();
1829 int nb_integration_pts = OP::getGaussPts().size2();
1830 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1831 auto t_w = OP::getFTensor0IntegrationWeight();
1832
1833 int nb_base_functions = data.getN().size2() / 3;
1834 auto t_row_base_fun = data.getFTensor1N<3>();
1835
1836 auto get_ftensor1 = [](auto &v) {
1838 &v[2]);
1839 };
1840
1841 // Note: First three values of bc.vals are the center of rotation
1842 // 4th is rotation angle in radians, and remaining values are axis of
1843 // rotation. Also, if rotation axis is not provided, it defaults to the
1844 // normal vector of the face.
1845
1846 // get bc data
1847 FTensor::Tensor1<double, 3> t_center(bc.vals[0], bc.vals[1], bc.vals[2]);
1848
1849 auto get_rotation_angle = [&]() {
1850 double theta = bc.theta;
1851 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1852 theta *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1853 }
1854 return theta;
1855 };
1856
1857 auto get_rotation = [&](auto theta) {
1859 if (bc.vals.size() == 7) {
1860 t_omega(0) = bc.vals[4];
1861 t_omega(1) = bc.vals[5];
1862 t_omega(2) = bc.vals[6];
1863 } else {
1864 // Use gemetric face normal as rotation axis
1865 t_omega(i) = OP::getFTensor1Normal()(i);
1866 }
1867 if (t_omega.l2() > std::numeric_limits<double>::epsilon()) {
1868 t_omega.normalize();
1869 } else {
1870 MOFEM_LOG("SELF", Sev::warning)
1871 << "Rotation axis is zero vector for block " << bc.blockName
1872 << ". This may lead to unexpected results.";
1873 }
1874 t_omega(i) *= theta;
1876 RotSelector::SMALL_ROT
1877 ? 0.
1878 : t_omega.l2());
1879 };
1880
1881 auto t_R = get_rotation(get_rotation_angle());
1882 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1883
1884 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1886 t_delta(i) = t_center(i) - t_coords(i);
1888 t_disp(i) = t_delta(i) - t_R(i, j) * t_delta(j);
1889
1890 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1891 int bb = 0;
1892 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1893 t_nf(i) += t_w * (t_row_base_fun(j) * t_normal(j)) * t_disp(i) * 0.5;
1894 ++t_nf;
1895 ++t_row_base_fun;
1896 }
1897 for (; bb != nb_base_functions; ++bb)
1898 ++t_row_base_fun;
1899
1900 ++t_w;
1901 ++t_normal;
1902 ++t_coords;
1903 }
1904 }
1905 }
1907}
1908
1910 return OP::iNtegrate(data);
1911}
1912
1915
1916 FTENSOR_INDEX(3, i);
1917 FTENSOR_INDEX(3, j);
1918
1919 double time = OP::getFEMethod()->ts_t;
1922 }
1923
1924 // get entity of face
1925 EntityHandle fe_ent = OP::getFEEntityHandle();
1926 // iterate over all boundary data
1927 for (auto &bc : (*bcRotPtr)) {
1928 // check if finite element entity is part of boundary condition
1929 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1930 int nb_dofs = data.getIndices().size();
1931 int nb_integration_pts = OP::getGaussPts().size2();
1932 auto t_w = OP::getFTensor0IntegrationWeight();
1933
1934 int nb_base_functions = data.getN().size2();
1935 auto t_row_base_fun = data.getFTensor0N();
1936
1937 auto get_ftensor1 = [](auto &v) {
1939 &v[2]);
1940 };
1941
1942 // Note: First three values of bc.vals are the center of rotation
1943 // 4th is rotation angle in radians, and remaining values are axis of
1944 // rotation. Also, if rotation axis is not provided, it defaults to the
1945 // normal vector of the face.
1946
1947 // get bc data
1948 FTensor::Tensor1<double, 3> t_center(bc.vals[0], bc.vals[1], bc.vals[2]);
1949
1950 auto get_rotation_angle = [&]() {
1951 double theta = bc.theta;
1952 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1953 theta *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1954 }
1955 return theta;
1956 };
1957
1958 auto get_rotation = [&](auto theta) {
1960 if (bc.vals.size() == 7) {
1961 t_omega(0) = bc.vals[4];
1962 t_omega(1) = bc.vals[5];
1963 t_omega(2) = bc.vals[6];
1964 } else {
1965 // Use gemetric face normal as rotation axis
1966 t_omega(i) = OP::getFTensor1Normal()(i);
1967 }
1968 if (t_omega.l2() > std::numeric_limits<double>::epsilon()) {
1969 t_omega.normalize();
1970 }
1971 t_omega(i) *= theta;
1973 RotSelector::SMALL_ROT
1974 ? 0.
1975 : t_omega.l2());
1976 };
1977
1978 auto area = getMeasure();
1979 auto t_R = get_rotation(get_rotation_angle());
1980 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1981 auto t_disp_val =
1982 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
1983 *this->sourceVec, nb_integration_pts)();
1984
1985 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1986 auto tau_scale =
1987 area * t_w * OP::betaCoeff(t_coords(0), t_coords(1), t_coords(2));
1988
1990 t_delta(i) = t_center(i) - t_coords(i);
1992 t_bc_disp(i) = t_delta(i) - t_R(i, j) * t_delta(j);
1993
1994 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
1995 int bb = 0;
1996 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1997 t_nf(i) +=
1998 (tau_scale * t_row_base_fun) * (t_disp_val(i) - t_bc_disp(i));
1999 ++t_nf;
2000 ++t_row_base_fun;
2001 }
2002 for (; bb != nb_base_functions; ++bb)
2003 ++t_row_base_fun;
2004
2005 ++t_w;
2006 ++t_coords;
2007 ++t_disp_val;
2008 }
2009 }
2010 }
2011
2013}
2014
2016 EntData &col_data) {
2018 // get entity of face
2019 EntityHandle fe_ent = OP::getFEEntityHandle();
2020 // iterate over all boundary data
2021 for (auto &bc : (*bcRotPtr)) {
2022 // check if finite element entity is part of boundary condition
2023 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2024 int nb_dofs = row_data.getIndices().size();
2025
2026 int nb_integration_pts = OP::getGaussPts().size2();
2027 auto t_w = OP::getFTensor0IntegrationWeight();
2028 int nb_base_functions = row_data.getN().size2();
2029 auto t_row_base_fun = row_data.getFTensor0N();
2030
2033
2034 auto get_t_vec = [&](const int rr) {
2035 std::array<double *, SPACE_DIM> ptrs;
2036 for (auto i = 0; i != SPACE_DIM; ++i)
2037 ptrs[i] = &OP::locMat(rr + i, i);
2039 SPACE_DIM>(ptrs);
2040 };
2041
2042 auto area = getMeasure();
2043 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
2044 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2045 auto tau_scale =
2046 area * t_w * OP::betaCoeff(t_coords(0), t_coords(1), t_coords(2));
2047 int rr = 0;
2048 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2049 auto t_mat = get_t_vec(SPACE_DIM * rr);
2050 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
2051 for (int cc = 0; cc != nb_dofs / SPACE_DIM; ++cc) {
2052 for (int ii = 0; ii != SPACE_DIM; ++ii) {
2053 t_mat(ii) += tau_scale * (t_row_base_fun * t_col_base_fun);
2054 }
2055 ++t_col_base_fun;
2056 ++t_mat;
2057 }
2058 ++t_row_base_fun;
2059 }
2060 for (; rr != nb_base_functions; ++rr)
2061 ++t_row_base_fun;
2062
2063 ++t_w;
2064 ++t_coords;
2065 }
2066 }
2067 }
2068
2070}
2071
2072template <AssemblyType A>
2075
2076 double time = OP::getFEMethod()->ts_t;
2079 }
2080
2081 // get entity of face
2082 EntityHandle fe_ent = OP::getFEEntityHandle();
2083 // iterate over all boundary data
2084 for (auto &bc : (*bcDispPtr)) {
2085 // check if finite element entity is part of boundary condition
2086 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2087
2088 for (auto &bd : (*brokenBaseSideDataPtr)) {
2089
2090 auto t_approx_P = getFTensor2FromMat<3, 3, -1, DL>(bd.getFlux());
2091 auto t_u = getFTensor1FromMat<3, -1, DL>(*hybridDispPtr);
2092 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
2093 auto t_w = OP::getFTensor0IntegrationWeight();
2094
2097
2099
2100 double scale = 1;
2101 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2102 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2103 } else {
2104 MOFEM_LOG("SELF", Sev::warning)
2105 << "No scaling method found for " << bc.blockName;
2106 }
2107
2108 // get bc data
2109 double val = scale * bc.val;
2110
2111 int nb_dofs = data.getIndices().size();
2112 int nb_integration_pts = OP::getGaussPts().size2();
2113 int nb_base_functions = data.getN().size2();
2114 auto t_row_base = data.getFTensor0N();
2115 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2116
2118 t_N(i) = t_normal(i);
2119 t_N.normalize();
2120
2122 t_P(i, j) = t_N(i) * t_N(j);
2124 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
2125
2126 FTensor::Tensor1<double, 3> t_traction;
2127 t_traction(i) = t_approx_P(i, j) * t_N(j);
2128
2130 t_res(i) =
2131 t_Q(i, j) * t_traction(j) + t_P(i, j) * 2 * t_u(j) - t_N(i) * val;
2132
2133 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
2134 int bb = 0;
2135 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
2136 t_nf(i) += (t_w * t_row_base * OP::getMeasure()) * t_res(i);
2137 ++t_nf;
2138 ++t_row_base;
2139 }
2140 for (; bb != nb_base_functions; ++bb)
2141 ++t_row_base;
2142
2143 ++t_w;
2144 ++t_normal;
2145 ++t_u;
2146 ++t_approx_P;
2147 }
2148 }
2149 }
2150 }
2152}
2153
2154template <AssemblyType A>
2157 EntData &col_data) {
2159
2160 double time = OP::getFEMethod()->ts_t;
2163 }
2164
2165 int row_nb_dofs = row_data.getIndices().size();
2166 int col_nb_dofs = col_data.getIndices().size();
2167 auto &locMat = OP::locMat;
2168 locMat.resize(row_nb_dofs, col_nb_dofs, false);
2169 locMat.clear();
2170
2171 // get entity of face
2172 EntityHandle fe_ent = OP::getFEEntityHandle();
2173 // iterate over all boundary data
2174 for (auto &bc : (*bcDispPtr)) {
2175 // check if finite element entity is part of boundary condition
2176 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2177
2178 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
2179 auto t_w = OP::getFTensor0IntegrationWeight();
2180
2183
2184 double scale = 1;
2185 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2186 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2187 } else {
2188 MOFEM_LOG("SELF", Sev::warning)
2189 << "No scaling method found for " << bc.blockName;
2190 }
2191
2192 int nb_integration_pts = OP::getGaussPts().size2();
2193 int row_nb_dofs = row_data.getIndices().size();
2194 int col_nb_dofs = col_data.getIndices().size();
2195 int nb_base_functions = row_data.getN().size2();
2196 auto t_row_base = row_data.getFTensor0N();
2197
2199
2200 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2201
2203 t_N(i) = t_normal(i);
2204 t_N.normalize();
2205
2207 t_P(i, j) = t_N(i) * t_N(j);
2208
2210 t_d_res(i, j) = 2.0 * t_P(i, j);
2211
2212 int rr = 0;
2213 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
2214 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
2215 locMat, SPACE_DIM * rr);
2216 auto t_col_base = col_data.getFTensor0N(gg, 0);
2217 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
2218 t_mat(i, j) += (t_w * t_row_base * t_col_base) * t_d_res(i, j);
2219 ++t_mat;
2220 ++t_col_base;
2221 }
2222 ++t_row_base;
2223 }
2224
2225 for (; rr != nb_base_functions; ++rr)
2226 ++t_row_base;
2227
2228 ++t_w;
2229 ++t_normal;
2230 }
2231
2232 locMat *= OP::getMeasure();
2233 }
2234 }
2236}
2237
2238template <AssemblyType A>
2241 EntData &col_data) {
2243
2244 double time = OP::getFEMethod()->ts_t;
2247 }
2248
2249 int row_nb_dofs = row_data.getIndices().size();
2250 int col_nb_dofs = col_data.getIndices().size();
2251 auto &locMat = OP::locMat;
2252 locMat.resize(row_nb_dofs, col_nb_dofs, false);
2253 locMat.clear();
2254
2255 // get entity of face
2256 EntityHandle fe_ent = OP::getFEEntityHandle();
2257 // iterate over all boundary data
2258 for (auto &bc : (*bcDispPtr)) {
2259 // check if finite element entity is part of boundary condition
2260 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2261
2262 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
2263 auto t_w = OP::getFTensor0IntegrationWeight();
2264
2268
2270
2271 double scale = 1;
2272 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2273 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2274 } else {
2275 MOFEM_LOG("SELF", Sev::warning)
2276 << "No scaling method found for " << bc.blockName;
2277 }
2278
2279 int nb_integration_pts = OP::getGaussPts().size2();
2280 int nb_base_functions = row_data.getN().size2();
2281 auto t_row_base = row_data.getFTensor0N();
2282
2283 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2284
2286 t_N(i) = t_normal(i);
2287 t_N.normalize();
2288
2290 t_P(i, j) = t_N(i) * t_N(j);
2292 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
2293
2295 t_d_res(i, j) = t_Q(i, j);
2296
2297 int rr = 0;
2298 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
2299 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
2300 OP::locMat, SPACE_DIM * rr);
2301 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2302 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
2303 t_mat(i, j) +=
2304 ((t_w * t_row_base) * (t_N(k) * t_col_base(k))) * t_d_res(i, j);
2305 ++t_mat;
2306 ++t_col_base;
2307 }
2308 ++t_row_base;
2309 }
2310
2311 for (; rr != nb_base_functions; ++rr)
2312 ++t_row_base;
2313
2314 ++t_w;
2315 ++t_normal;
2316 }
2317
2318 locMat *= OP::getMeasure();
2319 }
2320 }
2322}
2323
2325 return OP::iNtegrate(data);
2326}
2327
2329 EntData &col_data) {
2330 return OP::iNtegrate(row_data, col_data);
2331}
2332
2334 EntData &col_data) {
2335 return OP::iNtegrate(row_data, col_data);
2336}
2337
2340
2341 // get entity of face
2342 EntityHandle fe_ent = OP::getFEEntityHandle();
2343 // iterate over all boundary data
2344 for (auto &bc : (*bcSpringPtr)) {
2345 // check if finite element entity is part of boundary condition
2346 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2347
2348 for (auto &bd : (*brokenBaseSideDataPtr)) {
2349
2350 auto t_approx_P = getFTensor2FromMat<3, 3, -1, DL>(bd.getFlux());
2351 auto t_u = getFTensor1FromMat<3, -1, DL>(*hybridDispPtr);
2352 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
2353 auto t_w = OP::getFTensor0IntegrationWeight();
2354
2357
2359
2360 int nb_dofs = data.getIndices().size();
2361 int nb_integration_pts = OP::getGaussPts().size2();
2362 int nb_base_functions = data.getN().size2();
2363 auto t_row_base = data.getFTensor0N();
2364 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2365
2367 t_N(i) = t_normal(i);
2368 t_N.normalize();
2369
2371 t_P(i, j) = t_N(i) * t_N(j);
2373 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
2374
2375 FTensor::Tensor1<double, 3> t_traction;
2376 t_traction(i) = t_approx_P(i, j) * t_N(j);
2377
2379 t_res(i) = 0.5 *(t_traction(i)) - bc.normalStiffness * t_P(i, j) * t_u(j) -
2380 bc.tangentialStiffness * t_Q(i, j) * t_u(j);
2381
2382 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
2383 int bb = 0;
2384 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
2385 t_nf(i) += (t_w * t_row_base * OP::getMeasure()) * t_res(i);
2386 ++t_nf;
2387 ++t_row_base;
2388 }
2389 for (; bb != nb_base_functions; ++bb)
2390 ++t_row_base;
2391
2392 ++t_w;
2393 ++t_normal;
2394 ++t_u;
2395 ++t_approx_P;
2396 }
2397 }
2398 }
2399 }
2401}
2402
2404 EntData &col_data) {
2406
2407 int row_nb_dofs = row_data.getIndices().size();
2408 int col_nb_dofs = col_data.getIndices().size();
2409 auto &locMat = OP::locMat;
2410 locMat.resize(row_nb_dofs, col_nb_dofs, false);
2411 locMat.clear();
2412
2413 // get entity of face
2414 EntityHandle fe_ent = OP::getFEEntityHandle();
2415 // iterate over all boundary data
2416 for (auto &bc : (*bcSpringPtr)) {
2417 // check if finite element entity is part of boundary condition
2418 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2419
2420 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
2421 auto t_w = OP::getFTensor0IntegrationWeight();
2422
2425
2426 int nb_integration_pts = OP::getGaussPts().size2();
2427 int nb_base_functions = row_data.getN().size2();
2428 auto t_row_base = row_data.getFTensor0N();
2429
2431
2432 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2433
2435 t_N(i) = t_normal(i);
2436 t_N.normalize();
2437
2439 t_P(i, j) = t_N(i) * t_N(j);
2441 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
2442
2444 t_d_res(i, j) = -(bc.normalStiffness * t_P(i, j) +
2445 bc.tangentialStiffness * t_Q(i, j));
2446
2447 int rr = 0;
2448 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
2449 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
2450 locMat, SPACE_DIM * rr);
2451 auto t_col_base = col_data.getFTensor0N(gg, 0);
2452 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
2453 t_mat(i, j) += (t_w * t_row_base * t_col_base) * t_d_res(i, j);
2454 ++t_mat;
2455 ++t_col_base;
2456 }
2457 ++t_row_base;
2458 }
2459
2460 for (; rr != nb_base_functions; ++rr)
2461 ++t_row_base;
2462
2463 ++t_w;
2464 ++t_normal;
2465 }
2466
2467 locMat *= OP::getMeasure();
2468 }
2469 }
2471}
2472
2474 EntData &col_data) {
2476
2477 int row_nb_dofs = row_data.getIndices().size();
2478 int col_nb_dofs = col_data.getIndices().size();
2479 auto &locMat = OP::locMat;
2480 locMat.resize(row_nb_dofs, col_nb_dofs, false);
2481 locMat.clear();
2482
2483 // get entity of face
2484 EntityHandle fe_ent = OP::getFEEntityHandle();
2485 // iterate over all boundary data
2486 for (auto &bc : (*bcSpringPtr)) {
2487 // check if finite element entity is part of boundary condition
2488 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2489
2490 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
2491 auto t_w = OP::getFTensor0IntegrationWeight();
2492
2496
2497 int nb_integration_pts = OP::getGaussPts().size2();
2498 int nb_base_functions = row_data.getN().size2();
2499 auto t_row_base = row_data.getFTensor0N();
2500
2502
2503 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2504
2506 t_N(i) = t_normal(i);
2507 t_N.normalize();
2508
2509 int rr = 0;
2510 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
2511 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
2512 OP::locMat, SPACE_DIM * rr);
2513 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
2514 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
2515 t_mat(i, j) +=
2516 ((t_w * t_row_base) * (t_N(k) * t_col_base(k))) * 0.5 * t_kd(i, j);
2517 ++t_mat;
2518 ++t_col_base;
2519 }
2520 ++t_row_base;
2521 }
2522
2523 for (; rr != nb_base_functions; ++rr)
2524 ++t_row_base;
2525
2526 ++t_w;
2527 ++t_normal;
2528 }
2529
2530 locMat *= OP::getMeasure();
2531 }
2532 }
2534}
2535
2536template <AssemblyType A>
2539
2540 double time = OP::getFEMethod()->ts_t;
2543 }
2544
2545 // get entity of face
2546 EntityHandle fe_ent = OP::getFEEntityHandle();
2547 // iterate over all boundary data
2548 for (auto &bc : (*bcDispPtr)) {
2549 // check if finite element entity is part of boundary condition
2550 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2551
2553 // placeholder to pass boundary block id to python
2554
2555 auto [block_name, v_analytical_expr] =
2556 getAnalyticalExpr(this, analytical_expr, bc.blockName);
2557
2558 int nb_dofs = data.getIndices().size();
2559 if (!nb_dofs) {
2560 continue;
2561 }
2562
2563 int nb_integration_pts = OP::getGaussPts().size2();
2564 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
2565 auto t_w = OP::getFTensor0IntegrationWeight();
2566 int nb_base_functions = data.getN().size2() / 3;
2567 auto t_row_base_fun = data.getFTensor1N<3>();
2568
2571
2572 // get bc data
2573 auto t_bc_disp = getFTensor1FromMat<3, -1, DL>(v_analytical_expr);
2574
2575 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2576 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
2577
2578 int bb = 0;
2579 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
2580 t_nf(i) +=
2581 t_w * (t_row_base_fun(j) * t_normal(j)) * t_bc_disp(i) * 0.5;
2582 ++t_nf;
2583 ++t_row_base_fun;
2584 }
2585 for (; bb != nb_base_functions; ++bb)
2586 ++t_row_base_fun;
2587
2588 ++t_bc_disp;
2589 ++t_w;
2590 ++t_normal;
2591 }
2592 }
2593 }
2595}
2596
2598 return OP::iNtegrate(data);
2599}
2600
2603
2604 FTENSOR_INDEX(3, i);
2605
2606 int nb_dofs = data.getFieldData().size();
2607 int nb_integration_pts = getGaussPts().size2();
2608 int nb_base_functions = data.getN().size2();
2609
2610 double time = getFEMethod()->ts_t;
2613 }
2614
2615#ifndef NDEBUG
2616 if (this->locF.size() != nb_dofs)
2617 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2618 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
2619#endif // NDEBUG
2620
2621 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
2623
2624 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
2625 auto t_row_base = data.getFTensor0N();
2626 auto t_w = getFTensor0IntegrationWeight();
2627 auto t_coords = getFTensor1CoordsAtGaussPts();
2628 auto t_normal = getFTensor1NormalsAtGaussPts();
2629
2630 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2631
2632 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2633
2634 double a = sqrt(t_normal(i) * t_normal(i));
2635 a /= 2.;
2636 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2637 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2638 int rr = 0;
2639 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2640 t_f(i) -=
2641 (time_scale * a * t_w * t_row_base * tau) * (t_val(i) * scale);
2642 ++t_row_base;
2643 ++t_f;
2644 }
2645
2646 for (; rr != nb_base_functions; ++rr)
2647 ++t_row_base;
2648 ++t_w;
2649 ++t_coords;
2650 ++t_normal;
2651 }
2653 };
2654
2655 // get entity of face
2656 EntityHandle fe_ent = getFEEntityHandle();
2657 for (auto &bc : *(bcData)) {
2658 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2659
2660 double time_scale = 1;
2661 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2662 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2663 }
2664
2665 int nb_dofs = data.getFieldData().size();
2666 if (nb_dofs) {
2667
2668 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
2669 auto calc_tau = [](double, double y, double) {
2670 y -= 44;
2671 y /= (60 - 44);
2672 return -y * (y - 1) / 0.25;
2673 };
2674 CHKERR integrate_rhs(bc, calc_tau, time_scale);
2675 } else {
2676 CHKERR integrate_rhs(
2677 bc, [](double, double, double) { return 1; }, time_scale);
2678 }
2679 }
2680 }
2681 }
2683}
2684
2687
2688 FTENSOR_INDEX(3, i);
2689
2690 int nb_dofs = data.getFieldData().size();
2691 int nb_integration_pts = getGaussPts().size2();
2692 int nb_base_functions = data.getN().size2();
2693
2694 double time = getFEMethod()->ts_t;
2697 }
2698
2699#ifndef NDEBUG
2700 if (this->locF.size() != nb_dofs)
2701 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2702 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
2703#endif // NDEBUG
2704
2705 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
2707
2708 auto val = bc.val;
2709 auto t_row_base = data.getFTensor0N();
2710 auto t_w = getFTensor0IntegrationWeight();
2711 auto t_coords = getFTensor1CoordsAtGaussPts();
2712 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
2713 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
2714
2715 auto t_grad_gamma_u = getFTensor2FromMat<3, 2, -1, DL>(*hybridGradDispPtr);
2716
2717 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2718
2719 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2720
2726
2728 if (EshelbianCore::stretchSelector == LINEAR &&
2729 EshelbianCore::gradApproximator < MODERATE_ROT) {
2730
2731 t_normal(i) = (FTensor::levi_civita<double>(i, j, k) * t_tangent1(j)) *
2732 t_tangent2(k);
2733 } else {
2734 t_normal(i) = (FTensor::levi_civita<double>(i, j, k) *
2735 (t_tangent1(j) + t_grad_gamma_u(j, N0))) *
2736 (t_tangent2(k) + t_grad_gamma_u(k, N1));
2737 }
2738 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2739 auto t_val = FTensor::Tensor1<double, 3>();
2740 t_val(i) = (time_scale * t_w * tau * scale * val) * t_normal(i);
2741
2742 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2743 int rr = 0;
2744 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2745 t_f(i) += t_row_base * t_val(i);
2746 ++t_row_base;
2747 ++t_f;
2748 }
2749
2750 for (; rr != nb_base_functions; ++rr)
2751 ++t_row_base;
2752 ++t_w;
2753 ++t_coords;
2754 ++t_tangent1;
2755 ++t_tangent2;
2756 ++t_grad_gamma_u;
2757 }
2758 this->locF /= 2.;
2759
2761 };
2762
2763 // get entity of face
2764 EntityHandle fe_ent = getFEEntityHandle();
2765 for (auto &bc : *(bcData)) {
2766 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2767
2768 double time_scale = 1;
2769 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2770 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2771 }
2772
2773 int nb_dofs = data.getFieldData().size();
2774 if (nb_dofs) {
2775 CHKERR integrate_rhs(
2776 bc, [](double, double, double) { return 1; }, time_scale);
2777 }
2778 }
2779 }
2781}
2782
2783template <AssemblyType A>
2786 EntData &col_data) {
2788
2789 if (EshelbianCore::stretchSelector == LINEAR &&
2790 EshelbianCore::gradApproximator < MODERATE_ROT) {
2792 }
2793
2794 double time = OP::getFEMethod()->ts_t;
2797 }
2798
2799 int nb_base_functions = row_data.getN().size2();
2800 int row_nb_dofs = row_data.getIndices().size();
2801 int col_nb_dofs = col_data.getIndices().size();
2802 int nb_integration_pts = OP::getGaussPts().size2();
2803 auto &locMat = OP::locMat;
2804 locMat.resize(row_nb_dofs, col_nb_dofs, false);
2805 locMat.clear();
2806
2807 auto integrate_lhs = [&](auto &bc, auto calc_tau, double time_scale) {
2809
2810 auto val = bc.val;
2811 auto t_row_base = row_data.getFTensor0N();
2812 auto t_w = OP::getFTensor0IntegrationWeight();
2813 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
2814 auto t_tangent1 = OP::getFTensor1Tangent1AtGaussPts();
2815 auto t_tangent2 = OP::getFTensor1Tangent2AtGaussPts();
2816
2817 auto t_grad_gamma_u = getFTensor2FromMat<3, 2, -1, DL>(*hybridGradDispPtr);
2819
2820 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2821
2826
2829
2830 auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
2831 auto t_val = time_scale * t_w * tau * val;
2832
2833 int rr = 0;
2834 for (; rr != row_nb_dofs / SPACE_DIM; ++rr) {
2835 auto t_mat = getFTensor2FromArray<SPACE_DIM, SPACE_DIM, SPACE_DIM>(
2836 locMat, SPACE_DIM * rr);
2837 auto t_diff_col_base = col_data.getFTensor1DiffN<2>(gg, 0);
2838 for (auto cc = 0; cc != col_nb_dofs / SPACE_DIM; ++cc) {
2840 t_normal_du(i, l) = (FTensor::levi_civita<double>(i, j, k) *
2841 (t_tangent2(k) + t_grad_gamma_u(k, N1))) *
2842 t_kd(j, l) * t_diff_col_base(N0)
2843
2844 +
2845
2846 (FTensor::levi_civita<double>(i, j, k) *
2847 (t_tangent1(j) + t_grad_gamma_u(j, N0))) *
2848 t_kd(k, l) * t_diff_col_base(N1);
2849
2850 t_mat(i, j) += t_row_base * t_val * t_normal_du(i, j);
2851 ++t_mat;
2852 ++t_diff_col_base;
2853 }
2854 ++t_row_base;
2855 }
2856
2857 for (; rr != nb_base_functions; ++rr)
2858 ++t_row_base;
2859 ++t_w;
2860 ++t_coords;
2861 ++t_tangent1;
2862 ++t_tangent2;
2863 ++t_grad_gamma_u;
2864 }
2865
2866 OP::locMat /= 2.;
2867
2869 };
2870
2871 // get entity of face
2872 EntityHandle fe_ent = OP::getFEEntityHandle();
2873 for (auto &bc : *(bcData)) {
2874 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2875
2876 double time_scale = 1;
2877 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
2878 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
2879 }
2880
2881 int nb_dofs = row_data.getFieldData().size();
2882 if (nb_dofs) {
2883 CHKERR integrate_lhs(
2884 bc, [](double, double, double) { return 1; }, time_scale);
2885 }
2886 }
2887 }
2888
2890}
2891
2893 EntData &col_data) {
2894 return OP::iNtegrate(row_data, col_data);
2895}
2896
2899
2900 FTENSOR_INDEX(3, i);
2901
2902 int nb_dofs = data.getFieldData().size();
2903 int nb_integration_pts = getGaussPts().size2();
2904 int nb_base_functions = data.getN().size2();
2905
2906 double time = getFEMethod()->ts_t;
2909 }
2910
2911#ifndef NDEBUG
2912 if (this->locF.size() != nb_dofs)
2913 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2914 "Size of locF %ld != nb_dofs %d", this->locF.size(), nb_dofs);
2915#endif // NDEBUG
2916
2917 // get entity of face
2918 EntityHandle fe_ent = getFEEntityHandle();
2919 for (auto &bc : *(bcData)) {
2920 if (bc.faces.find(fe_ent) != bc.faces.end()) {
2921
2923 // placeholder to pass boundary block id to python
2924 auto [block_name, v_analytical_expr] =
2925 getAnalyticalExpr(this, analytical_expr, bc.blockName);
2926 auto t_val = getFTensor1FromMat<3, -1, DL>(v_analytical_expr);
2927 auto t_row_base = data.getFTensor0N();
2928 auto t_w = getFTensor0IntegrationWeight();
2929 auto t_coords = getFTensor1CoordsAtGaussPts();
2930
2931 double scale = (piolaScalePtr) ? 1. / (*piolaScalePtr) : 1.0;
2932
2933 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2934
2935 auto t_f = getFTensor1FromPtr<3>(&*this->locF.begin());
2936 int rr = 0;
2937 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
2938 t_f(i) -= t_w * t_row_base * (t_val(i) * scale);
2939 ++t_row_base;
2940 ++t_f;
2941 }
2942
2943 for (; rr != nb_base_functions; ++rr)
2944 ++t_row_base;
2945 ++t_w;
2946 ++t_coords;
2947 ++t_val;
2948 }
2949 this->locF *= getMeasure();
2950 }
2951 }
2953}
2954
2956 EntData &col_data) {
2958 int nb_integration_pts = row_data.getN().size1();
2959 int row_nb_dofs = row_data.getIndices().size();
2960 int col_nb_dofs = col_data.getIndices().size();
2961 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
2963 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2));
2964 };
2965 FTensor::Index<'i', 3> i;
2966 auto v = getVolume();
2967 auto t_w = getFTensor0IntegrationWeight();
2968 int row_nb_base_functions = row_data.getN().size2();
2969 auto t_row_base_fun = row_data.getFTensor0N();
2970 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2971 double a = v * t_w;
2972 int rr = 0;
2973 for (; rr != row_nb_dofs / 3; ++rr) {
2974 auto t_col_diff_base_fun = col_data.getFTensor2DiffN<3, 3>(gg, 0);
2975 auto t_m = get_ftensor1(K, 3 * rr, 0);
2976 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
2977 double div_col_base = t_col_diff_base_fun(i, i);
2978 t_m(i) -= a * t_row_base_fun * div_col_base;
2979 ++t_m;
2980 ++t_col_diff_base_fun;
2981 }
2982 ++t_row_base_fun;
2983 }
2984 for (; rr != row_nb_base_functions; ++rr)
2985 ++t_row_base_fun;
2986 ++t_w;
2987 }
2989}
2990
2992 EntData &col_data) {
2994
2995 if (alphaW < std::numeric_limits<double>::epsilon() &&
2996 alphaRho < std::numeric_limits<double>::epsilon())
2998
2999 const int nb_integration_pts = row_data.getN().size1();
3000 const int row_nb_dofs = row_data.getIndices().size();
3001 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
3003 &m(r + 0, c + 0), &m(r + 1, c + 1), &m(r + 2, c + 2)
3004
3005 );
3006 };
3007 FTensor::Index<'i', 3> i;
3008
3009 auto v = getVolume();
3010 auto t_w = getFTensor0IntegrationWeight();
3011
3012 auto piola_scale = dataAtPts->piolaScale;
3013 auto alpha_w = alphaW / piola_scale;
3014 auto alpha_rho = alphaRho / piola_scale;
3015
3016 int row_nb_base_functions = row_data.getN().size2();
3017 auto t_row_base_fun = row_data.getFTensor0N();
3018
3019 double ts_scale = alpha_w * getTSa();
3020 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon())
3021 ts_scale += alpha_rho * getTSaa();
3022
3023 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3024 double a = v * t_w * ts_scale;
3025
3026 int rr = 0;
3027 for (; rr != row_nb_dofs / 3; ++rr) {
3028
3029 auto t_col_base_fun = row_data.getFTensor0N(gg, 0);
3030 auto t_m = get_ftensor1(K, 3 * rr, 0);
3031 for (int cc = 0; cc != row_nb_dofs / 3; ++cc) {
3032 const double b = a * t_row_base_fun * t_col_base_fun;
3033 t_m(i) += b;
3034 ++t_m;
3035 ++t_col_base_fun;
3036 }
3037
3038 ++t_row_base_fun;
3039 }
3040
3041 for (; rr != row_nb_base_functions; ++rr)
3042 ++t_row_base_fun;
3043
3044 ++t_w;
3045 }
3046
3048}
3049
3051 EntData &col_data) {
3053
3059
3060 int nb_integration_pts = row_data.getN().size1();
3061 int row_nb_dofs = row_data.getIndices().size();
3062 int col_nb_dofs = col_data.getIndices().size();
3063 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
3065
3066 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
3067
3068 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
3069
3070 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
3071
3072 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
3073
3074 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
3075
3076 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2));
3077 };
3078
3079 auto v = getVolume();
3080 auto t_w = getFTensor0IntegrationWeight();
3081
3082 int row_nb_base_functions = row_data.getN().size2();
3083 auto t_row_base_fun = row_data.getFTensor0N();
3084
3085 auto t_approx_P_adjoint_log_du_dP =
3086 dataAtPts->getFTensorAdjointPdUdP(nb_integration_pts);
3087
3088 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3089 double a = v * t_w;
3090 int rr = 0;
3091 for (; rr != row_nb_dofs / 6; ++rr) {
3092
3093 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
3094 auto t_m = get_ftensor3(K, 6 * rr, 0);
3095
3096 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3097 t_m(L, i) -=
3098 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(j)) *
3099 t_row_base_fun;
3100 ++t_col_base_fun;
3101 ++t_m;
3102 }
3103
3104 ++t_row_base_fun;
3105 }
3106 for (; rr != row_nb_base_functions; ++rr)
3107 ++t_row_base_fun;
3108 ++t_w;
3109 ++t_approx_P_adjoint_log_du_dP;
3110 }
3111
3113}
3114
3116 EntData &col_data) {
3118
3124
3125 int nb_integration_pts = row_data.getN().size1();
3126 int row_nb_dofs = row_data.getIndices().size();
3127 int col_nb_dofs = col_data.getIndices().size();
3128 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3130 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c), &m(r + 3, c), &m(r + 4, c),
3131 &m(r + 5, c));
3132 };
3133
3134 auto v = getVolume();
3135 auto t_w = getFTensor0IntegrationWeight();
3136 auto t_row_base_fun = row_data.getFTensor0N();
3137
3138 int row_nb_base_functions = row_data.getN().size2();
3139
3140 auto t_approx_P_adjoint_log_du_dP =
3141 dataAtPts->getFTensorAdjointPdUdP(nb_integration_pts);
3142
3143 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3144 double a = v * t_w;
3145 int rr = 0;
3146 for (; rr != row_nb_dofs / 6; ++rr) {
3147 auto t_m = get_ftensor2(K, 6 * rr, 0);
3148 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
3149 for (int cc = 0; cc != col_nb_dofs; ++cc) {
3150 t_m(L) -=
3151 a * (t_approx_P_adjoint_log_du_dP(i, j, L) * t_col_base_fun(i, j)) *
3152 t_row_base_fun;
3153 ++t_m;
3154 ++t_col_base_fun;
3155 }
3156 ++t_row_base_fun;
3157 }
3158 for (; rr != row_nb_base_functions; ++rr)
3159 ++t_row_base_fun;
3160 ++t_w;
3161 ++t_approx_P_adjoint_log_du_dP;
3162 }
3164}
3165
3167 EntData &col_data) {
3169
3172
3173 int nb_integration_pts = getGaussPts().size2();
3174 int row_nb_dofs = row_data.getIndices().size();
3175 int col_nb_dofs = col_data.getIndices().size();
3176 auto get_ftensor3 = [](MatrixDouble &m, const int r, const int c) {
3178
3179 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
3180
3181 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
3182
3183 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2),
3184
3185 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2),
3186
3187 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2),
3188
3189 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2)
3190
3191 );
3192 };
3193 FTensor::Index<'i', 3> i;
3194 FTensor::Index<'j', 3> j;
3195 FTensor::Index<'k', 3> k;
3196 FTensor::Index<'m', 3> m;
3197 FTensor::Index<'n', 3> n;
3198
3199 auto v = getVolume();
3200 auto t_w = getFTensor0IntegrationWeight();
3201 auto t_approx_P_adjoint_log_du_domega =
3202 dataAtPts->getFTensorAdjointPdUdOmega(nb_integration_pts);
3203
3204 int row_nb_base_functions = row_data.getN().size2();
3205 auto t_row_base_fun = row_data.getFTensor0N();
3206
3207 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3208 double a = v * t_w;
3209
3210 int rr = 0;
3211 for (; rr != row_nb_dofs / 6; ++rr) {
3212 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
3213 auto t_m = get_ftensor3(K, 6 * rr, 0);
3214 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3215 double v = a * t_row_base_fun * t_col_base_fun;
3216 t_m(L, k) -= v * t_approx_P_adjoint_log_du_domega(k, L);
3217 ++t_m;
3218 ++t_col_base_fun;
3219 }
3220 ++t_row_base_fun;
3221 }
3222
3223 for (; rr != row_nb_base_functions; ++rr)
3224 ++t_row_base_fun;
3225
3226 ++t_w;
3227 ++t_approx_P_adjoint_log_du_domega;
3228 }
3229
3231}
3232
3234 EntData &col_data) {
3236 int nb_integration_pts = getGaussPts().size2();
3237 int row_nb_dofs = row_data.getIndices().size();
3238 int col_nb_dofs = col_data.getIndices().size();
3239 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3241 size_symm>{
3242
3243 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2), &m(r + 0, c + 3),
3244 &m(r + 0, c + 4), &m(r + 0, c + 5),
3245
3246 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2), &m(r + 1, c + 3),
3247 &m(r + 1, c + 4), &m(r + 1, c + 5),
3248
3249 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2), &m(r + 2, c + 3),
3250 &m(r + 2, c + 4), &m(r + 2, c + 5)
3251
3252 };
3253 };
3254
3257
3258 auto v = getVolume();
3259 auto t_w = getFTensor0IntegrationWeight();
3260 auto t_levi_kirchhoff_du =
3261 dataAtPts->getFTensorLeviKirchhoffdLogStretch(nb_integration_pts);
3262 int row_nb_base_functions = row_data.getN().size2();
3263 auto t_row_base_fun = row_data.getFTensor0N();
3264 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3265 double a = v * t_w;
3266 int rr = 0;
3267 for (; rr != row_nb_dofs / 3; ++rr) {
3268 auto t_m = get_ftensor2(K, 3 * rr, 0);
3269 const double b = a * t_row_base_fun;
3270 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
3271 for (int cc = 0; cc != col_nb_dofs / size_symm; ++cc) {
3272 t_m(k, L) -= (b * t_col_base_fun) * t_levi_kirchhoff_du(k, L);
3273 ++t_m;
3274 ++t_col_base_fun;
3275 }
3276 ++t_row_base_fun;
3277 }
3278 for (; rr != row_nb_base_functions; ++rr) {
3279 ++t_row_base_fun;
3280 }
3281 ++t_w;
3282 ++t_levi_kirchhoff_du;
3283 }
3285}
3286
3288 EntData &col_data) {
3290
3297
3298 int nb_integration_pts = getGaussPts().size2();
3299 int row_nb_dofs = row_data.getIndices().size();
3300 int col_nb_dofs = col_data.getIndices().size();
3301 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3303
3304 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
3305
3306 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
3307
3308 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
3309
3310 );
3311 };
3312
3313 auto v = getVolume();
3314 auto t_w = getFTensor0IntegrationWeight();
3315
3316 int row_nb_base_functions = row_data.getN().size2();
3317 auto t_row_base_fun = row_data.getFTensor0N();
3318 auto t_levi_kirchhoff_dP =
3319 dataAtPts->getFTensorLeviKirchhoffP(nb_integration_pts);
3320
3321 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3322 double a = v * t_w;
3323 int rr = 0;
3324 for (; rr != row_nb_dofs / 3; ++rr) {
3325 double b = a * t_row_base_fun;
3326 auto t_col_base_fun = col_data.getFTensor1N<3>(gg, 0);
3327 auto t_m = get_ftensor2(K, 3 * rr, 0);
3328 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3329 t_m(m, i) -= b * (t_levi_kirchhoff_dP(m, i, k) * t_col_base_fun(k));
3330 ++t_m;
3331 ++t_col_base_fun;
3332 }
3333 ++t_row_base_fun;
3334 }
3335 for (; rr != row_nb_base_functions; ++rr) {
3336 ++t_row_base_fun;
3337 }
3338
3339 ++t_w;
3340 ++t_levi_kirchhoff_dP;
3341 }
3343}
3344
3346 EntData &col_data) {
3348 int nb_integration_pts = getGaussPts().size2();
3349 int row_nb_dofs = row_data.getIndices().size();
3350 int col_nb_dofs = col_data.getIndices().size();
3351
3352 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
3354 &m(r + 0, c), &m(r + 1, c), &m(r + 2, c));
3355 };
3356
3357 FTENSOR_INDEX(3, i);
3358 FTENSOR_INDEX(3, k);
3359 FTENSOR_INDEX(3, m);
3360
3361 auto v = getVolume();
3362 auto t_w = getFTensor0IntegrationWeight();
3363 auto t_levi_kirchoff_dP =
3364 dataAtPts->getFTensorLeviKirchhoffP(nb_integration_pts);
3365
3366 int row_nb_base_functions = row_data.getN().size2();
3367 auto t_row_base_fun = row_data.getFTensor0N();
3368
3369 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3370 double a = v * t_w;
3371 int rr = 0;
3372 for (; rr != row_nb_dofs / 3; ++rr) {
3373 double b = a * t_row_base_fun;
3374 auto t_col_base_fun = col_data.getFTensor2N<3, 3>(gg, 0);
3375 auto t_m = get_ftensor1(K, 3 * rr, 0);
3376 for (int cc = 0; cc != col_nb_dofs; ++cc) {
3377 t_m(m) -= b * (t_levi_kirchoff_dP(m, i, k) * t_col_base_fun(i, k));
3378 ++t_m;
3379 ++t_col_base_fun;
3380 }
3381 ++t_row_base_fun;
3382 }
3383
3384 for (; rr != row_nb_base_functions; ++rr) {
3385 ++t_row_base_fun;
3386 }
3387 ++t_w;
3388 ++t_levi_kirchoff_dP;
3389 }
3391}
3392
3394 EntData &col_data) {
3396 int nb_integration_pts = getGaussPts().size2();
3397 int row_nb_dofs = row_data.getIndices().size();
3398 int col_nb_dofs = col_data.getIndices().size();
3399 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3401
3402 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
3403
3404 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
3405
3406 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
3407
3408 );
3409 };
3410 FTensor::Index<'i', 3> i;
3411 FTensor::Index<'j', 3> j;
3412 FTensor::Index<'k', 3> k;
3413 FTensor::Index<'l', 3> l;
3414 FTensor::Index<'m', 3> m;
3415 FTensor::Index<'n', 3> n;
3416
3418
3419 auto v = getVolume();
3420 auto ts_a =
3421 (std::abs(alphaViscousR) > std::numeric_limits<double>::epsilon() ||
3422 std::abs(alphaViscousR0) > std::numeric_limits<double>::epsilon() ||
3423 std::abs(alphaViscousOmega) > std::numeric_limits<double>::epsilon() ||
3424 std::abs(alphaViscousOmega0) > std::numeric_limits<double>::epsilon())
3425 ? getTSa()
3426 : 0.0;
3427 auto t_w = getFTensor0IntegrationWeight();
3428 auto t_levi_kirchhoff0 =
3429 dataAtPts->getFTensorLeviKirchhoff0(nb_integration_pts);
3430 auto t_levi_kirchhoff_domega =
3431 dataAtPts->getFTensorLeviKirchhoffdOmega(nb_integration_pts);
3432 int row_nb_base_functions = row_data.getN().size2();
3433 auto t_row_base_fun = row_data.getFTensor0N();
3434 auto t_row_grad_fun = row_data.getFTensor1DiffN<3>();
3435
3436 // auto time_step = getTStimeStep();
3437 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3438 auto nrm_levi_kirchhoff0 = t_levi_kirchhoff0.l2();
3439 double a = v * t_w;
3440 double mass_coeff =
3441 (a * (alphaR + alphaR0 * nrm_levi_kirchhoff0)) +
3442 (a * (alphaViscousR + alphaViscousR0 * nrm_levi_kirchhoff0)) *
3443 (ts_a /*/ time_step*/);
3444 double grad_coeff =
3445 (a * (alphaOmega + alphaOmega0 * nrm_levi_kirchhoff0)) +
3446 (a * (alphaViscousOmega + alphaViscousOmega0 * nrm_levi_kirchhoff0)) *
3447 (ts_a /*/ time_step*/);
3448
3449 int rr = 0;
3450 for (; rr != row_nb_dofs / 3; ++rr) {
3451 auto t_m = get_ftensor2(K, 3 * rr, 0);
3452 const double row_mass = a * t_row_base_fun;
3453 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
3454 auto t_col_grad_fun = col_data.getFTensor1DiffN<3>(gg, 0);
3455 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3456 t_m(k, l) -= (row_mass * t_col_base_fun) * t_levi_kirchhoff_domega(k, l);
3457 t_m(k, l) += t_kd(k, l) * (mass_coeff * t_row_base_fun * t_col_base_fun);
3458 t_m(k, l) +=
3459 t_kd(k, l) * (grad_coeff * (t_row_grad_fun(i) * t_col_grad_fun(i)));
3460 ++t_m;
3461 ++t_col_base_fun;
3462 ++t_col_grad_fun;
3463 }
3464 ++t_row_base_fun;
3465 ++t_row_grad_fun;
3466 }
3467 for (; rr != row_nb_base_functions; ++rr) {
3468 ++t_row_base_fun;
3469 ++t_row_grad_fun;
3470 }
3471 ++t_w;
3472 ++t_levi_kirchhoff0;
3473 ++t_levi_kirchhoff_domega;
3474 }
3476}
3477
3478template <typename TInvD, typename TRotation>
3479auto getDiffSpatialGradientDP(TInvD &t_d_u_d_b, TRotation &t_R) {
3480 FTENSOR_INDEXES(SPACE_DIM, i, j, k, l, m, n);
3481 constexpr auto t_diff_sym = FTensor::DiffSymmetrize<double>();
3482
3484 t_d_b_d_p;
3485 t_d_b_d_p(i, j, k, l) = t_diff_sym(i, j, m, l) * t_R(k, m);
3486
3488 t_d_u_d_p;
3489 t_d_u_d_p(i, j, k, l) =
3490 t_d_u_d_b(i, j, m, n) * t_d_b_d_p(m, n, k, l);
3491
3493 t_d_h_d_p;
3494 t_d_h_d_p(i, j, k, l) = t_R(i, m) * t_d_u_d_p(m, j, k, l);
3495 return t_d_h_d_p;
3496}
3497
3499 EntData &col_data) {
3505 integrateImpl<size_symm * size_symm>(row_data, col_data));
3506 } else {
3507 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
3508 }
3510};
3511
3512template <int S>
3514 EntData &col_data) {
3516
3517 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3519
3520 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
3521
3522 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
3523
3524 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
3525
3526 );
3527 };
3528
3529 int nb_integration_pts = getGaussPts().size2();
3530 int row_nb_dofs = row_data.getIndices().size();
3531 int col_nb_dofs = col_data.getIndices().size();
3532
3533 auto v = getVolume();
3534 auto t_w = getFTensor0IntegrationWeight();
3535 int row_nb_base_functions = row_data.getN().size2() / 3;
3536
3541
3542 auto t_inv_D =
3543 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, S>(dataAtPts->matInvD);
3544 auto t_R = dataAtPts->getFTensorRotMat(nb_integration_pts);
3545
3546 auto t_row_base = row_data.getFTensor1N<3>();
3547 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3548 double a = v * t_w;
3549
3550 auto assemble = [&](auto &t_diff_h_p) {
3551 int rr = 0;
3552 for (; rr != row_nb_dofs / 3; ++rr) {
3553 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
3554 auto t_m = get_ftensor2(K, 3 * rr, 0);
3555 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3556 t_m(i, k) -=
3557 a * t_row_base(j) * (t_diff_h_p(i, j, k, l) * t_col_base(l));
3558 ++t_m;
3559 ++t_col_base;
3560 }
3561
3562 ++t_row_base;
3563 }
3564
3565 for (; rr != row_nb_base_functions; ++rr)
3566 ++t_row_base;
3567 };
3568
3571 auto t_diff_h_p = getDiffSpatialGradientDP(t_inv_D, t_R);
3572 assemble(t_diff_h_p);
3573 } else {
3574 assemble(t_inv_D);
3575 }
3576
3577 ++t_w;
3578 ++t_inv_D;
3579 ++t_R;
3580 }
3582}
3583
3586 EntData &col_data) {
3592 integrateImpl<size_symm * size_symm>(row_data, col_data));
3593 } else {
3594 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
3595 }
3597};
3598
3599template <int S>
3602 EntData &col_data) {
3604
3605 int nb_integration_pts = getGaussPts().size2();
3606 int row_nb_dofs = row_data.getIndices().size();
3607 int col_nb_dofs = col_data.getIndices().size();
3608
3609 auto v = getVolume();
3610 auto t_w = getFTensor0IntegrationWeight();
3611 int row_nb_base_functions = row_data.getN().size2() / 9;
3612
3617
3618 auto t_inv_D =
3619 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, S>(dataAtPts->matInvD);
3620 auto t_R = dataAtPts->getFTensorRotMat(nb_integration_pts);
3621
3622 auto t_row_base = row_data.getFTensor2N<3, 3>();
3623 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3624 double a = v * t_w;
3625
3626 auto assemble = [&](auto &t_diff_h_p) {
3627 int rr = 0;
3628 for (; rr != row_nb_dofs; ++rr) {
3629 auto t_col_base = col_data.getFTensor2N<3, 3>(gg, 0);
3630 for (int cc = 0; cc != col_nb_dofs; ++cc) {
3631 K(rr, cc) -= a * (t_row_base(i, j) *
3632 (t_diff_h_p(i, j, k, l) * t_col_base(k, l)));
3633 ++t_col_base;
3634 }
3635
3636 ++t_row_base;
3637 }
3638
3639 for (; rr != row_nb_base_functions; ++rr)
3640 ++t_row_base;
3641 };
3642
3645 auto t_diff_h_p = getDiffSpatialGradientDP(t_inv_D, t_R);
3646 assemble(t_diff_h_p);
3647 } else {
3648 assemble(t_inv_D);
3649 }
3650
3651 ++t_w;
3652 ++t_inv_D;
3653 ++t_R;
3654 }
3656}
3657
3659 EntData &col_data) {
3665 integrateImpl<size_symm * size_symm>(row_data, col_data));
3666 } else {
3667 MoFEMFunctionReturnHot(integrateImpl<0>(row_data, col_data));
3668 }
3670};
3671
3672template <int S>
3675 EntData &col_data) {
3677
3678 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
3680
3681 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2)
3682
3683 );
3684 };
3685
3686 int nb_integration_pts = getGaussPts().size2();
3687 int row_nb_dofs = row_data.getIndices().size();
3688 int col_nb_dofs = col_data.getIndices().size();
3689
3690 auto v = getVolume();
3691 auto t_w = getFTensor0IntegrationWeight();
3692 int row_nb_base_functions = row_data.getN().size2() / 9;
3693
3700
3701 auto t_inv_D =
3702 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, S>(dataAtPts->matInvD);
3703 auto t_R = dataAtPts->getFTensorRotMat(nb_integration_pts);
3704
3705 auto t_row_base = row_data.getFTensor2N<3, 3>();
3706 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3707 double a = v * t_w;
3708
3709 auto assemble = [&](auto &t_diff_h_p) {
3710 auto t_m = get_ftensor1(K, 0, 0);
3711 int rr = 0;
3712 for (; rr != row_nb_dofs; ++rr) {
3713 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
3714 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3715 t_m(k) -=
3716 a * (t_row_base(i, j) * t_diff_h_p(i, j, k, l)) *
3717 t_col_base(l);
3718 ++t_col_base;
3719 ++t_m;
3720 }
3721
3722 ++t_row_base;
3723 }
3724
3725 for (; rr != row_nb_base_functions; ++rr)
3726 ++t_row_base;
3727 };
3728
3731 auto t_diff_h_p = getDiffSpatialGradientDP(t_inv_D, t_R);
3732 assemble(t_diff_h_p);
3733 } else {
3734 assemble(t_inv_D);
3735 }
3736
3737 ++t_w;
3738 ++t_inv_D;
3739 ++t_R;
3740 }
3742}
3743
3745 EntData &col_data) {
3747
3748 auto get_ftensor1 = [](MatrixDouble &m, const int r, const int c) {
3750
3751 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2)
3752
3753 );
3754 };
3755
3756 int nb_integration_pts = getGaussPts().size2();
3757 int row_nb_dofs = row_data.getIndices().size();
3758 int col_nb_dofs = col_data.getIndices().size();
3759
3760 auto v = getVolume();
3761 auto t_w = getFTensor0IntegrationWeight();
3762 int row_nb_base_functions = row_data.getN().size2() / 9;
3763
3766
3767 auto t_row_base = row_data.getFTensor2N<3, 3>();
3768 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3769 double a = v * t_w;
3770
3771 auto t_m = get_ftensor1(K, 0, 0);
3772
3773 int rr = 0;
3774 for (; rr != row_nb_dofs; ++rr) {
3775 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
3776 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3777 t_m(k) += a * t_row_base(k, l) * t_col_base(l);
3778 ++t_col_base;
3779 ++t_m;
3780 }
3781
3782 ++t_row_base;
3783 }
3784
3785 for (; rr != row_nb_base_functions; ++rr)
3786 ++t_row_base;
3787 ++t_w;
3788 }
3789
3791}
3792
3794 EntData &col_data) {
3796
3803
3804 int nb_integration_pts = row_data.getN().size1();
3805 int row_nb_dofs = row_data.getIndices().size();
3806 int col_nb_dofs = col_data.getIndices().size();
3807
3808 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3810
3811 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2),
3812
3813 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2),
3814
3815 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2)
3816
3817 );
3818 };
3819
3820 auto v = getVolume();
3821 auto t_w = getFTensor0IntegrationWeight();
3822 int row_nb_base_functions = row_data.getN().size2() / 3;
3823 auto t_row_base_fun = row_data.getFTensor1N<3>();
3824
3825 auto t_h_domega = dataAtPts->getFTensorSmallHdOmega(nb_integration_pts);
3826
3827 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3828 double a = v * t_w;
3829
3830 int rr = 0;
3831 for (; rr != row_nb_dofs / 3; ++rr) {
3832
3834 t_PRT(i, k) = t_row_base_fun(j) * t_h_domega(i, j, k);
3835
3836 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
3837 auto t_m = get_ftensor2(K, 3 * rr, 0);
3838 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3839 t_m(i, j) -= (a * t_col_base_fun) * t_PRT(i, j);
3840 ++t_m;
3841 ++t_col_base_fun;
3842 }
3843
3844 ++t_row_base_fun;
3845 }
3846
3847 for (; rr != row_nb_base_functions; ++rr)
3848 ++t_row_base_fun;
3849 ++t_w;
3850 ++t_h_domega;
3851 }
3853}
3854
3857 EntData &col_data) {
3859
3866
3867 int nb_integration_pts = row_data.getN().size1();
3868 int row_nb_dofs = row_data.getIndices().size();
3869 int col_nb_dofs = col_data.getIndices().size();
3870
3871 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
3873 &m(r, c + 0), &m(r, c + 1), &m(r, c + 2));
3874 };
3875
3876 auto v = getVolume();
3877 auto t_w = getFTensor0IntegrationWeight();
3878 int row_nb_base_functions = row_data.getN().size2() / 9;
3879 auto t_row_base_fun = row_data.getFTensor2N<3, 3>();
3880
3881 auto t_h_domega = dataAtPts->getFTensorSmallHdOmega(nb_integration_pts);
3882 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3883 double a = v * t_w;
3884
3885 int rr = 0;
3886 for (; rr != row_nb_dofs; ++rr) {
3887
3889 t_PRT(k) = t_row_base_fun(i, j) * t_h_domega(i, j, k);
3890
3891 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
3892 auto t_m = get_ftensor2(K, rr, 0);
3893 for (int cc = 0; cc != col_nb_dofs / 3; ++cc) {
3894 t_m(j) -= (a * t_col_base_fun) * t_PRT(j);
3895 ++t_m;
3896 ++t_col_base_fun;
3897 }
3898
3899 ++t_row_base_fun;
3900 }
3901
3902 for (; rr != row_nb_base_functions; ++rr)
3903 ++t_row_base_fun;
3904
3905 ++t_w;
3906 ++t_h_domega;
3907 }
3909}
3910
3912 EntData &data) {
3914
3915 if (tagSense != getSkeletonSense())
3917
3918 auto get_tag = [&](auto name) {
3919 auto &mob = getPtrFE()->mField.get_moab();
3920 Tag tag;
3921 CHK_MOAB_THROW(mob.tag_get_handle(name, tag), "get tag");
3922 return tag;
3923 };
3924
3925 auto get_tag_value = [&](auto &&tag, int dim) {
3926 auto &mob = getPtrFE()->mField.get_moab();
3927 auto face = getSidePtrFE()->getFEEntityHandle();
3928 std::vector<double> value(dim);
3929 CHK_MOAB_THROW(mob.tag_get_data(tag, &face, 1, value.data()), "set tag");
3930 return value;
3931 };
3932
3933 auto create_tag = [this](const std::string tag_name, const int size) {
3934 double def_VAL[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
3935 Tag th;
3936 CHKERR postProcMesh.tag_get_handle(tag_name.c_str(), size, MB_TYPE_DOUBLE,
3937 th, MB_TAG_CREAT | MB_TAG_SPARSE,
3938 def_VAL);
3939 return th;
3940 };
3941
3942 Tag th_cauchy_streess = create_tag("CauchyStress", 9);
3943 Tag th_detF = create_tag("detF", 1);
3944 Tag th_traction = create_tag("traction", 3);
3945 Tag th_disp_error = create_tag("DisplacementError", 1);
3946
3947 Tag th_energy = create_tag("Energy", 1);
3948 Tag th_young_modulus = create_tag("YoungModulus", 1);
3949
3950 const auto nb_gauss_pts = getGaussPts().size2();
3951 auto t_w = dataAtPts->getFTensorSmallWL2(nb_gauss_pts);
3952 auto t_h = dataAtPts->getFTensorSmallH(nb_gauss_pts);
3953 auto t_approx_P = dataAtPts->getFTensorApproxP(nb_gauss_pts);
3954
3955 auto t_normal = getFTensor1NormalsAtGaussPts();
3956 auto t_disp = dataAtPts->getFTensorSmallWH1(nb_gauss_pts);
3957
3958 // auto sense = getSkeletonSense();
3959
3960 if (dataAtPts->energyAtPts.size() == 0) {
3961 // that is for case that energy is not calculated
3962 dataAtPts->energyAtPts.resize(nb_gauss_pts);
3963 dataAtPts->energyAtPts.clear();
3964 }
3965 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
3966 auto t_youngs_modulus = getFTensor0FromVec(dataAtPts->youngModulusAtPts);
3967
3968 auto next = [&]() {
3969 ++t_w;
3970 ++t_h;
3971 ++t_approx_P;
3972 ++t_normal;
3973 ++t_disp;
3974 ++t_youngs_modulus;
3975 ++t_energy;
3976 };
3977
3978 FTensor::Index<'i', 3> i;
3979 FTensor::Index<'j', 3> j;
3980 FTensor::Index<'k', 3> k;
3981 FTensor::Index<'l', 3> l;
3982
3983 auto set_float_precision = [](const double x) {
3984 if (std::abs(x) < std::numeric_limits<float>::epsilon())
3985 return 0.;
3986 else
3987 return x;
3988 };
3989
3990 // scalars
3991 auto save_scal_tag = [&](auto &th, auto v, const int gg) {
3993 v = set_float_precision(v);
3994 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1, &v);
3996 };
3997
3998 // vectors
3999 VectorDouble3 v(3);
4000 FTensor::Tensor1<FTensor::PackPtr<double *, 0>, 3> t_v(&v[0], &v[1], &v[2]);
4001 auto save_vec_tag = [&](auto &th, auto &t_d, const int gg) {
4003 t_v(i) = t_d(i);
4004 for (auto &a : v.data())
4005 a = set_float_precision(a);
4006 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
4007 &*v.data().begin());
4009 };
4010
4011 // tensors
4012
4013 MatrixDouble3by3 m(3, 3);
4015 &m(0, 0), &m(0, 1), &m(0, 2),
4016
4017 &m(1, 0), &m(1, 1), &m(1, 2),
4018
4019 &m(2, 0), &m(2, 1), &m(2, 2));
4020
4021 auto save_mat_tag = [&](auto &th, auto &t_d, const int gg) {
4023 t_m(i, j) = t_d(i, j);
4024 for (auto &v : m.data())
4025 v = set_float_precision(v);
4026 CHKERR postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
4027 &*m.data().begin());
4029 };
4030
4031 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
4032
4033 FTensor::Tensor1<double, 3> t_traction;
4034 t_traction(i) = t_approx_P(i, j) * t_normal(j) / t_normal.l2();
4035 // vectors
4036 t_traction(i) *= tagSense;
4037 CHKERR save_vec_tag(th_traction, t_traction, gg);
4038
4039 double u_error = sqrt((t_disp(i) - t_w(i)) * (t_disp(i) - t_w(i)));
4040 if (!std::isfinite(u_error))
4041 u_error = -1.;
4042 CHKERR save_scal_tag(th_disp_error, u_error, gg);
4043 CHKERR save_scal_tag(th_energy, t_energy, gg);
4045 CHKERR save_scal_tag(th_young_modulus, t_youngs_modulus, gg);
4046
4047 const double jac = determinantTensor3by3(t_h);
4049 t_cauchy(i, j) = (1. / jac) * (t_approx_P(i, k) * t_h(j, k));
4050 CHKERR save_mat_tag(th_cauchy_streess, t_cauchy, gg);
4051 CHKERR postProcMesh.tag_set_data(th_detF, &mapGaussPts[gg], 1, &jac);
4052
4053 next();
4054 }
4055
4057}
4058
4060 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
4061 std::vector<FieldSpace> spaces, std::string geom_field_name,
4062 boost::shared_ptr<Range> crack_front_edges_ptr) {
4064
4065 constexpr bool scale_l2 = false;
4066
4067 if (scale_l2) {
4068 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
4069 "Scale L2 Ainsworth Legendre base is not implemented");
4070 }
4071
4072 CHKERR MoFEM::AddHOOps<2, 3, 3>::add(pipeline, spaces, geom_field_name);
4073
4075}
4076
4078 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
4079 std::vector<FieldSpace> spaces, std::string geom_field_name,
4080 boost::shared_ptr<Range> crack_front_edges_ptr) {
4082
4083 constexpr bool scale_l2 = false;
4084
4085 if (scale_l2) {
4086 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
4087 "Scale L2 Ainsworth Legendre base is not implemented");
4088 }
4089
4090 CHKERR MoFEM::AddHOOps<2, 2, 3>::add(pipeline, spaces, geom_field_name);
4091
4093}
4094
4096 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
4097 std::vector<FieldSpace> spaces, std::string geom_field_name,
4098 boost::shared_ptr<Range> crack_front_edges_ptr,
4099 boost::shared_ptr<MatrixDouble> jac, boost::shared_ptr<VectorDouble> det,
4100 boost::shared_ptr<MatrixDouble> inv_jac) {
4102
4103 if (!geom_field_name.empty()) {
4105 auto jac = boost::make_shared<MatrixDouble>();
4106 auto det = boost::make_shared<VectorDouble>();
4107 pipeline.push_back(
4109 geom_field_name, jac));
4110 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
4111 pipeline.push_back(
4113 }
4114 }
4115
4116 constexpr bool scale_l2_ainsworth_legendre_base = false;
4117
4118 if (scale_l2_ainsworth_legendre_base) {
4119
4121 : public MoFEM::OpCalculateVectorFieldGradient<SPACE_DIM, SPACE_DIM> {
4122
4124
4125 OpCalculateVectorFieldGradient(const std::string &field_name,
4126 boost::shared_ptr<MatrixDouble> jac,
4127 boost::shared_ptr<Range> edges_ptr)
4128 : OP(field_name, jac), edgesPtr(edges_ptr) {}
4129
4130 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
4131
4132 auto ent = data.getFieldEntities().size()
4133 ? data.getFieldEntities()[0]->getEnt()
4134 : 0;
4135
4136 if (type == MBEDGE && edgesPtr->find(ent) != edgesPtr->end()) {
4137 return 0;
4138 } else {
4139 return OP::doWork(side, type, data);
4140 }
4141 };
4142
4143 private:
4144 boost::shared_ptr<Range> edgesPtr;
4145 };
4146
4147 if (!geom_field_name.empty()) {
4148 auto jac = boost::make_shared<MatrixDouble>();
4149 auto det = boost::make_shared<VectorDouble>();
4150 pipeline.push_back(new OpCalculateVectorFieldGradient(
4151 geom_field_name, jac,
4152 EshelbianCore::setSingularity ? crack_front_edges_ptr
4153 : boost::make_shared<Range>()));
4154 pipeline.push_back(new OpInvertMatrix<3>(jac, det, nullptr));
4155 pipeline.push_back(new OpScaleBaseBySpaceInverseOfMeasure(
4157 }
4158 }
4159
4160 CHKERR MoFEM::AddHOOps<3, 3, 3>::add(pipeline, spaces, geom_field_name, jac,
4161 det, inv_jac);
4162
4164}
4165
4166/**
4167 * @brief Caluclate face material force and normal pressure at gauss points
4168 *
4169 * @param side
4170 * @param type
4171 * @param data
4172 * @return MoFEMErrorCode
4173 *
4174 * Reconstruct the full gradient \f$U=\nabla u\f$ on a surface from the
4175 * symmetric part and the surface gradient.
4176 *
4177 * @details
4178 * Inputs:
4179 * - \c t_strain : \f$\varepsilon=\tfrac12(U+U^\top)\f$ (symmetric strain on
4180 * S),
4181 * - \c t_grad_u_gamma : \f$u^\Gamma = U P\f$ (right-projected/surface
4182 * gradient), with \f$P=I-\mathbf N\otimes\mathbf N\f$,
4183 * - \c t_normal : (possibly non‑unit) surface normal.
4184 *
4185 * Procedure (pointwise on S):
4186 * 1) Normalize the normal \f$\mathbf n=\mathbf N/\|\mathbf N\|\f$.
4187 * 2) Form the residual \f$R=\varepsilon-\operatorname{sym}(u^\Gamma)\f$, where
4188 * \f$\operatorname{sym}(A)=\tfrac12(A+A^\top)\f$.
4189 * 3) Recover the normal directional derivative (a vector)
4190 * \f$\mathbf v=\partial_{\mathbf n}u=2R\mathbf n-(\mathbf n^\top R\,\mathbf
4191 * n)\,\mathbf n\f$. 4) Assemble the full gradient \f$U = u^\Gamma + \mathbf
4192 * v\otimes \mathbf n\f$.
4193 *
4194 * Properties (sanity checks):
4195 * - \f$\tfrac12(U+U^\top)=\varepsilon\f$ (matches the given symmetric part),
4196 * - \f$U P = u^\Gamma\f$ (tangential/right-projected columns unchanged),
4197 * - Only the **normal column** is updated via \f$\mathbf v\otimes\mathbf n\f$.
4198 *
4199 * Mapping to variables in this snippet:
4200 * - \f$\varepsilon \leftrightarrow\f$ \c t_strain,
4201 * - \f$u^\Gamma \leftrightarrow\f$ \c t_grad_u_gamma,
4202 * - \f$\mathbf N \leftrightarrow\f$ \c t_normal (normalized into \c t_N),
4203 * - \f$R \leftrightarrow\f$ \c t_R,
4204 * - \f$U \leftrightarrow\f$ \c t_grad_u.
4205 *
4206 * @pre \c t_normal is nonzero; \c t_strain is symmetric.
4207 * @note All indices use Einstein summation; computation is local to the surface
4208 * point.
4209 *
4210 */
4212 EntData &data) {
4214
4227
4228 const auto nb_gauss_pts = getGaussPts().size2();
4230 dataAtPts->faceMaterialForceAtPts, nb_gauss_pts);
4231 dataAtPts->normalPressureAtPts.resize(nb_gauss_pts, false);
4232 if (getNinTheLoop() == 0) {
4233 dataAtPts->faceMaterialForceAtPts.clear();
4234 dataAtPts->normalPressureAtPts.clear();
4235 }
4236 auto loop_size = getLoopSize();
4237 if (loop_size == 1) {
4238 auto numebered_fe_ptr = getSidePtrFE()->numeredEntFiniteElementPtr;
4239 auto pstatus = numebered_fe_ptr->getPStatus();
4240 if (pstatus & (PSTATUS_SHARED | PSTATUS_MULTISHARED)) {
4241 loop_size = 2;
4242 }
4243 }
4244
4246
4247 auto t_normal = getFTensor1NormalsAtGaussPts();
4248 auto t_T = dataAtPts->getFTensorFaceMaterialForce(
4249 nb_gauss_pts); //< face material force
4250 auto t_p =
4251 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
4252 auto t_P = dataAtPts->getFTensorApproxP(nb_gauss_pts);
4253 auto t_u_gamma = dataAtPts->getFTensorSmallHybridDisp(nb_gauss_pts);
4254 auto t_grad_u_gamma = dataAtPts->getFTensorGradHybridDisp(nb_gauss_pts);
4255 auto t_strain = dataAtPts->getFTensorLogStretch(nb_gauss_pts);
4256 auto t_omega = dataAtPts->getFTensorRotAxis(nb_gauss_pts);
4257
4263
4264 auto next = [&]() {
4265 ++t_normal;
4266 ++t_P;
4267 // ++t_grad_P;
4268 ++t_omega;
4269 ++t_u_gamma;
4270 ++t_grad_u_gamma;
4271 ++t_strain;
4272 ++t_T;
4273 ++t_p;
4274 };
4275
4277 case GRIFFITH_FORCE:
4278 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
4279 t_N(I) = t_normal(I);
4280 t_N.normalize();
4281
4282 t_A(i, j) = levi_civita(i, j, k) * t_omega(k);
4283 t_R(i, k) = t_kd(i, k) + t_A(i, k);
4284 t_grad_u(i, j) = t_R(i, j) + t_strain(i, j);
4285
4286 t_T(I) += t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
4287 // note that works only for Hooke material, for nonlinear material we need
4288 // strain energy expressed by stress
4289 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2.) / loop_size;
4290
4291 t_p += t_N(I) *
4292 (t_N(J) * ((t_kd(i, I) + t_grad_u_gamma(i, I)) * t_P(i, J))) /
4293 loop_size;
4294
4295 next();
4296 }
4297 break;
4298 case GRIFFITH_SKELETON:
4299 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
4300
4301 // Normalize the normal
4302 t_N(I) = t_normal(I);
4303 t_N.normalize();
4304
4305 // R = ε − sym(u^Γ)
4306 t_R(i, j) =
4307 t_strain(i, j) - 0.5 * (t_grad_u_gamma(i, j) + t_grad_u_gamma(j, i));
4308
4309 // U = u^Γ + [2 R N − (Nᵀ R N) N] ⊗ N
4310 t_grad_u(i, J) =
4311 t_grad_u_gamma(i, J) +
4312 (2 * t_R(i, K) * t_N(K) - (t_R(k, L) * t_N(k) * t_N(L)) * t_N(i)) *
4313 t_N(J);
4314
4315 t_T(I) += t_N(J) * (t_grad_u(i, I) * t_P(i, J)) / loop_size;
4316 // note that works only for Hooke material, for nonlinear material we need
4317 // strain energy expressed by stress
4318 t_T(I) -= t_N(I) * ((t_strain(i, K) * t_P(i, K)) / 2.) / loop_size;
4319
4320 // calculate nominal face pressure
4321 t_p += t_N(I) *
4322 (t_N(J) * ((t_kd(i, I) + t_grad_u_gamma(i, I)) * t_P(i, J))) /
4323 loop_size;
4324
4325 next();
4326 }
4327 break;
4328
4329 default:
4330 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
4331 "Grffith energy release "
4332 "selector not implemented");
4333 };
4334
4335#ifndef NDEBUG
4336 auto side_fe_ptr = getSidePtrFE();
4337 auto side_fe_mi_ptr = side_fe_ptr->numeredEntFiniteElementPtr;
4338 auto pstatus = side_fe_mi_ptr->getPStatus();
4339 if (pstatus) {
4340 auto owner = side_fe_mi_ptr->getOwnerProc();
4341 MOFEM_LOG("SELF", Sev::noisy)
4342 << "OpFaceSideMaterialForce: owner proc is not 0, owner proc: " << owner
4343 << " " << getPtrFE()->mField.get_comm_rank() << " n in the loop "
4344 << getNinTheLoop() << " loop size " << getLoopSize();
4345 }
4346#endif // NDEBUG
4347
4349}
4350
4352 EntData &data) {
4354
4355#ifndef NDEBUG
4356 auto fe_mi_ptr = getFEMethod()->numeredEntFiniteElementPtr;
4357 auto pstatus = fe_mi_ptr->getPStatus();
4358 if (pstatus) {
4359 auto owner = fe_mi_ptr->getOwnerProc();
4360 MOFEM_LOG("SELF", Sev::noisy)
4361 << "OpFaceMaterialForce: owner proc is not 0, owner proc: " << owner
4362 << " " << getPtrFE()->mField.get_comm_rank();
4363 }
4364#endif // NDEBUG
4365
4367
4369 t_face_T(I) = 0.;
4370 double face_pressure = 0.;
4371 auto t_T = dataAtPts->getFTensorFaceMaterialForce(
4372 getGaussPts().size2()); //< face material force
4373 auto t_p =
4374 getFTensor0FromVec(dataAtPts->normalPressureAtPts); //< normal pressure
4375 auto t_w = getFTensor0IntegrationWeight();
4376 for (auto gg = 0; gg != getGaussPts().size2(); ++gg) {
4377 t_face_T(I) += t_w * t_T(I);
4378 face_pressure += t_w * t_p;
4379 ++t_w;
4380 ++t_T;
4381 ++t_p;
4382 }
4383 t_face_T(I) *= getMeasure();
4384 face_pressure *= getMeasure();
4385
4386 auto get_tag = [&](auto name, auto dim) {
4387 auto &moab = getPtrFE()->mField.get_moab();
4388 Tag tag;
4389 double def_val[] = {0., 0., 0.};
4390 CHK_MOAB_THROW(moab.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
4391 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
4392 "create tag");
4393 return tag;
4394 };
4395
4396 auto set_tag = [&](auto &&tag, auto ptr) {
4397 auto &moab = getPtrFE()->mField.get_moab();
4398 auto face = getPtrFE()->getFEEntityHandle();
4399 CHK_MOAB_THROW(moab.tag_set_data(tag, &face, 1, ptr), "set tag");
4400 };
4401
4402 set_tag(get_tag("MaterialForce", 3), &t_face_T(0));
4403 set_tag(get_tag("FacePressure", 1), &face_pressure);
4404
4406}
4407
4408template <typename OP_PTR>
4409std::tuple<std::string, MatrixDouble>
4411 const std::string block_name) {
4412
4413 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
4414
4415 auto ts_time = op_ptr->getTStime();
4416 auto ts_time_step = op_ptr->getTStimeStep();
4417
4420 ts_time_step = EshelbianCore::physicalDt;
4421 }
4422
4423 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
4424 MatrixDouble m_ref_normals = op_ptr->getNormalsAtGaussPts();
4425
4426 auto v_analytical_expr =
4427 analytical_expr_function(ts_time_step, ts_time, nb_gauss_pts,
4428 m_ref_coords, m_ref_normals, block_name);
4429
4430 if (PetscUnlikely(!v_analytical_expr.size2())) {
4432 "Analytical expression is empty or does not exist, "
4433 "check python file");
4434 }
4435
4436 return std::make_tuple(block_name, v_analytical_expr);
4437}
4438
4440 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
4441 boost::shared_ptr<MatrixDouble> vec, ScalarFun beta_coeff,
4442 boost::shared_ptr<Range> ents_ptr)
4443 : OP(broken_base_side_data, ents_ptr) {
4444 this->sourceVec = vec;
4445 this->betaCoeff = beta_coeff;
4446}
4447
4449 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
4450 ScalarFun beta_coeff, boost::shared_ptr<Range> ents_ptr)
4451 : OP(broken_base_side_data, ents_ptr) {
4452 this->sourceVec = boost::shared_ptr<MatrixDouble>();
4453 this->betaCoeff = beta_coeff;
4454}
4455
4457OpBrokenBaseTimesBrokenDisp::doWork(int row_side, EntityType row_type,
4458 EntitiesFieldData::EntData &row_data) {
4460
4461 if (OP::entsPtr) {
4462 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
4464 }
4465
4466#ifndef NDEBUG
4467 if (!brokenBaseSideData) {
4468 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
4469 }
4470#endif // NDEBUG
4471
4472 auto do_work_rhs = [this](int row_side, EntityType row_type,
4473 EntitiesFieldData::EntData &row_data) {
4475 // get number of dofs on row
4476 OP::nbRows = row_data.getIndices().size();
4477 if (!OP::nbRows)
4479 // get number of integration points
4480 OP::nbIntegrationPts = OP::getGaussPts().size2();
4481 // get row base functions
4482 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
4483 // resize and clear the right hand side vector
4484 OP::locF.resize(OP::nbRows, false);
4485 OP::locF.clear();
4486 // integrate local vector
4487 CHKERR this->iNtegrate(row_data);
4488 // assemble local vector
4489 CHKERR this->aSsemble(row_data);
4491 };
4492
4493 switch (OP::opType) {
4494 case OP::OPSPACE:
4495 for (auto &bd : *brokenBaseSideData) {
4496 this->sourceVec =
4497 boost::shared_ptr<MatrixDouble>(brokenBaseSideData, &bd.getFlux());
4498 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData());
4499 this->sourceVec.reset();
4500 }
4501 break;
4502 default:
4504 (std::string("wrong op type ") +
4505 OpBaseDerivativesBase::OpTypeNames[OP::opType])
4506 .c_str());
4507 }
4508
4510}
4511
4513 const std::string row_field,
4514 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
4515 ScalarFun beta_coeff, boost::shared_ptr<Range> ents_ptr)
4516 : OP(row_field, boost::shared_ptr<MatrixDouble>(), beta_coeff, ents_ptr),
4517 brokenBaseSideDataPtr(broken_base_side_data) {
4518 this->betaCoeff = beta_coeff;
4519}
4520
4524 for (auto &bd : (*brokenBaseSideDataPtr)) {
4525 this->sourceVec =
4526 boost::shared_ptr<MatrixDouble>(brokenBaseSideDataPtr, &bd.getFlux());
4527
4528#ifndef NDEBUG
4529 if (this->sourceVec->size2() != SPACE_DIM) {
4530 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4531 "Inconsistent size of the source vector");
4532 }
4533 if (this->sourceVec->size1() != OP::getGaussPts().size2()) {
4534 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4535 "Inconsistent size of the source vector");
4536 }
4537#endif // NDEBUG
4538
4539 CHKERR OP::iNtegrate(data);
4540
4541 this->sourceVec.reset();
4542 }
4544}
4545
4547 std::string row_field,
4548 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
4549 ScalarFun beta, const bool assmb_transpose, const bool only_transpose,
4550 boost::shared_ptr<Range> ents_ptr)
4551 : OP(row_field, broken_base_side_data, assmb_transpose, only_transpose,
4552 ents_ptr) {
4553 this->betaCoeff = beta;
4554 this->sYmm = false;
4555}
4556
4558 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
4559 ScalarFun beta, boost::shared_ptr<Range> ents_ptr)
4560 : OP(broken_base_side_data, ents_ptr) {
4561 this->sYmm = false;
4562 this->betaCoeff = beta;
4563 OP::assembleTranspose = false;
4564 OP::onlyTranspose = false;
4565}
4566
4568OpBrokenBaseBrokenBase::doWork(int row_side, EntityType row_type,
4569 EntitiesFieldData::EntData &row_data) {
4571
4572 if (OP::entsPtr) {
4573 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
4575 }
4576
4577#ifndef NDEBUG
4578 if (!brokenBaseSideData) {
4579 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
4580 }
4581#endif // NDEBUG
4582
4583 auto do_work_lhs = [this](int row_side, int col_side, EntityType row_type,
4584 EntityType col_type,
4586 EntitiesFieldData::EntData &col_data) {
4588
4589 auto check_if_assemble_transpose = [&] {
4590 if (this->sYmm) {
4591 if (OP::rowSide != OP::colSide || OP::rowType != OP::colType)
4592 return true;
4593 else
4594 return false;
4595 } else if (OP::assembleTranspose) {
4596 return true;
4597 }
4598 return false;
4599 };
4600
4601 OP::rowSide = row_side;
4602 OP::rowType = row_type;
4603 OP::colSide = col_side;
4604 OP::colType = col_type;
4605 OP::nbCols = col_data.getIndices().size();
4606 OP::locMat.resize(OP::nbRows, OP::nbCols, false);
4607 OP::locMat.clear();
4608 CHKERR this->iNtegrate(row_data, col_data);
4609 CHKERR this->aSsemble(row_data, col_data, check_if_assemble_transpose());
4611 };
4612
4613 switch (OP::opType) {
4614 case OP::OPSPACE:
4615
4616 for (auto &bd : *brokenBaseSideData) {
4617
4618#ifndef NDEBUG
4619 if (!bd.getData().getNSharedPtr(bd.getData().getBase())) {
4620 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4621 "base functions not set");
4622 }
4623#endif
4624
4625 OP::nbRows = bd.getData().getIndices().size();
4626 if (!OP::nbRows)
4628 OP::nbIntegrationPts = OP::getGaussPts().size2();
4629 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(bd.getData());
4630
4631 if (!OP::nbRows)
4633
4634 CHKERR do_work_lhs(
4635
4636 // side
4637 bd.getSide(), bd.getSide(),
4638
4639 // type
4640 bd.getType(), bd.getType(),
4641
4642 // row_data
4643 bd.getData(), bd.getData()
4644
4645 );
4646 }
4647
4648 break;
4649
4650 default:
4652 (std::string("wrong op type ") +
4653 OpBaseDerivativesBase::OpTypeNames[OP::opType])
4654 .c_str());
4655 }
4656
4658}
4659
4660} // namespace EshelbianPlasticity
Auxilary functions for Eshelbian plasticity.
Eshelbian plasticity interface.
std::string type
Lie algebra implementation.
#define FTENSOR_INDEXES(DIM,...)
#define FTENSOR_INDEX(DIM, I)
constexpr double a
constexpr int SPACE_DIM
Fourth-order symmetrization tensor.
Fourth-order differential tensor symmetric in both index pairs.
Kronecker Delta class symmetric.
Kronecker Delta class.
Mapping from symmetric tensor indices to packed storage index.
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
@ H1
continuous field
Definition definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_IMPOSSIBLE_CASE
Definition definitions.h:35
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_INVALID_DATA
Definition definitions.h:36
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
constexpr auto t_kd
boost::function< double(const double, const double, const double)> ScalarFun
Scalar function type.
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
MoFEM::TsCtx * ts_ctx
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
auto getMat(A &&t_val, B &&t_vec, Fun< double > f)
Get the Mat object.
auto getDiffMat(A &&t_val, B &&t_vec, Fun< double > f, Fun< double > d_f, const int nb)
Get the Diff Mat object.
auto getDiffSpatialGradientDP(TInvD &t_d_u_d_b, TRotation &t_R)
std::tuple< std::string, MatrixDouble > getAnalyticalExpr(OP_PTR op_ptr, MatrixDouble &analytical_expr, const std::string block_name)
MatrixDouble analytical_expr_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, MatrixDouble &m_ref_normals, const std::string block_name)
auto getDiffSpatialGradientDR(TInvD &t_d_u_d_b, TRotation &t_R, TDiffRotation &t_diff_R, TStress &t_P)
boost::shared_ptr< VectorDouble > VectorPtr
DataLayoutTraits< DataLayout::GaussByCoeffs > DL
Definition MatHuHu.hpp:33
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
decltype(GetFTensor2SymmetricFromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2SymmetricFromMatType
auto getFTensor2FromMat(M &data)
Get tensor rank 2 (matrix) form data matrix.
decltype(GetFTensor4FromMatImpl< Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor4FromMatType
decltype(GetFTensor4DdgFromMatImpl< Tensor_Dim01, Tensor_Dim23, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor4DdgFromMatType
auto getFTensor1FromMat(M &data, int rr=0, int cc=0)
Get tensor rank 1 (vector) form data matrix.
decltype(GetFTensor1FromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor1FromMatType
MoFEMErrorCode computeEigenValuesSymmetric(const MatrixDouble &mat, VectorDouble &eig, MatrixDouble &eigen_vec)
compute eigenvalues of a symmetric matrix using lapack dsyev
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
static auto determinantTensor3by3(T &t)
Calculate the determinant of a 3x3 matrix or a tensor of rank 2.
decltype(GetFTensor3FromMatImpl< Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor3FromMatType
decltype(GetFTensor2FromMatImpl< Tensor_Dim0, Tensor_Dim1, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2FromMatType
constexpr IntegrationType I
constexpr auto field_name
FTensor::Index< 'm', 3 > m
const int N
Definition speed_test.cpp:3
static enum StretchSelector stretchSelector
static PetscBool l2UserBaseScale
static enum StretchHandling stretchHandling
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static double physicalDt
static PetscBool physicalTimeFlg
static double currentPhysicalTime
static constexpr enum SymmetrySelector symmetrySelector
static boost::function< double(const double)> f
static PetscBool setSingularity
static bool hasNonHomogeneousMaterialBlock
static boost::function< double(const double)> d_f
static bool isNoStretch()
static enum EnergyReleaseSelector energyReleaseSelector
static boost::function< double(const double)> inv_f
static auto diffDiffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:110
static auto diffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:105
static auto exp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:69
Add operators pushing bases from local to physical configuration.
std::array< bool, MBMAXTYPE > doEntities
If true operator is executed for entity.
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::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
const VectorFieldEntities & getFieldEntities() const
Get field entities (const version)
auto getFTensor2N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
auto getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorDouble & getFieldData() const
Get DOF values on entity.
auto getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
EntityHandle getFEEntityHandle() const
Return finite element entity handle.
MatrixDouble & getCoordsAtGaussPts()
Gauss points and weight, matrix (nb. of points x 3)
auto getFTensor0IntegrationWeight()
Get integration weights.
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Operator for inverting matrices at integration points.
Scale base functions by inverses of measure of element.
static constexpr Switches CtxSetTime
Time value switch.
@ CTX_TSSETIJACOBIAN
Setting up implicit Jacobian.
MoFEMErrorCode iNtegrate(EntData &data)
MatrixDouble K
local tangent matrix
VectorDouble nF
local right hand side vector
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
MoFEMErrorCode assemble(int row_side, int col_side, EntityType row_type, EntityType col_type, EntData &row_data, EntData &col_data)
boost::shared_ptr< AnalyticalTractionBcVec > bcData
boost::shared_ptr< double > piolaScalePtr
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
OpBrokenBaseBrokenBase(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, ScalarFun beta, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
OpBrokenBaseTimesBrokenDisp(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, ScalarFun beta_coeff=[](double, double, double) constexpr { return 1;}, boost::shared_ptr< Range > ents_ptr=nullptr)
OpBrokenBaseTimesHybridDisp(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< MatrixDouble > vec, ScalarFun beta_coeff=[](double, double, double) constexpr { return 1;}, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
boost::shared_ptr< double > piolaScalePtr
MoFEMErrorCode iNtegrate(EntData &data)
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
boost::shared_ptr< PressureBcVec > bcData
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
boost::shared_ptr< double > piolaScalePtr
boost::shared_ptr< TractionBcVec > bcData
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.
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
MoFEMErrorCode doWork(int side, EntityType type, EntData &data) override
Operator for linear form, usually to calculate values on right hand side.
boost::shared_ptr< ExternalStrainVec > externalStrainVecPtr
OpCalculateExternalPressure(VectorPtr external_pressure_ptr, boost::shared_ptr< ExternalStrainVec > external_strain_vec_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
std::array< double, 6 > & reactionVec
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Operator for linear form, usually to calculate values on right hand side.
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Caluclate face material force and normal pressure at gauss points.
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpHybridBaseTimesBrokenDisp(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, ScalarFun beta_coeff, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenBaseSideDataPtr
OpHyrbridBaseBrokenBase(std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, ScalarFun beta, const bool assmb_transpose, const bool only_transpose, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &data)
std::vector< EntityHandle > & mapGaussPts
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode integrate(EntData &data)
MoFEMErrorCode integrate(EntData &data)
MoFEMErrorCode integrate(EntData &data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrateImpl(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrateImpl(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrateImpl(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &data)
MoFEMErrorCode integrate(EntData &row_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &data)
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, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
MoFEMErrorCode iNtegrate(EntData &data)
double scale
Definition plastic.cpp:124
constexpr auto size_symm
Definition plastic.cpp:42