v0.16.3
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
11//! [HenckyOps]
12namespace HenckyOps {
13
14static const double eps = std::sqrt(std::numeric_limits<double>::epsilon());
15
16auto f = [](double v) { return 0.5 * std::log(v); };
17auto d_f = [](double v) { return 0.5 / v; };
18auto dd_f = [](double v) { return -0.5 / (v * v); };
19
20//! [Hencky common data]
21struct CommonData : public boost::enable_shared_from_this<CommonData> {
22 boost::shared_ptr<MatrixDouble> matGradPtr;
23 boost::shared_ptr<MatrixDouble> matDPtr;
24 boost::shared_ptr<MatrixDouble> matLogCPlastic;
25
26 MatrixDouble matEigVal;
27 MatrixDouble matEigVec;
28 MatrixDouble matLogC;
29 MatrixDouble matLogCdC;
30 MatrixDouble matFirstPiolaStress;
32 MatrixDouble matHenckyStress;
33 MatrixDouble matTangent;
34
35 inline auto getMatFirstPiolaStress() {
36 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
38 }
39
40 inline auto getMatHenckyStress() {
41 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
43 }
44
45 inline auto getMatLogC() {
46 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &matLogC);
47 }
48
49 inline auto getMatTangent() {
50 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &matTangent);
51 }
52};
53//! [Hencky common data]
54
55template <int DIM, IntegrationType I, typename DomainEleOp>
57
58template <int DIM, IntegrationType I, typename DomainEleOp>
60
61template <int DIM, IntegrationType I, typename DomainEleOp>
63
64template <int DIM, IntegrationType I, typename DomainEleOp, int S>
66
67template <int DIM, IntegrationType I, typename DomainEleOp, int S>
69
70template <int DIM, IntegrationType I, typename DomainEleOp, int S>
72
73template <int DIM, IntegrationType I, typename DomainEleOp, int S>
75
76template <int DIM, IntegrationType I, typename DomainEleOp, int S>
78
79template <int DIM, IntegrationType I, typename DomainEleOp, int S>
81
82template <int DIM, IntegrationType I, typename DomainEleOp, int S>
84
85template <int DIM, typename DomainEleOp>
86struct OpCalculateEigenValsImpl<DIM, GAUSS, DomainEleOp> : public DomainEleOp {
87
89 boost::shared_ptr<CommonData> common_data)
91 commonDataPtr(common_data) {
92 std::fill(&DomainEleOp::doEntities[MBEDGE],
93 &DomainEleOp::doEntities[MBMAXTYPE], false);
94 }
95
96 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
98
99 FTensor::Index<'i', DIM> i;
100 FTensor::Index<'j', DIM> j;
101 FTensor::Index<'k', DIM> k;
102
103 [[maybe_unused]] constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
104 // const size_t nb_gauss_pts = matGradPtr->size2();
105 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
106
107 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
108
109 commonDataPtr->matEigVal.resize(nb_gauss_pts, DIM, false);
110 commonDataPtr->matEigVec.resize(nb_gauss_pts, DIM * DIM, false);
111 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
112 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
113
114 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
115
120
121 F(i, j) = t_grad(i, j) + t_kd(i, j);
122 C(i, j) = F(k, i) ^ F(k, j);
123
124 for (int ii = 0; ii != DIM; ii++)
125 for (int jj = 0; jj != DIM; jj++)
126 eigen_vec(ii, jj) = C(ii, jj);
127
128 CHKERR computeEigenValuesSymmetric(eigen_vec, eig);
129 for (auto ii = 0; ii != DIM; ++ii)
130 eig(ii) = std::max(eps, eig(ii));
131
132 // rare case when two eigen values are equal
133 auto nb_uniq =
134 getUniqNb<DIM>(getVectorAdaptor(&eig(0), DIM), FTensor::Number<DIM>{});
135 if constexpr (DIM == 3) {
136 if (nb_uniq == 2) {
137 CHKERR sortEigenVals<DIM>(
138 getVectorAdaptor(&eig(0), DIM),
139 getMatrixAdaptor(&eigen_vec(0, 0), DIM, DIM),
141 }
142 }
143
144 t_eig_val(i) = eig(i);
145 t_eig_vec(i, j) = eigen_vec(i, j);
146
147#ifndef NDEBUG
148 auto nb_uniq_test = getUniqNb<DIM>(getVectorAdaptor(&t_eig_val(0), DIM),
150 if (nb_uniq_test != nb_uniq) {
151 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
152 "Inconsistent number of unique eigen values %ld != %ld",
153 nb_uniq, nb_uniq_test);
154 }
155#endif
156
157 ++t_grad;
158 ++t_eig_val;
159 ++t_eig_vec;
160 }
161
163 }
164
165private:
166 boost::shared_ptr<CommonData> commonDataPtr;
167};
168
169template <int DIM, typename DomainEleOp>
170struct OpCalculateLogCImpl<DIM, GAUSS, DomainEleOp> : public DomainEleOp {
171
173 boost::shared_ptr<CommonData> common_data)
175 commonDataPtr(common_data) {
176 std::fill(&DomainEleOp::doEntities[MBEDGE],
177 &DomainEleOp::doEntities[MBMAXTYPE], false);
178 }
179
180 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
182
183 FTensor::Index<'i', DIM> i;
184 FTensor::Index<'j', DIM> j;
185
186 // const size_t nb_gauss_pts = matGradPtr->size2();
187 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
188 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
189 commonDataPtr->matLogC.resize(nb_gauss_pts, size_symm, false);
190
191 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
192 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
193
194 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
195
196 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
197 t_logC(i, j) = EigenMatrix::getMat(t_eig_val, t_eig_vec, f)(i, j);
198 ++t_eig_val;
199 ++t_eig_vec;
200 ++t_logC;
201 }
202
204 }
205
206private:
207 boost::shared_ptr<CommonData> commonDataPtr;
208};
209
210template <int DIM, typename DomainEleOp>
211struct OpCalculateLogC_dCImpl<DIM, GAUSS, DomainEleOp> : public DomainEleOp {
212
214 boost::shared_ptr<CommonData> common_data)
216 commonDataPtr(common_data) {
217 std::fill(&DomainEleOp::doEntities[MBEDGE],
218 &DomainEleOp::doEntities[MBMAXTYPE], false);
219 }
220
221 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
223
224 FTensor::Index<'i', DIM> i;
225 FTensor::Index<'j', DIM> j;
226 FTensor::Index<'k', DIM> k;
227 FTensor::Index<'l', DIM> l;
228
229 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
230 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
231 commonDataPtr->matLogCdC.resize(nb_gauss_pts, size_symm * size_symm, false);
232 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
233 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
234 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
235
236 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
237 // rare case when two eigen values are equal
238 auto nb_uniq = getUniqNb<DIM>(getVectorAdaptor(&t_eig_val(0), DIM),
240 t_logC_dC(i, j, k, l) =
241 2 * EigenMatrix::getDiffMat(t_eig_val, t_eig_vec, f, d_f,
242 nb_uniq)(i, j, k, l);
243
244 ++t_logC_dC;
245 ++t_eig_val;
246 ++t_eig_vec;
247 }
248
250 }
251
252private:
253 boost::shared_ptr<CommonData> commonDataPtr;
254};
255
256 //! [Hencky Stress]
257template <int DIM, typename DomainEleOp, int S>
259 : public DomainEleOp {
260
262 boost::shared_ptr<CommonData> common_data)
264 commonDataPtr(common_data) {
265 std::fill(&DomainEleOp::doEntities[MBEDGE],
266 &DomainEleOp::doEntities[MBMAXTYPE], false);
267 }
268
269 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
271
272 FTensor::Index<'i', DIM> i;
273 FTensor::Index<'j', DIM> j;
274 FTensor::Index<'k', DIM> k;
275 FTensor::Index<'l', DIM> l;
276
277 // const size_t nb_gauss_pts = matGradPtr->size2();
278 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
279 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
280 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
281 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
282 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
283 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
284
285 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
286 t_T(i, j) = t_D(i, j, k, l) * t_logC(k, l);
287 ++t_logC;
288 ++t_T;
289 ++t_D;
290 }
291
293 }
294
295private:
296 boost::shared_ptr<CommonData> commonDataPtr;
297};
298
299//! [Hencky Stress]
300template <int DIM, typename DomainEleOp, int S>
302 : public DomainEleOp {
303
305 const std::string field_name, boost::shared_ptr<VectorDouble> temperature,
306 boost::shared_ptr<CommonData> common_data,
307 boost::shared_ptr<VectorDouble> coeff_expansion_ptr,
308 boost::shared_ptr<double> ref_temp_ptr)
309 : DomainEleOp(field_name, DomainEleOp::OPROW), tempPtr(temperature),
310 commonDataPtr(common_data), coeffExpansionPtr(coeff_expansion_ptr),
311 refTempPtr(ref_temp_ptr) {
312 std::fill(&DomainEleOp::doEntities[MBEDGE],
313 &DomainEleOp::doEntities[MBMAXTYPE], false);
314 }
315
316 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
318
319 FTensor::Index<'i', DIM> i;
320 FTensor::Index<'j', DIM> j;
321 FTensor::Index<'k', DIM> k;
322 FTensor::Index<'l', DIM> l;
323
324 [[maybe_unused]] constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
325
326 // const size_t nb_gauss_pts = matGradPtr->size2();
327 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
328 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
329 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
330 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
331 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
332 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
333 commonDataPtr->matFirstPiolaStress.resize(nb_gauss_pts, DIM * DIM, false);
334 commonDataPtr->matSecondPiolaStress.resize(nb_gauss_pts, size_symm, false);
335 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
336 auto t_P = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matFirstPiolaStress);
337 auto t_S =
338 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
339 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
340 auto t_temp = getFTensor0FromVec(*tempPtr);
341
343 t_coeff_exp(i, j) = 0;
344 for (auto d = 0; d != SPACE_DIM; ++d) {
345 t_coeff_exp(d, d) = (*coeffExpansionPtr)[d];
346 }
347
348 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
349#ifdef HENCKY_SMALL_STRAIN
350 t_P(i, j) = t_D(i, j, k, l) *
351 (t_grad(k, l) - t_coeff_exp(k, l) * (t_temp - (*refTempPtr)));
352#else
353 t_T(i, j) = t_D(i, j, k, l) *
354 (t_logC(k, l) - t_coeff_exp(k, l) * (t_temp - (*refTempPtr)));
356 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
357 t_S(k, l) = t_T(i, j) * t_logC_dC(i, j, k, l);
358 t_P(i, l) = t_F(i, k) * t_S(k, l);
359#endif
360 ++t_grad;
361 ++t_logC;
362 ++t_logC_dC;
363 ++t_P;
364 ++t_T;
365 ++t_S;
366 ++t_D;
367 ++t_temp;
368 }
369
371 }
372
373private:
374 boost::shared_ptr<CommonData> commonDataPtr;
375 boost::shared_ptr<VectorDouble> tempPtr;
376 boost::shared_ptr<VectorDouble> coeffExpansionPtr;
377 boost::shared_ptr<double> refTempPtr;
378};
379
380template <int DIM, typename DomainEleOp, int S>
382 : public DomainEleOp {
383
385 boost::shared_ptr<CommonData> common_data,
386 boost::shared_ptr<MatrixDouble> mat_D_ptr,
387 const double scale = 1)
388 : DomainEleOp(field_name, DomainEleOp::OPROW), commonDataPtr(common_data),
389 scaleStress(scale), matDPtr(mat_D_ptr) {
390 std::fill(&DomainEleOp::doEntities[MBEDGE],
391 &DomainEleOp::doEntities[MBMAXTYPE], false);
392
393 matLogCPlastic = commonDataPtr->matLogCPlastic;
394 }
395
396 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
398
399 FTensor::Index<'i', DIM> i;
400 FTensor::Index<'j', DIM> j;
401 FTensor::Index<'k', DIM> k;
402 FTensor::Index<'l', DIM> l;
403
404 // const size_t nb_gauss_pts = matGradPtr->size2();
405 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
406 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*matDPtr);
407 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
408 auto t_logCPlastic = getFTensor2SymmetricFromMat<DIM>(*matLogCPlastic);
409 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
410 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
411 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
412
413 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
414 t_T(i, j) = t_D(i, j, k, l) * (t_logC(k, l) - t_logCPlastic(k, l));
415 t_T(i, j) /= scaleStress;
416 ++t_logC;
417 ++t_T;
418 ++t_D;
419 ++t_logCPlastic;
420 }
421
423 }
424
425private:
426 boost::shared_ptr<CommonData> commonDataPtr;
427 boost::shared_ptr<MatrixDouble> matDPtr;
428 boost::shared_ptr<MatrixDouble> matLogCPlastic;
429 const double scaleStress;
430};
431
432// ![Piola Stress]
433template <int DIM, typename DomainEleOp, int S>
435 : public DomainEleOp {
436
438 boost::shared_ptr<CommonData> common_data)
440 commonDataPtr(common_data) {
441 std::fill(&DomainEleOp::doEntities[MBEDGE],
442 &DomainEleOp::doEntities[MBMAXTYPE], false);
443 }
444
445 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
447
448 FTensor::Index<'i', DIM> i;
449 FTensor::Index<'j', DIM> j;
450 FTensor::Index<'k', DIM> k;
451 FTensor::Index<'l', DIM> l;
452
453 [[maybe_unused]] constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
454
455 // const size_t nb_gauss_pts = matGradPtr->size2();
456 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
457#ifdef HENCKY_SMALL_STRAIN
458 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
459#endif
460 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
461 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
462 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
463 commonDataPtr->matFirstPiolaStress.resize(nb_gauss_pts, DIM * DIM, false);
464 commonDataPtr->matSecondPiolaStress.resize(nb_gauss_pts, size_symm, false);
465 auto t_P = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matFirstPiolaStress);
466 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
467 auto t_S =
468 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
469 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
470
471 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
472
473#ifdef HENCKY_SMALL_STRAIN
474 t_P(i, j) = t_D(i, j, k, l) * t_grad(k, l);
475#else
477 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
478 t_S(k, l) = t_T(i, j) * t_logC_dC(i, j, k, l);
479 t_P(i, l) = t_F(i, k) * t_S(k, l);
480#endif
481
482 ++t_grad;
483 ++t_logC;
484 ++t_logC_dC;
485 ++t_P;
486 ++t_T;
487 ++t_S;
488#ifdef HENCKY_SMALL_STRAIN
489 ++t_D;
490#endif
491 }
492
494 }
495
496private:
497 boost::shared_ptr<CommonData> commonDataPtr;
498};
499// ![Piola Stress]
500
501//! [Op Hencky Tangent impl]
502template <int DIM, typename DomainEleOp, int S>
503struct OpHenckyTangentImpl<DIM, GAUSS, DomainEleOp, S> : public DomainEleOp {
505 boost::shared_ptr<CommonData> common_data,
506 boost::shared_ptr<MatrixDouble> mat_D_ptr = nullptr)
508 commonDataPtr(common_data) {
509 std::fill(&DomainEleOp::doEntities[MBEDGE],
510 &DomainEleOp::doEntities[MBMAXTYPE], false);
511 if (mat_D_ptr)
512 matDPtr = mat_D_ptr;
513 else
514 matDPtr = commonDataPtr->matDPtr;
515 }
516
517 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
519
520 FTensor::Index<'i', DIM> i;
521 FTensor::Index<'j', DIM> j;
522 FTensor::Index<'k', DIM> k;
523 FTensor::Index<'l', DIM> l;
524 FTensor::Index<'m', DIM> m;
525 FTensor::Index<'n', DIM> n;
526 FTensor::Index<'o', DIM> o;
527 FTensor::Index<'p', DIM> p;
528
529 [[maybe_unused]] constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
530 // const size_t nb_gauss_pts = matGradPtr->size2();
531 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
532 commonDataPtr->matTangent.resize(nb_gauss_pts, DIM * DIM * DIM * DIM);
533 auto dP_dF =
534 getFTensor4FromMat<DIM, DIM, DIM, DIM>(commonDataPtr->matTangent);
535
536 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*matDPtr);
537 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
538 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
539 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
540 auto t_S =
541 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
542 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
543 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
544
545 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
546
547#ifdef HENCKY_SMALL_STRAIN
548 dP_dF(i, j, k, l) = t_D(i, j, k, l);
549#else
550
552 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
553
554 // rare case when two eigen values are equal
555 auto nb_uniq = getUniqNb<DIM>(getVectorAdaptor(&t_eig_val(0), DIM),
558 dC_dF(i, j, k, l) = (t_kd(i, l) * t_F(k, j)) + (t_kd(j, l) * t_F(k, i));
559
560 auto TL = EigenMatrix::getDiffDiffMat(t_eig_val, t_eig_vec, f, d_f, dd_f,
561 t_T, nb_uniq);
562 TL(i, j, k, l) *= 4;
563 FTensor::Ddg<double, DIM, DIM> P_D_P_plus_TL;
564 P_D_P_plus_TL(i, j, k, l) =
565 TL(i, j, k, l) +
566 (t_logC_dC(i, j, o, p) * t_D(o, p, m, n)) * t_logC_dC(m, n, k, l);
567 P_D_P_plus_TL(i, j, k, l) *= 0.5;
568 dP_dF(i, j, m, n) = t_kd(i, m) * (t_kd(k, n) * t_S(k, j));
569 dP_dF(i, j, m, n) +=
570 t_F(i, k) * (P_D_P_plus_TL(k, j, o, p) * dC_dF(o, p, m, n));
571
572#endif
573
574 ++dP_dF;
575
576 ++t_grad;
577 ++t_eig_val;
578 ++t_eig_vec;
579 ++t_logC_dC;
580 ++t_S;
581 ++t_T;
582 ++t_D;
583 }
584
586 }
587
588private:
589 boost::shared_ptr<CommonData> commonDataPtr;
590 boost::shared_ptr<MatrixDouble> matDPtr;
591};
592
593//! [Op Hencky Tangent impl]
594template <int DIM, typename AssemblyDomainEleOp, int S>
596 : public AssemblyDomainEleOp {
598 const std::string row_field_name, const std::string col_field_name,
599 boost::shared_ptr<CommonData> elastic_common_data_ptr,
600 boost::shared_ptr<VectorDouble> coeff_expansion_ptr);
601
602 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
603 EntitiesFieldData::EntData &col_data);
604
605private:
606 boost::shared_ptr<CommonData> elasticCommonDataPtr;
607 boost::shared_ptr<VectorDouble> coeffExpansionPtr;
608};
609
610template <int DIM, typename AssemblyDomainEleOp, int S>
613 const std::string row_field_name, const std::string col_field_name,
614 boost::shared_ptr<CommonData> elastic_common_data_ptr,
615 boost::shared_ptr<VectorDouble> coeff_expansion_ptr)
616 : AssemblyDomainEleOp(row_field_name, col_field_name,
617 AssemblyDomainEleOp::OPROWCOL),
618 elasticCommonDataPtr(elastic_common_data_ptr),
619 coeffExpansionPtr(coeff_expansion_ptr) {
620 this->sYmm = false;
621}
622
623template <int DIM, typename AssemblyDomainEleOp, int S>
624MoFEMErrorCode
626 iNtegrate(EntitiesFieldData::EntData &row_data,
627 EntitiesFieldData::EntData &col_data) {
629
630 auto &locMat = AssemblyDomainEleOp::locMat;
631
632 const auto nb_integration_pts = row_data.getN().size1();
633 const auto nb_row_base_functions = row_data.getN().size2();
634 auto t_w = this->getFTensor0IntegrationWeight();
635
636 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
637 auto t_row_diff_base = row_data.getFTensor1DiffN<DIM>();
638 auto t_D = getFTensor4DdgFromMat<DIM, DIM, 0>(*elasticCommonDataPtr->matDPtr);
639 auto t_grad =
640 getFTensor2FromMat<DIM, DIM>(*(elasticCommonDataPtr->matGradPtr));
641 auto t_logC_dC =
642 getFTensor4DdgFromMat<DIM, DIM>(elasticCommonDataPtr->matLogCdC);
645
646 FTensor::Index<'i', DIM> i;
647 FTensor::Index<'j', DIM> j;
648 FTensor::Index<'k', DIM> k;
649 FTensor::Index<'l', DIM> l;
650 FTensor::Index<'m', DIM> m;
651 FTensor::Index<'n', DIM> n;
652 FTensor::Index<'o', DIM> o;
653
655 t_coeff_exp(i, j) = 0;
656 for (auto d = 0; d != SPACE_DIM; ++d) {
657 t_coeff_exp(d, d) = (*coeffExpansionPtr)[d];
658 }
659
660 t_eigen_strain(i, j) = (t_D(i, j, k, l) * t_coeff_exp(k, l));
661
662 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
663
664 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
665
666 double alpha = this->getMeasure() * t_w;
667 auto rr = 0;
668 for (; rr != AssemblyDomainEleOp::nbRows / DIM; ++rr) {
669 auto t_mat =
670 getFTensor1FromMat<DIM, 1,
671 DataLayoutTraits<DataLayout::CoeffsByGauss>>(
672 locMat, rr * DIM);
673 auto t_col_base = col_data.getFTensor0N(gg, 0);
674 for (auto cc = 0; cc != AssemblyDomainEleOp::nbCols; cc++) {
675#ifdef HENCKY_SMALL_STRAIN
676 t_mat(i) -=
677 (t_row_diff_base(j) * t_eigen_strain(i, j)) * (t_col_base * alpha);
678#else
679 t_mat(i) -= (t_row_diff_base(j) *
680 (t_F(i, o) * ((t_D(m, n, k, l) * t_coeff_exp(k, l)) *
681 t_logC_dC(m, n, o, j)))) *
682 (t_col_base * alpha);
683#endif
684
685 ++t_mat;
686 ++t_col_base;
687 }
688
689 ++t_row_diff_base;
690 }
691 for (; rr != nb_row_base_functions; ++rr)
692 ++t_row_diff_base;
693
694 ++t_w;
695 ++t_grad;
696 ++t_logC_dC;
697 ++t_D;
698 }
699
701}
702
703//! [Hencky integrators]
704template <typename DomainEleOp> struct HenckyIntegrators {
705 template <int DIM, IntegrationType I>
707
708 template <int DIM, IntegrationType I>
710
711 template <int DIM, IntegrationType I>
713
714 template <int DIM, IntegrationType I, int S>
717
718 template <int DIM, IntegrationType I, int S>
721
722 template <int DIM, IntegrationType I, int S>
725
726 template <int DIM, IntegrationType I, int S>
729
730 template <int DIM, IntegrationType I, int S>
732
733 template <int DIM, IntegrationType I, typename AssemblyDomainEleOp, int S>
736};
737//! [Hencky integrators]
738
739//! [Add material block operations]
740template <int DIM>
741MoFEMErrorCode
743 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
744 std::string block_name,
745 boost::shared_ptr<MatrixDouble> mat_D_Ptr, Sev sev,
746 double scale = 1) {
748
749 PetscBool plane_strain_flag = PETSC_FALSE;
750 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-plane_strain",
751 &plane_strain_flag, PETSC_NULLPTR);
752
753 struct OpMatBlocks : public DomainEleOp {
754 OpMatBlocks(boost::shared_ptr<MatrixDouble> m, double bulk_modulus_K,
755 double shear_modulus_G, MoFEM::Interface &m_field, Sev sev,
756 std::vector<const CubitMeshSets *> meshset_vec_ptr,
757 double scale, PetscBool plane_strain_flag)
758 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE), matDPtr(m),
759 bulkModulusKDefault(bulk_modulus_K),
760 shearModulusGDefault(shear_modulus_G), scaleYoungModulus(scale),
761 planeStrainFlag(plane_strain_flag) {
762 CHK_THROW_MESSAGE(extractBlockData(m_field, meshset_vec_ptr, sev),
763 "Can not get data from block");
764 }
765
766 MoFEMErrorCode doWork(int side, EntityType type,
767 EntitiesFieldData::EntData &data) {
769
770 for (auto &b : blockData) {
771
772 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
773 CHKERR getMatDPtr(matDPtr, b.bulkModulusK * scaleYoungModulus,
774 b.shearModulusG * scaleYoungModulus,
775 planeStrainFlag);
777 }
778 }
779
780 CHKERR getMatDPtr(matDPtr, bulkModulusKDefault * scaleYoungModulus,
781 shearModulusGDefault * scaleYoungModulus,
782 planeStrainFlag);
784 }
785
786 private:
787 boost::shared_ptr<MatrixDouble> matDPtr;
788 const double scaleYoungModulus;
789 const PetscBool planeStrainFlag;
790
791 struct BlockData {
792 double bulkModulusK;
793 double shearModulusG;
794 Range blockEnts;
795 };
796
797 double bulkModulusKDefault;
798 double shearModulusGDefault;
799 std::vector<BlockData> blockData;
800
801 MoFEMErrorCode
802 extractBlockData(MoFEM::Interface &m_field,
803 std::vector<const CubitMeshSets *> meshset_vec_ptr,
804 Sev sev) {
806
807 for (auto m : meshset_vec_ptr) {
808 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock") << *m;
809 std::vector<double> block_data;
810 CHKERR m->getAttributes(block_data);
811 if (block_data.size() != 2) {
812 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
813 "Expected that block has two attribute");
814 }
815 auto get_block_ents = [&]() {
816 Range ents;
817 CHKERR
818 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
819 return ents;
820 };
821
822 double young_modulus = block_data[0];
823 double poisson_ratio = block_data[1];
824 double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
825 double shear_modulus_G = young_modulus / (2 * (1 + poisson_ratio));
826
827 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock")
828 << "E = " << young_modulus << " nu = " << poisson_ratio;
829
830 blockData.push_back(
831 {bulk_modulus_K, shear_modulus_G, get_block_ents()});
832 }
833 MOFEM_LOG_CHANNEL("WORLD");
835 }
836
837 // Compute elasticity tensor D
838 MoFEMErrorCode getMatDPtr(boost::shared_ptr<MatrixDouble> mat_D_ptr,
839 double bulk_modulus_K, double shear_modulus_G,
840 PetscBool is_plane_strain) {
842 //! [Calculate elasticity tensor]
843 auto set_material_stiffness = [&]() {
844 FTensor::Index<'i', DIM> i;
845 FTensor::Index<'j', DIM> j;
846 FTensor::Index<'k', DIM> k;
847 FTensor::Index<'l', DIM> l;
849 double A = (SPACE_DIM == 2 && !is_plane_strain)
850 ? 2 * shear_modulus_G /
851 (bulk_modulus_K + (4. / 3.) * shear_modulus_G)
852 : 1;
853 auto t_D = getFTensor4DdgFromMat<DIM, DIM, 0>(*mat_D_ptr);
854 t_D(i, j, k, l) =
855 2 * shear_modulus_G * ((t_kd(i, k) ^ t_kd(j, l)) / 4.) +
856 A * (bulk_modulus_K - (2. / 3.) * shear_modulus_G) * t_kd(i, j) *
857 t_kd(k, l);
858 };
859 //! [Calculate elasticity tensor]
860 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
861 mat_D_ptr->resize(1, size_symm * size_symm);
862 set_material_stiffness();
864 }
865 };
866
867 double E = 1.0;
868 double nu = 0.3;
869
870 PetscOptionsBegin(PETSC_COMM_WORLD, "", "", "none");
871 CHKERR PetscOptionsScalar("-young_modulus", "Young modulus", "", E, &E,
872 PETSC_NULLPTR);
873 CHKERR PetscOptionsScalar("-poisson_ratio", "poisson ratio", "", nu, &nu,
874 PETSC_NULLPTR);
875 PetscOptionsEnd();
876
877 double bulk_modulus_K = E / (3 * (1 - 2 * nu));
878 double shear_modulus_G = E / (2 * (1 + nu));
879 pip.push_back(new OpMatBlocks(
880 mat_D_Ptr, bulk_modulus_K, shear_modulus_G, m_field, sev,
881
882 // Get blockset using regular expression
883 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
884
885 (boost::format("%s(.*)") % block_name).str()
886
887 )),
888 scale, plane_strain_flag
889
890 ));
891
893}
894//! [Add material block operations]
895
896//! [commonDataFactory]
897template <int DIM, IntegrationType I, typename DomainEleOp>
899 MoFEM::Interface &m_field,
900 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
901 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
902
903 auto common_ptr = boost::make_shared<HenckyOps::CommonData>();
904 common_ptr->matDPtr = boost::make_shared<MatrixDouble>();
905 common_ptr->matGradPtr = boost::make_shared<MatrixDouble>();
906
907 CHK_THROW_MESSAGE(addMatBlockOps<DIM>(m_field, pip, block_name,
908 common_ptr->matDPtr, sev, scale),
909 "addMatBlockOps");
910
912
913 pip.push_back(new OpCalculateVectorFieldGradient<DIM, DIM>(
914 field_name, common_ptr->matGradPtr));
915 pip.push_back(new typename H::template OpCalculateEigenVals<DIM, I>(
916 field_name, common_ptr));
917 pip.push_back(
918 new typename H::template OpCalculateLogC<DIM, I>(field_name, common_ptr));
919 pip.push_back(new typename H::template OpCalculateLogC_dC<DIM, I>(
920 field_name, common_ptr));
921 // Assumes constant D matrix per entity
922 pip.push_back(new typename H::template OpCalculateHenckyStress<DIM, I, 0>(
923 field_name, common_ptr));
924 pip.push_back(new typename H::template OpCalculatePiolaStress<DIM, I, 0>(
925 field_name, common_ptr));
926
927 return common_ptr;
928}
929//! [commonDataFactory]
930
931//! [opFactoryDomainRhs]
932template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
933MoFEMErrorCode opFactoryDomainRhs(
934 MoFEM::Interface &m_field,
935 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
936 std::string field_name, boost::shared_ptr<HenckyOps::CommonData> common_ptr,
937 Sev sev) {
939
940 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
941 A>::template LinearForm<I>;
943 typename B::template OpGradTimesTensor<1, DIM, DIM>;
944 pip.push_back(
945 new OpInternalForcePiola("U", common_ptr->getMatFirstPiolaStress()));
946
948}
949
950template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
951MoFEMErrorCode opFactoryDomainRhs(
952 MoFEM::Interface &m_field,
953 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
954 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
956
957 auto common_ptr = commonDataFactory<DIM, I, DomainEleOp>(
958 m_field, pip, field_name, block_name, sev, scale);
959 CHKERR opFactoryDomainRhs<DIM, A, I, DomainEleOp>(m_field, pip, field_name,
960 common_ptr, sev);
961
963}
964//! [opFactoryDomainRhs]
965
966//! [opFactoryDomainLhs]
967template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
968MoFEMErrorCode opFactoryDomainLhs(
969 MoFEM::Interface &m_field,
970 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
971 std::string field_name, boost::shared_ptr<HenckyOps::CommonData> common_ptr,
972 Sev sev) {
974
975 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
976 A>::template BiLinearForm<I>;
977 using OpKPiola = typename B::template OpGradTensorGrad<1, DIM, DIM, -1>;
978
980 // Assumes constant D matrix per entity
981 pip.push_back(new typename H::template OpHenckyTangent<DIM, I, 0>(
982 field_name, common_ptr));
983 pip.push_back(
984 new OpKPiola(field_name, field_name, common_ptr->getMatTangent()));
985
987}
988
989template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
990MoFEMErrorCode opFactoryDomainLhs(
991 MoFEM::Interface &m_field,
992 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
993 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
995
996 auto common_ptr = commonDataFactory<DIM, I, DomainEleOp>(
997 m_field, pip, field_name, block_name, sev, scale);
998 CHKERR opFactoryDomainLhs<DIM, A, I, DomainEleOp>(m_field, pip, field_name,
999 common_ptr, sev);
1000
1002}
1003//! [opFactoryDomainLhs]
1004
1005} // namespace HenckyOps
1006
1007#endif // __HENCKY_OPS_HPP__
SmartPetscObj< Mat > C
std::string type
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
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.
[HenckyOps]
Definition HenckyOps.hpp:12
static const double eps
Definition HenckyOps.hpp:14
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)
[opFactoryDomainRhs]
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)
[commonDataFactory]
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)
[Hencky integrators]
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)
[Add material block operations]
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
constexpr AssemblyType A
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
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
[Hencky common data]
Definition HenckyOps.hpp:21
MatrixDouble matEigVal
Definition HenckyOps.hpp:26
MatrixDouble matLogCdC
Definition HenckyOps.hpp:29
MatrixDouble matEigVec
Definition HenckyOps.hpp:27
MatrixDouble matTangent
Definition HenckyOps.hpp:33
boost::shared_ptr< MatrixDouble > matLogCPlastic
Definition HenckyOps.hpp:24
MatrixDouble matFirstPiolaStress
Definition HenckyOps.hpp:30
MatrixDouble matLogC
Definition HenckyOps.hpp:28
boost::shared_ptr< MatrixDouble > matDPtr
Definition HenckyOps.hpp:23
MatrixDouble matSecondPiolaStress
Definition HenckyOps.hpp:31
MatrixDouble matHenckyStress
Definition HenckyOps.hpp:32
boost::shared_ptr< MatrixDouble > matGradPtr
Definition HenckyOps.hpp:22
[Hencky integrators]
OpCalculateEigenValsImpl(const std::string field_name, boost::shared_ptr< CommonData > common_data)
Definition HenckyOps.hpp:88
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Definition HenckyOps.hpp:96
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)
int nbRows
number of dofs on rows
MatrixDouble locMat
local entity block matrix
int nbCols
number if dof on column
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.