v0.16.0
Loading...
Searching...
No Matches
HenckyOps.hpp
Go to the documentation of this file.
1/**
2 * \file HenckyOps.hpp
3 * \example mofem/tutorials/vec-2_nonlinear_elasticity/src/HenckyOps.hpp
4 *
5 * @copyright Copyright (c) 2023
6 */
7
8#ifndef __HENCKY_OPS_HPP__
9#define __HENCKY_OPS_HPP__
10
11namespace HenckyOps {
12
13const double eps = std::sqrt(std::numeric_limits<double>::epsilon());
14
15auto f = [](double v) { return 0.5 * std::log(v); };
16auto d_f = [](double v) { return 0.5 / v; };
17auto dd_f = [](double v) { return -0.5 / (v * v); };
18
19inline bool is_eq(const double &a, const double &b) {
20 const auto abs_max = std::max(1., std::max(std::abs(a), std::abs(b)));
21 return std::abs(a - b) <= eps * abs_max;
22};
23
24template <int DIM> inline auto get_uniq_nb(double *ptr) {
25 std::array<double, DIM> tmp;
26 std::copy(ptr, ptr + DIM, tmp.begin());
27 std::sort(tmp.begin(), tmp.end());
28 return std::distance(tmp.begin(), std::unique(tmp.begin(), tmp.end(), is_eq));
29};
30
31template <int DIM>
34 static_assert(DIM == 3, "sort_eigen_vals expects three eigenvalues");
35
36 int i = 0, j = 1, k = 2;
37
38 if (is_eq(eig(0), eig(1))) {
39 i = 0;
40 j = 2;
41 k = 1;
42 } else if (is_eq(eig(0), eig(2))) {
43 i = 0;
44 j = 1;
45 k = 2;
46 } else if (is_eq(eig(1), eig(2))) {
47 i = 1;
48 j = 0;
49 k = 2;
50 }
51
53 eigen_vec(i, 0), eigen_vec(i, 1), eigen_vec(i, 2),
54
55 eigen_vec(j, 0), eigen_vec(j, 1), eigen_vec(j, 2),
56
57 eigen_vec(k, 0), eigen_vec(k, 1), eigen_vec(k, 2)};
58
59 FTensor::Tensor1<double, DIM> eig_c{eig(i), eig(j), eig(k)};
60
61 {
62 FTensor::Index<'i', DIM> i;
63 FTensor::Index<'j', DIM> j;
64 eig(i) = eig_c(i);
65 eigen_vec(i, j) = eigen_vec_c(i, j);
66 }
67};
68
69struct CommonData : public boost::enable_shared_from_this<CommonData> {
70 boost::shared_ptr<MatrixDouble> matGradPtr;
71 boost::shared_ptr<MatrixDouble> matDPtr;
72 boost::shared_ptr<MatrixDouble> matLogCPlastic;
73
74 MatrixDouble matEigVal;
75 MatrixDouble matEigVec;
76 MatrixDouble matLogC;
77 MatrixDouble matLogCdC;
78 MatrixDouble matFirstPiolaStress;
80 MatrixDouble matHenckyStress;
81 MatrixDouble matTangent;
82
83 inline auto getMatFirstPiolaStress() {
84 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
86 }
87
88 inline auto getMatHenckyStress() {
89 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
91 }
92
93 inline auto getMatLogC() {
94 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &matLogC);
95 }
96
97 inline auto getMatTangent() {
98 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &matTangent);
99 }
100};
101
102template <int DIM, IntegrationType I, typename DomainEleOp>
104
105template <int DIM, IntegrationType I, typename DomainEleOp>
107
108template <int DIM, IntegrationType I, typename DomainEleOp>
110
111template <int DIM, IntegrationType I, typename DomainEleOp, int S>
113
114template <int DIM, IntegrationType I, typename DomainEleOp, int S>
116
117template <int DIM, IntegrationType I, typename DomainEleOp, int S>
119
120template <int DIM, IntegrationType I, typename DomainEleOp, int S>
122
123template <int DIM, IntegrationType I, typename DomainEleOp, int S>
125
126template <int DIM, IntegrationType I, typename DomainEleOp, int S>
128
129template <int DIM, IntegrationType I, typename DomainEleOp, int S>
131
132template <int DIM, typename DomainEleOp>
134
136 boost::shared_ptr<CommonData> common_data)
138 commonDataPtr(common_data) {
139 std::fill(&DomainEleOp::doEntities[MBEDGE],
140 &DomainEleOp::doEntities[MBMAXTYPE], false);
141 }
142
143 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
145
146 FTensor::Index<'i', DIM> i;
147 FTensor::Index<'j', DIM> j;
148 FTensor::Index<'k', DIM> k;
149
150 [[maybe_unused]] constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
151 // const size_t nb_gauss_pts = matGradPtr->size2();
152 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
153
154 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
155
156 commonDataPtr->matEigVal.resize(nb_gauss_pts, DIM, false);
157 commonDataPtr->matEigVec.resize(nb_gauss_pts, DIM * DIM, false);
158 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
159 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
160
161 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
162
167
168 F(i, j) = t_grad(i, j) + t_kd(i, j);
169 C(i, j) = F(k, i) ^ F(k, j);
170
171 for (int ii = 0; ii != DIM; ii++)
172 for (int jj = 0; jj != DIM; jj++)
173 eigen_vec(ii, jj) = C(ii, jj);
174
175 CHKERR computeEigenValuesSymmetric(eigen_vec, eig);
176 for (auto ii = 0; ii != DIM; ++ii)
177 eig(ii) = std::max(eps, eig(ii));
178
179 // rare case when two eigen values are equal
180 auto nb_uniq = get_uniq_nb<DIM>(&eig(0));
181 if constexpr (DIM == 3) {
182 if (nb_uniq == 2) {
183 sort_eigen_vals<DIM>(eig, eigen_vec);
184 }
185 }
186
187 t_eig_val(i) = eig(i);
188 t_eig_vec(i, j) = eigen_vec(i, j);
189
190#ifndef NDEBUG
191 auto nb_uniq_test = get_uniq_nb<DIM>(&t_eig_val(0));
192 if (nb_uniq_test != nb_uniq) {
193 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
194 "Inconsistent number of unique eigen values %ld != %ld",
195 nb_uniq, nb_uniq_test);
196 }
197#endif
198
199 ++t_grad;
200 ++t_eig_val;
201 ++t_eig_vec;
202 }
203
205 }
206
207private:
208 boost::shared_ptr<CommonData> commonDataPtr;
209};
210
211template <int DIM, typename DomainEleOp>
212struct OpCalculateLogCImpl<DIM, GAUSS, DomainEleOp> : public DomainEleOp {
213
215 boost::shared_ptr<CommonData> common_data)
217 commonDataPtr(common_data) {
218 std::fill(&DomainEleOp::doEntities[MBEDGE],
219 &DomainEleOp::doEntities[MBMAXTYPE], false);
220 }
221
222 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
224
225 FTensor::Index<'i', DIM> i;
226 FTensor::Index<'j', DIM> j;
227
228 // const size_t nb_gauss_pts = matGradPtr->size2();
229 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
230 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
231 commonDataPtr->matLogC.resize(nb_gauss_pts, size_symm, false);
232
233 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
234 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
235
236 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
237
238 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
239 t_logC(i, j) = EigenMatrix::getMat(t_eig_val, t_eig_vec, f)(i, j);
240 ++t_eig_val;
241 ++t_eig_vec;
242 ++t_logC;
243 }
244
246 }
247
248private:
249 boost::shared_ptr<CommonData> commonDataPtr;
250};
251
252template <int DIM, typename DomainEleOp>
253struct OpCalculateLogC_dCImpl<DIM, GAUSS, DomainEleOp> : public DomainEleOp {
254
256 boost::shared_ptr<CommonData> common_data)
258 commonDataPtr(common_data) {
259 std::fill(&DomainEleOp::doEntities[MBEDGE],
260 &DomainEleOp::doEntities[MBMAXTYPE], false);
261 }
262
263 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
265
266 FTensor::Index<'i', DIM> i;
267 FTensor::Index<'j', DIM> j;
268 FTensor::Index<'k', DIM> k;
269 FTensor::Index<'l', DIM> l;
270
271 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
272 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
273 commonDataPtr->matLogCdC.resize(nb_gauss_pts, size_symm * size_symm, false);
274 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
275 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
276 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
277
278 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
279 // rare case when two eigen values are equal
280 auto nb_uniq = get_uniq_nb<DIM>(&t_eig_val(0));
281 t_logC_dC(i, j, k, l) =
282 2 * EigenMatrix::getDiffMat(t_eig_val, t_eig_vec, f, d_f,
283 nb_uniq)(i, j, k, l);
284
285 ++t_logC_dC;
286 ++t_eig_val;
287 ++t_eig_vec;
288 }
289
291 }
292
293private:
294 boost::shared_ptr<CommonData> commonDataPtr;
295};
296
297template <int DIM, typename DomainEleOp, int S>
299 : public DomainEleOp {
300
302 boost::shared_ptr<CommonData> common_data)
304 commonDataPtr(common_data) {
305 std::fill(&DomainEleOp::doEntities[MBEDGE],
306 &DomainEleOp::doEntities[MBMAXTYPE], false);
307 }
308
309 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
311
312 FTensor::Index<'i', DIM> i;
313 FTensor::Index<'j', DIM> j;
314 FTensor::Index<'k', DIM> k;
315 FTensor::Index<'l', DIM> l;
316
317 // const size_t nb_gauss_pts = matGradPtr->size2();
318 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
319 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
320 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
321 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
322 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
323 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
324
325 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
326 t_T(i, j) = t_D(i, j, k, l) * t_logC(k, l);
327 ++t_logC;
328 ++t_T;
329 ++t_D;
330 }
331
333 }
334
335private:
336 boost::shared_ptr<CommonData> commonDataPtr;
337};
338
339template <int DIM, typename DomainEleOp, int S>
341 : public DomainEleOp {
342
344 const std::string field_name, boost::shared_ptr<VectorDouble> temperature,
345 boost::shared_ptr<CommonData> common_data,
346 boost::shared_ptr<VectorDouble> coeff_expansion_ptr,
347 boost::shared_ptr<double> ref_temp_ptr)
348 : DomainEleOp(field_name, DomainEleOp::OPROW), tempPtr(temperature),
349 commonDataPtr(common_data), coeffExpansionPtr(coeff_expansion_ptr),
350 refTempPtr(ref_temp_ptr) {
351 std::fill(&DomainEleOp::doEntities[MBEDGE],
352 &DomainEleOp::doEntities[MBMAXTYPE], false);
353 }
354
355 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
357
358 FTensor::Index<'i', DIM> i;
359 FTensor::Index<'j', DIM> j;
360 FTensor::Index<'k', DIM> k;
361 FTensor::Index<'l', DIM> l;
362
363 [[maybe_unused]] constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
364
365 // const size_t nb_gauss_pts = matGradPtr->size2();
366 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
367 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
368 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
369 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
370 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
371 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
372 commonDataPtr->matFirstPiolaStress.resize(nb_gauss_pts, DIM * DIM, false);
373 commonDataPtr->matSecondPiolaStress.resize(nb_gauss_pts, size_symm, false);
374 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
375 auto t_P = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matFirstPiolaStress);
376 auto t_S =
377 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
378 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
379 auto t_temp = getFTensor0FromVec(*tempPtr);
380
382 t_coeff_exp(i, j) = 0;
383 for (auto d = 0; d != SPACE_DIM; ++d) {
384 t_coeff_exp(d, d) = (*coeffExpansionPtr)[d];
385 }
386
387 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
388#ifdef HENCKY_SMALL_STRAIN
389 t_P(i, j) = t_D(i, j, k, l) *
390 (t_grad(k, l) - t_coeff_exp(k, l) * (t_temp - (*refTempPtr)));
391#else
392 t_T(i, j) = t_D(i, j, k, l) *
393 (t_logC(k, l) - t_coeff_exp(k, l) * (t_temp - (*refTempPtr)));
395 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
396 t_S(k, l) = t_T(i, j) * t_logC_dC(i, j, k, l);
397 t_P(i, l) = t_F(i, k) * t_S(k, l);
398#endif
399 ++t_grad;
400 ++t_logC;
401 ++t_logC_dC;
402 ++t_P;
403 ++t_T;
404 ++t_S;
405 ++t_D;
406 ++t_temp;
407 }
408
410 }
411
412private:
413 boost::shared_ptr<CommonData> commonDataPtr;
414 boost::shared_ptr<VectorDouble> tempPtr;
415 boost::shared_ptr<VectorDouble> coeffExpansionPtr;
416 boost::shared_ptr<double> refTempPtr;
417};
418
419template <int DIM, typename DomainEleOp, int S>
421 : public DomainEleOp {
422
424 boost::shared_ptr<CommonData> common_data,
425 boost::shared_ptr<MatrixDouble> mat_D_ptr,
426 const double scale = 1)
427 : DomainEleOp(field_name, DomainEleOp::OPROW), commonDataPtr(common_data),
428 scaleStress(scale), matDPtr(mat_D_ptr) {
429 std::fill(&DomainEleOp::doEntities[MBEDGE],
430 &DomainEleOp::doEntities[MBMAXTYPE], false);
431
432 matLogCPlastic = commonDataPtr->matLogCPlastic;
433 }
434
435 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
437
438 FTensor::Index<'i', DIM> i;
439 FTensor::Index<'j', DIM> j;
440 FTensor::Index<'k', DIM> k;
441 FTensor::Index<'l', DIM> l;
442
443 // const size_t nb_gauss_pts = matGradPtr->size2();
444 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
445 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*matDPtr);
446 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
447 auto t_logCPlastic = getFTensor2SymmetricFromMat<DIM>(*matLogCPlastic);
448 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
449 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
450 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
451
452 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
453 t_T(i, j) = t_D(i, j, k, l) * (t_logC(k, l) - t_logCPlastic(k, l));
454 t_T(i, j) /= scaleStress;
455 ++t_logC;
456 ++t_T;
457 ++t_D;
458 ++t_logCPlastic;
459 }
460
462 }
463
464private:
465 boost::shared_ptr<CommonData> commonDataPtr;
466 boost::shared_ptr<MatrixDouble> matDPtr;
467 boost::shared_ptr<MatrixDouble> matLogCPlastic;
468 const double scaleStress;
469};
470
471template <int DIM, typename DomainEleOp, int S>
473 : public DomainEleOp {
474
476 boost::shared_ptr<CommonData> common_data)
478 commonDataPtr(common_data) {
479 std::fill(&DomainEleOp::doEntities[MBEDGE],
480 &DomainEleOp::doEntities[MBMAXTYPE], false);
481 }
482
483 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
485
486 FTensor::Index<'i', DIM> i;
487 FTensor::Index<'j', DIM> j;
488 FTensor::Index<'k', DIM> k;
489 FTensor::Index<'l', DIM> l;
490
491 [[maybe_unused]] constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
492
493 // const size_t nb_gauss_pts = matGradPtr->size2();
494 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
495#ifdef HENCKY_SMALL_STRAIN
496 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
497#endif
498 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
499 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
500 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
501 commonDataPtr->matFirstPiolaStress.resize(nb_gauss_pts, DIM * DIM, false);
502 commonDataPtr->matSecondPiolaStress.resize(nb_gauss_pts, size_symm, false);
503 auto t_P = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matFirstPiolaStress);
504 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
505 auto t_S =
506 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
507 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
508
509 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
510
511#ifdef HENCKY_SMALL_STRAIN
512 t_P(i, j) = t_D(i, j, k, l) * t_grad(k, l);
513#else
515 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
516 t_S(k, l) = t_T(i, j) * t_logC_dC(i, j, k, l);
517 t_P(i, l) = t_F(i, k) * t_S(k, l);
518#endif
519
520 ++t_grad;
521 ++t_logC;
522 ++t_logC_dC;
523 ++t_P;
524 ++t_T;
525 ++t_S;
526#ifdef HENCKY_SMALL_STRAIN
527 ++t_D;
528#endif
529 }
530
532 }
533
534private:
535 boost::shared_ptr<CommonData> commonDataPtr;
536};
537
538template <int DIM, typename DomainEleOp, int S>
539struct OpHenckyTangentImpl<DIM, GAUSS, DomainEleOp, S> : public DomainEleOp {
541 boost::shared_ptr<CommonData> common_data,
542 boost::shared_ptr<MatrixDouble> mat_D_ptr = nullptr)
544 commonDataPtr(common_data) {
545 std::fill(&DomainEleOp::doEntities[MBEDGE],
546 &DomainEleOp::doEntities[MBMAXTYPE], false);
547 if (mat_D_ptr)
548 matDPtr = mat_D_ptr;
549 else
550 matDPtr = commonDataPtr->matDPtr;
551 }
552
553 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
555
556 FTensor::Index<'i', DIM> i;
557 FTensor::Index<'j', DIM> j;
558 FTensor::Index<'k', DIM> k;
559 FTensor::Index<'l', DIM> l;
560 FTensor::Index<'m', DIM> m;
561 FTensor::Index<'n', DIM> n;
562 FTensor::Index<'o', DIM> o;
563 FTensor::Index<'p', DIM> p;
564
565 [[maybe_unused]] constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
566 // const size_t nb_gauss_pts = matGradPtr->size2();
567 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
568 commonDataPtr->matTangent.resize(nb_gauss_pts, DIM * DIM * DIM * DIM);
569 auto dP_dF =
570 getFTensor4FromMat<DIM, DIM, DIM, DIM>(commonDataPtr->matTangent);
571
572 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*matDPtr);
573 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
574 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
575 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
576 auto t_S =
577 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
578 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
579 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
580
581 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
582
583#ifdef HENCKY_SMALL_STRAIN
584 dP_dF(i, j, k, l) = t_D(i, j, k, l);
585#else
586
588 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
589
590 // rare case when two eigen values are equal
591 auto nb_uniq = get_uniq_nb<DIM>(&t_eig_val(0));
593 dC_dF(i, j, k, l) = (t_kd(i, l) * t_F(k, j)) + (t_kd(j, l) * t_F(k, i));
594
595 auto TL = EigenMatrix::getDiffDiffMat(t_eig_val, t_eig_vec, f, d_f, dd_f,
596 t_T, nb_uniq);
597 TL(i, j, k, l) *= 4;
598 FTensor::Ddg<double, DIM, DIM> P_D_P_plus_TL;
599 P_D_P_plus_TL(i, j, k, l) =
600 TL(i, j, k, l) +
601 (t_logC_dC(i, j, o, p) * t_D(o, p, m, n)) * t_logC_dC(m, n, k, l);
602 P_D_P_plus_TL(i, j, k, l) *= 0.5;
603 dP_dF(i, j, m, n) = t_kd(i, m) * (t_kd(k, n) * t_S(k, j));
604 dP_dF(i, j, m, n) +=
605 t_F(i, k) * (P_D_P_plus_TL(k, j, o, p) * dC_dF(o, p, m, n));
606
607#endif
608
609 ++dP_dF;
610
611 ++t_grad;
612 ++t_eig_val;
613 ++t_eig_vec;
614 ++t_logC_dC;
615 ++t_S;
616 ++t_T;
617 ++t_D;
618 }
619
621 }
622
623private:
624 boost::shared_ptr<CommonData> commonDataPtr;
625 boost::shared_ptr<MatrixDouble> matDPtr;
626};
627
628template <int DIM, typename AssemblyDomainEleOp, int S>
630 : public AssemblyDomainEleOp {
632 const std::string row_field_name, const std::string col_field_name,
633 boost::shared_ptr<CommonData> elastic_common_data_ptr,
634 boost::shared_ptr<VectorDouble> coeff_expansion_ptr);
635
636 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
637 EntitiesFieldData::EntData &col_data);
638
639private:
640 boost::shared_ptr<CommonData> elasticCommonDataPtr;
641 boost::shared_ptr<VectorDouble> coeffExpansionPtr;
642};
643
644template <int DIM, typename AssemblyDomainEleOp, int S>
647 const std::string row_field_name, const std::string col_field_name,
648 boost::shared_ptr<CommonData> elastic_common_data_ptr,
649 boost::shared_ptr<VectorDouble> coeff_expansion_ptr)
650 : AssemblyDomainEleOp(row_field_name, col_field_name,
651 AssemblyDomainEleOp::OPROWCOL),
652 elasticCommonDataPtr(elastic_common_data_ptr),
653 coeffExpansionPtr(coeff_expansion_ptr) {
654 this->sYmm = false;
655}
656
657template <int DIM, typename AssemblyDomainEleOp, int S>
658MoFEMErrorCode
660 iNtegrate(EntitiesFieldData::EntData &row_data,
661 EntitiesFieldData::EntData &col_data) {
663
664 auto &locMat = AssemblyDomainEleOp::locMat;
665
666 const auto nb_integration_pts = row_data.getN().size1();
667 const auto nb_row_base_functions = row_data.getN().size2();
668 auto t_w = this->getFTensor0IntegrationWeight();
669
670 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
671 auto t_row_diff_base = row_data.getFTensor1DiffN<DIM>();
672 auto t_D = getFTensor4DdgFromMat<DIM, DIM, 0>(*elasticCommonDataPtr->matDPtr);
673 auto t_grad =
674 getFTensor2FromMat<DIM, DIM>(*(elasticCommonDataPtr->matGradPtr));
675 auto t_logC_dC =
676 getFTensor4DdgFromMat<DIM, DIM>(elasticCommonDataPtr->matLogCdC);
679
680 FTensor::Index<'i', DIM> i;
681 FTensor::Index<'j', DIM> j;
682 FTensor::Index<'k', DIM> k;
683 FTensor::Index<'l', DIM> l;
684 FTensor::Index<'m', DIM> m;
685 FTensor::Index<'n', DIM> n;
686 FTensor::Index<'o', DIM> o;
687
689 t_coeff_exp(i, j) = 0;
690 for (auto d = 0; d != SPACE_DIM; ++d) {
691 t_coeff_exp(d, d) = (*coeffExpansionPtr)[d];
692 }
693
694 t_eigen_strain(i, j) = (t_D(i, j, k, l) * t_coeff_exp(k, l));
695
696 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
697
698 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
699
700 double alpha = this->getMeasure() * t_w;
701 auto rr = 0;
702 for (; rr != AssemblyDomainEleOp::nbRows / DIM; ++rr) {
703 auto t_mat =
704 getFTensor1FromMat<DIM, 1,
705 DataLayoutTraits<DataLayout::CoeffsByGauss>>(
706 locMat, rr * DIM);
707 auto t_col_base = col_data.getFTensor0N(gg, 0);
708 for (auto cc = 0; cc != AssemblyDomainEleOp::nbCols; cc++) {
709#ifdef HENCKY_SMALL_STRAIN
710 t_mat(i) -=
711 (t_row_diff_base(j) * t_eigen_strain(i, j)) * (t_col_base * alpha);
712#else
713 t_mat(i) -= (t_row_diff_base(j) *
714 (t_F(i, o) * ((t_D(m, n, k, l) * t_coeff_exp(k, l)) *
715 t_logC_dC(m, n, o, j)))) *
716 (t_col_base * alpha);
717#endif
718
719 ++t_mat;
720 ++t_col_base;
721 }
722
723 ++t_row_diff_base;
724 }
725 for (; rr != nb_row_base_functions; ++rr)
726 ++t_row_diff_base;
727
728 ++t_w;
729 ++t_grad;
730 ++t_logC_dC;
731 ++t_D;
732 }
733
735}
736
737template <typename DomainEleOp> struct HenckyIntegrators {
738 template <int DIM, IntegrationType I>
740
741 template <int DIM, IntegrationType I>
743
744 template <int DIM, IntegrationType I>
746
747 template <int DIM, IntegrationType I, int S>
750
751 template <int DIM, IntegrationType I, int S>
754
755 template <int DIM, IntegrationType I, int S>
758
759 template <int DIM, IntegrationType I, int S>
762
763 template <int DIM, IntegrationType I, int S>
765
766 template <int DIM, IntegrationType I, typename AssemblyDomainEleOp, int S>
769};
770
771template <int DIM>
772MoFEMErrorCode
774 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
775 std::string block_name,
776 boost::shared_ptr<MatrixDouble> mat_D_Ptr, Sev sev,
777 double scale = 1) {
779
780 PetscBool plane_strain_flag = PETSC_FALSE;
781 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-plane_strain",
782 &plane_strain_flag, PETSC_NULLPTR);
783
784 struct OpMatBlocks : public DomainEleOp {
785 OpMatBlocks(boost::shared_ptr<MatrixDouble> m, double bulk_modulus_K,
786 double shear_modulus_G, MoFEM::Interface &m_field, Sev sev,
787 std::vector<const CubitMeshSets *> meshset_vec_ptr,
788 double scale, PetscBool plane_strain_flag)
789 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE), matDPtr(m),
790 bulkModulusKDefault(bulk_modulus_K),
791 shearModulusGDefault(shear_modulus_G), scaleYoungModulus(scale),
792 planeStrainFlag(plane_strain_flag) {
793 CHK_THROW_MESSAGE(extractBlockData(m_field, meshset_vec_ptr, sev),
794 "Can not get data from block");
795 }
796
797 MoFEMErrorCode doWork(int side, EntityType type,
798 EntitiesFieldData::EntData &data) {
800
801 for (auto &b : blockData) {
802
803 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
804 CHKERR getMatDPtr(matDPtr, b.bulkModulusK * scaleYoungModulus,
805 b.shearModulusG * scaleYoungModulus,
806 planeStrainFlag);
808 }
809 }
810
811 CHKERR getMatDPtr(matDPtr, bulkModulusKDefault * scaleYoungModulus,
812 shearModulusGDefault * scaleYoungModulus,
813 planeStrainFlag);
815 }
816
817 private:
818 boost::shared_ptr<MatrixDouble> matDPtr;
819 const double scaleYoungModulus;
820 const PetscBool planeStrainFlag;
821
822 struct BlockData {
823 double bulkModulusK;
824 double shearModulusG;
825 Range blockEnts;
826 };
827
828 double bulkModulusKDefault;
829 double shearModulusGDefault;
830 std::vector<BlockData> blockData;
831
832 MoFEMErrorCode
833 extractBlockData(MoFEM::Interface &m_field,
834 std::vector<const CubitMeshSets *> meshset_vec_ptr,
835 Sev sev) {
837
838 for (auto m : meshset_vec_ptr) {
839 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock") << *m;
840 std::vector<double> block_data;
841 CHKERR m->getAttributes(block_data);
842 if (block_data.size() != 2) {
843 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
844 "Expected that block has two attribute");
845 }
846 auto get_block_ents = [&]() {
847 Range ents;
848 CHKERR
849 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
850 return ents;
851 };
852
853 double young_modulus = block_data[0];
854 double poisson_ratio = block_data[1];
855 double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
856 double shear_modulus_G = young_modulus / (2 * (1 + poisson_ratio));
857
858 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock")
859 << "E = " << young_modulus << " nu = " << poisson_ratio;
860
861 blockData.push_back(
862 {bulk_modulus_K, shear_modulus_G, get_block_ents()});
863 }
864 MOFEM_LOG_CHANNEL("WORLD");
866 }
867
868 MoFEMErrorCode getMatDPtr(boost::shared_ptr<MatrixDouble> mat_D_ptr,
869 double bulk_modulus_K, double shear_modulus_G,
870 PetscBool is_plane_strain) {
872 //! [Calculate elasticity tensor]
873 auto set_material_stiffness = [&]() {
874 FTensor::Index<'i', DIM> i;
875 FTensor::Index<'j', DIM> j;
876 FTensor::Index<'k', DIM> k;
877 FTensor::Index<'l', DIM> l;
879 double A = (SPACE_DIM == 2 && !is_plane_strain)
880 ? 2 * shear_modulus_G /
881 (bulk_modulus_K + (4. / 3.) * shear_modulus_G)
882 : 1;
883 auto t_D = getFTensor4DdgFromMat<DIM, DIM, 0>(*mat_D_ptr);
884 t_D(i, j, k, l) =
885 2 * shear_modulus_G * ((t_kd(i, k) ^ t_kd(j, l)) / 4.) +
886 A * (bulk_modulus_K - (2. / 3.) * shear_modulus_G) * t_kd(i, j) *
887 t_kd(k, l);
888 };
889 //! [Calculate elasticity tensor]
890 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
891 mat_D_ptr->resize(1, size_symm * size_symm);
892 set_material_stiffness();
894 }
895 };
896
897 double E = 1.0;
898 double nu = 0.3;
899
900 PetscOptionsBegin(PETSC_COMM_WORLD, "", "", "none");
901 CHKERR PetscOptionsScalar("-young_modulus", "Young modulus", "", E, &E,
902 PETSC_NULLPTR);
903 CHKERR PetscOptionsScalar("-poisson_ratio", "poisson ratio", "", nu, &nu,
904 PETSC_NULLPTR);
905 PetscOptionsEnd();
906
907 double bulk_modulus_K = E / (3 * (1 - 2 * nu));
908 double shear_modulus_G = E / (2 * (1 + nu));
909 pip.push_back(new OpMatBlocks(
910 mat_D_Ptr, bulk_modulus_K, shear_modulus_G, m_field, sev,
911
912 // Get blockset using regular expression
913 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
914
915 (boost::format("%s(.*)") % block_name).str()
916
917 )),
918 scale, plane_strain_flag
919
920 ));
921
923}
924
925template <int DIM, IntegrationType I, typename DomainEleOp>
927 MoFEM::Interface &m_field,
928 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
929 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
930
931 auto common_ptr = boost::make_shared<HenckyOps::CommonData>();
932 common_ptr->matDPtr = boost::make_shared<MatrixDouble>();
933 common_ptr->matGradPtr = boost::make_shared<MatrixDouble>();
934
935 CHK_THROW_MESSAGE(addMatBlockOps<DIM>(m_field, pip, block_name,
936 common_ptr->matDPtr, sev, scale),
937 "addMatBlockOps");
938
940
941 pip.push_back(new OpCalculateVectorFieldGradient<DIM, DIM>(
942 field_name, common_ptr->matGradPtr));
943 pip.push_back(new typename H::template OpCalculateEigenVals<DIM, I>(
944 field_name, common_ptr));
945 pip.push_back(
946 new typename H::template OpCalculateLogC<DIM, I>(field_name, common_ptr));
947 pip.push_back(new typename H::template OpCalculateLogC_dC<DIM, I>(
948 field_name, common_ptr));
949 // Assumes constant D matrix per entity
950 pip.push_back(new typename H::template OpCalculateHenckyStress<DIM, I, 0>(
951 field_name, common_ptr));
952 pip.push_back(new typename H::template OpCalculatePiolaStress<DIM, I, 0>(
953 field_name, common_ptr));
954
955 return common_ptr;
956}
957
958template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
959MoFEMErrorCode opFactoryDomainRhs(
960 MoFEM::Interface &m_field,
961 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
962 std::string field_name, boost::shared_ptr<HenckyOps::CommonData> common_ptr,
963 Sev sev) {
965
966 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
967 A>::template LinearForm<I>;
969 typename B::template OpGradTimesTensor<1, DIM, DIM>;
970 pip.push_back(
971 new OpInternalForcePiola("U", common_ptr->getMatFirstPiolaStress()));
972
974}
975
976template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
977MoFEMErrorCode opFactoryDomainRhs(
978 MoFEM::Interface &m_field,
979 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
980 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
982
983 auto common_ptr = commonDataFactory<DIM, I, DomainEleOp>(
984 m_field, pip, field_name, block_name, sev, scale);
985 CHKERR opFactoryDomainRhs<DIM, A, I, DomainEleOp>(m_field, pip, field_name,
986 common_ptr, sev);
987
989}
990
991template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
992MoFEMErrorCode opFactoryDomainLhs(
993 MoFEM::Interface &m_field,
994 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
995 std::string field_name, boost::shared_ptr<HenckyOps::CommonData> common_ptr,
996 Sev sev) {
998
999 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
1000 A>::template BiLinearForm<I>;
1001 using OpKPiola = typename B::template OpGradTensorGrad<1, DIM, DIM, -1>;
1002
1004 // Assumes constant D matrix per entity
1005 pip.push_back(new typename H::template OpHenckyTangent<DIM, I, 0>(
1006 field_name, common_ptr));
1007 pip.push_back(
1008 new OpKPiola(field_name, field_name, common_ptr->getMatTangent()));
1009
1011}
1012
1013template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
1014MoFEMErrorCode opFactoryDomainLhs(
1015 MoFEM::Interface &m_field,
1016 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1017 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
1019
1020 auto common_ptr = commonDataFactory<DIM, I, DomainEleOp>(
1021 m_field, pip, field_name, block_name, sev, scale);
1022 CHKERR opFactoryDomainLhs<DIM, A, I, DomainEleOp>(m_field, pip, field_name,
1023 common_ptr, sev);
1024
1026}
1027} // namespace HenckyOps
1028
1029#endif // __HENCKY_OPS_HPP__
std::string type
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
constexpr double a
constexpr int SPACE_DIM
DomainEle::UserDataOperator DomainEleOp
Finire element operator type.
Kronecker Delta class symmetric.
Kronecker Delta class.
#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()
@ NOSPACE
Definition definitions.h:83
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
double bulk_modulus_K
double shear_modulus_G
@ F
constexpr auto t_kd
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
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 getDiffDiffMat(A &&t_val, B &&t_vec, Fun< double > f, Fun< double > d_f, Fun< double > dd_f, C &&t_S, const int nb)
Get the Diff Diff Mat object.
auto get_uniq_nb(double *ptr)
Definition HenckyOps.hpp:24
auto sort_eigen_vals(FTensor::Tensor1< double, DIM > &eig, FTensor::Tensor2< double, DIM, DIM > &eigen_vec)
Definition HenckyOps.hpp:32
MoFEMErrorCode opFactoryDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HenckyOps::CommonData > common_ptr, Sev sev)
const double eps
Definition HenckyOps.hpp:13
MoFEMErrorCode opFactoryDomainRhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HenckyOps::CommonData > common_ptr, Sev sev)
MoFEMErrorCode addMatBlockOps(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string block_name, boost::shared_ptr< MatrixDouble > mat_D_Ptr, Sev sev, double scale=1)
auto commonDataFactory(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, std::string block_name, Sev sev, double scale=1)
bool is_eq(const double &a, const double &b)
Definition HenckyOps.hpp:19
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
constexpr AssemblyType A
constexpr auto field_name
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesTensor< 1, SPACE_DIM, SPACE_DIM > OpInternalForcePiola
Definition seepage.cpp:65
PetscBool is_plane_strain
Definition seepage.cpp:177
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradTensorGrad< 1, SPACE_DIM, SPACE_DIM, -1 > OpKPiola
[Only used for dynamics]
Definition seepage.cpp:63
FTensor::Index< 'm', 3 > m
MatrixDouble matEigVec
Definition HenckyOps.hpp:75
boost::shared_ptr< MatrixDouble > matLogCPlastic
Definition HenckyOps.hpp:72
MatrixDouble matHenckyStress
Definition HenckyOps.hpp:80
MatrixDouble matLogCdC
Definition HenckyOps.hpp:77
MatrixDouble matEigVal
Definition HenckyOps.hpp:74
MatrixDouble matFirstPiolaStress
Definition HenckyOps.hpp:78
boost::shared_ptr< MatrixDouble > matDPtr
Definition HenckyOps.hpp:71
MatrixDouble matSecondPiolaStress
Definition HenckyOps.hpp:79
MatrixDouble matLogC
Definition HenckyOps.hpp:76
MatrixDouble matTangent
Definition HenckyOps.hpp:81
boost::shared_ptr< MatrixDouble > matGradPtr
Definition HenckyOps.hpp:70
OpCalculateEigenValsImpl(const std::string field_name, boost::shared_ptr< CommonData > common_data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpCalculateHenckyPlasticStressImpl(const std::string field_name, boost::shared_ptr< CommonData > common_data, boost::shared_ptr< MatrixDouble > mat_D_ptr, const double scale=1)
OpCalculateHenckyStressImpl(const std::string field_name, boost::shared_ptr< CommonData > common_data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpCalculateHenckyThermalStressImpl(const std::string field_name, boost::shared_ptr< VectorDouble > temperature, boost::shared_ptr< CommonData > common_data, boost::shared_ptr< VectorDouble > coeff_expansion_ptr, boost::shared_ptr< double > ref_temp_ptr)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpCalculateLogCImpl(const std::string field_name, boost::shared_ptr< CommonData > common_data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpCalculateLogC_dCImpl(const std::string field_name, boost::shared_ptr< CommonData > common_data)
OpCalculatePiolaStressImpl(const std::string field_name, boost::shared_ptr< CommonData > common_data)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpHenckyTangentImpl(const std::string field_name, boost::shared_ptr< CommonData > common_data, boost::shared_ptr< MatrixDouble > mat_D_ptr=nullptr)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
virtual moab::Interface & get_moab()=0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
double young_modulus
Young modulus.
Definition plastic.cpp:126
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:127
double scale
Definition plastic.cpp:124
constexpr auto size_symm
Definition plastic.cpp:42
double H
Hardening.
Definition plastic.cpp:129