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
20inline bool is_eq(const double &a, const double &b) {
21 const auto abs_max = std::max(1., std::max(std::abs(a), std::abs(b)));
22 return std::abs(a - b) <= eps * abs_max;
23};
24
25template <int DIM> inline auto get_uniq_nb(double *ptr) {
26 std::array<double, DIM> tmp;
27 std::copy(ptr, ptr + DIM, tmp.begin());
28 std::sort(tmp.begin(), tmp.end());
29 return std::distance(tmp.begin(), std::unique(tmp.begin(), tmp.end(), is_eq));
30};
31
32template <int DIM>
35 static_assert(DIM == 3, "sort_eigen_vals expects three eigenvalues");
36
37 int i = 0, j = 1, k = 2;
38
39 if (is_eq(eig(0), eig(1))) {
40 i = 0;
41 j = 2;
42 k = 1;
43 } else if (is_eq(eig(0), eig(2))) {
44 i = 0;
45 j = 1;
46 k = 2;
47 } else if (is_eq(eig(1), eig(2))) {
48 i = 1;
49 j = 0;
50 k = 2;
51 }
52
54 eigen_vec(i, 0), eigen_vec(i, 1), eigen_vec(i, 2),
55
56 eigen_vec(j, 0), eigen_vec(j, 1), eigen_vec(j, 2),
57
58 eigen_vec(k, 0), eigen_vec(k, 1), eigen_vec(k, 2)};
59
60 FTensor::Tensor1<double, DIM> eig_c{eig(i), eig(j), eig(k)};
61
62 {
63 FTensor::Index<'i', DIM> i;
64 FTensor::Index<'j', DIM> j;
65 eig(i) = eig_c(i);
66 eigen_vec(i, j) = eigen_vec_c(i, j);
67 }
68};
69
70//! [Hencky common data]
71struct CommonData : public boost::enable_shared_from_this<CommonData> {
72 boost::shared_ptr<MatrixDouble> matGradPtr;
73 boost::shared_ptr<MatrixDouble> matDPtr;
74 boost::shared_ptr<MatrixDouble> matLogCPlastic;
75
76 MatrixDouble matEigVal;
77 MatrixDouble matEigVec;
78 MatrixDouble matLogC;
79 MatrixDouble matLogCdC;
80 MatrixDouble matFirstPiolaStress;
82 MatrixDouble matHenckyStress;
83 MatrixDouble matTangent;
84
85 inline auto getMatFirstPiolaStress() {
86 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
88 }
89
90 inline auto getMatHenckyStress() {
91 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
93 }
94
95 inline auto getMatLogC() {
96 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &matLogC);
97 }
98
99 inline auto getMatTangent() {
100 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &matTangent);
101 }
102};
103//! [Hencky common data]
104
105template <int DIM, IntegrationType I, typename DomainEleOp>
107
108template <int DIM, IntegrationType I, typename DomainEleOp>
110
111template <int DIM, IntegrationType I, typename DomainEleOp>
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, IntegrationType I, typename DomainEleOp, int S>
134
135template <int DIM, typename DomainEleOp>
137
139 boost::shared_ptr<CommonData> common_data)
141 commonDataPtr(common_data) {
142 std::fill(&DomainEleOp::doEntities[MBEDGE],
143 &DomainEleOp::doEntities[MBMAXTYPE], false);
144 }
145
146 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
148
149 FTensor::Index<'i', DIM> i;
150 FTensor::Index<'j', DIM> j;
151 FTensor::Index<'k', DIM> k;
152
153 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
154 // const size_t nb_gauss_pts = matGradPtr->size2();
155 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
156
157 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
158
159 commonDataPtr->matEigVal.resize(nb_gauss_pts, DIM, false);
160 commonDataPtr->matEigVec.resize(nb_gauss_pts, DIM * DIM, false);
161 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
162 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
163
164 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
165
170
171 F(i, j) = t_grad(i, j) + t_kd(i, j);
172 C(i, j) = F(k, i) ^ F(k, j);
173
174 for (int ii = 0; ii != DIM; ii++)
175 for (int jj = 0; jj != DIM; jj++)
176 eigen_vec(ii, jj) = C(ii, jj);
177
178 CHKERR computeEigenValuesSymmetric(eigen_vec, eig);
179 for (auto ii = 0; ii != DIM; ++ii)
180 eig(ii) = std::max(eps, eig(ii));
181
182 // rare case when two eigen values are equal
183 auto nb_uniq = get_uniq_nb<DIM>(&eig(0));
184 if constexpr (DIM == 3) {
185 if (nb_uniq == 2) {
186 sort_eigen_vals<DIM>(eig, eigen_vec);
187 }
188 }
189
190 t_eig_val(i) = eig(i);
191 t_eig_vec(i, j) = eigen_vec(i, j);
192
193#ifndef NDEBUG
194 auto nb_uniq_test = get_uniq_nb<DIM>(&t_eig_val(0));
195 if (nb_uniq_test != nb_uniq) {
196 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
197 "Inconsistent number of unique eigen values %ld != %ld",
198 nb_uniq, nb_uniq_test);
199 }
200#endif
201
202 ++t_grad;
203 ++t_eig_val;
204 ++t_eig_vec;
205 }
206
208 }
209
210private:
211 boost::shared_ptr<CommonData> commonDataPtr;
212};
213
214template <int DIM, typename DomainEleOp>
215struct OpCalculateLogCImpl<DIM, GAUSS, DomainEleOp> : public DomainEleOp {
216
218 boost::shared_ptr<CommonData> common_data)
220 commonDataPtr(common_data) {
221 std::fill(&DomainEleOp::doEntities[MBEDGE],
222 &DomainEleOp::doEntities[MBMAXTYPE], false);
223 }
224
225 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
227
228 FTensor::Index<'i', DIM> i;
229 FTensor::Index<'j', DIM> j;
230
231 // const size_t nb_gauss_pts = matGradPtr->size2();
232 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
233 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
234 commonDataPtr->matLogC.resize(nb_gauss_pts, size_symm, false);
235
236 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
237 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
238
239 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
240
241 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
242 t_logC(i, j) = EigenMatrix::getMat(t_eig_val, t_eig_vec, f)(i, j);
243 ++t_eig_val;
244 ++t_eig_vec;
245 ++t_logC;
246 }
247
249 }
250
251private:
252 boost::shared_ptr<CommonData> commonDataPtr;
253};
254
255template <int DIM, typename DomainEleOp>
256struct OpCalculateLogC_dCImpl<DIM, GAUSS, DomainEleOp> : public DomainEleOp {
257
259 boost::shared_ptr<CommonData> common_data)
261 commonDataPtr(common_data) {
262 std::fill(&DomainEleOp::doEntities[MBEDGE],
263 &DomainEleOp::doEntities[MBMAXTYPE], false);
264 }
265
266 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
268
269 FTensor::Index<'i', DIM> i;
270 FTensor::Index<'j', DIM> j;
271 FTensor::Index<'k', DIM> k;
272 FTensor::Index<'l', DIM> l;
273
274 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
275 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
276 commonDataPtr->matLogCdC.resize(nb_gauss_pts, size_symm * size_symm, false);
277 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
278 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
279 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
280
281 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
282 // rare case when two eigen values are equal
283 auto nb_uniq = get_uniq_nb<DIM>(&t_eig_val(0));
284 t_logC_dC(i, j, k, l) =
285 2 * EigenMatrix::getDiffMat(t_eig_val, t_eig_vec, f, d_f,
286 nb_uniq)(i, j, k, l);
287
288 ++t_logC_dC;
289 ++t_eig_val;
290 ++t_eig_vec;
291 }
292
294 }
295
296private:
297 boost::shared_ptr<CommonData> commonDataPtr;
298};
299
300 //! [Hencky Stress]
301template <int DIM, typename DomainEleOp, int S>
303 : public DomainEleOp {
304
306 boost::shared_ptr<CommonData> common_data)
308 commonDataPtr(common_data) {
309 std::fill(&DomainEleOp::doEntities[MBEDGE],
310 &DomainEleOp::doEntities[MBMAXTYPE], false);
311 }
312
313 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
315
316 FTensor::Index<'i', DIM> i;
317 FTensor::Index<'j', DIM> j;
318 FTensor::Index<'k', DIM> k;
319 FTensor::Index<'l', DIM> l;
320
321 // const size_t nb_gauss_pts = matGradPtr->size2();
322 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
323 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
324 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
325 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
326 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
327 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
328
329 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
330 t_T(i, j) = t_D(i, j, k, l) * t_logC(k, l);
331 ++t_logC;
332 ++t_T;
333 ++t_D;
334 }
335
337 }
338
339private:
340 boost::shared_ptr<CommonData> commonDataPtr;
341};
342
343//! [Hencky Stress]
344template <int DIM, typename DomainEleOp, int S>
346 : public DomainEleOp {
347
349 const std::string field_name, boost::shared_ptr<VectorDouble> temperature,
350 boost::shared_ptr<CommonData> common_data,
351 boost::shared_ptr<VectorDouble> coeff_expansion_ptr,
352 boost::shared_ptr<double> ref_temp_ptr)
353 : DomainEleOp(field_name, DomainEleOp::OPROW), tempPtr(temperature),
354 commonDataPtr(common_data), coeffExpansionPtr(coeff_expansion_ptr),
355 refTempPtr(ref_temp_ptr) {
356 std::fill(&DomainEleOp::doEntities[MBEDGE],
357 &DomainEleOp::doEntities[MBMAXTYPE], false);
358 }
359
360 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
362
363 FTensor::Index<'i', DIM> i;
364 FTensor::Index<'j', DIM> j;
365 FTensor::Index<'k', DIM> k;
366 FTensor::Index<'l', DIM> l;
367
368 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
369
370 // const size_t nb_gauss_pts = matGradPtr->size2();
371 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
372 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
373 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
374 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
375 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
376 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
377 commonDataPtr->matFirstPiolaStress.resize(nb_gauss_pts, DIM * DIM, false);
378 commonDataPtr->matSecondPiolaStress.resize(nb_gauss_pts, size_symm, false);
379 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
380 auto t_P = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matFirstPiolaStress);
381 auto t_S =
382 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
383 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
384 auto t_temp = getFTensor0FromVec(*tempPtr);
385
387 t_coeff_exp(i, j) = 0;
388 for (auto d = 0; d != SPACE_DIM; ++d) {
389 t_coeff_exp(d, d) = (*coeffExpansionPtr)[d];
390 }
391
392 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
393#ifdef HENCKY_SMALL_STRAIN
394 t_P(i, j) = t_D(i, j, k, l) *
395 (t_grad(k, l) - t_coeff_exp(k, l) * (t_temp - (*refTempPtr)));
396#else
397 t_T(i, j) = t_D(i, j, k, l) *
398 (t_logC(k, l) - t_coeff_exp(k, l) * (t_temp - (*refTempPtr)));
400 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
401 t_S(k, l) = t_T(i, j) * t_logC_dC(i, j, k, l);
402 t_P(i, l) = t_F(i, k) * t_S(k, l);
403#endif
404 ++t_grad;
405 ++t_logC;
406 ++t_logC_dC;
407 ++t_P;
408 ++t_T;
409 ++t_S;
410 ++t_D;
411 ++t_temp;
412 }
413
415 }
416
417private:
418 boost::shared_ptr<CommonData> commonDataPtr;
419 boost::shared_ptr<VectorDouble> tempPtr;
420 boost::shared_ptr<VectorDouble> coeffExpansionPtr;
421 boost::shared_ptr<double> refTempPtr;
422};
423
424template <int DIM, typename DomainEleOp, int S>
426 : public DomainEleOp {
427
429 boost::shared_ptr<CommonData> common_data,
430 boost::shared_ptr<MatrixDouble> mat_D_ptr,
431 const double scale = 1)
432 : DomainEleOp(field_name, DomainEleOp::OPROW), commonDataPtr(common_data),
433 scaleStress(scale), matDPtr(mat_D_ptr) {
434 std::fill(&DomainEleOp::doEntities[MBEDGE],
435 &DomainEleOp::doEntities[MBMAXTYPE], false);
436
437 matLogCPlastic = commonDataPtr->matLogCPlastic;
438 }
439
440 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
442
443 FTensor::Index<'i', DIM> i;
444 FTensor::Index<'j', DIM> j;
445 FTensor::Index<'k', DIM> k;
446 FTensor::Index<'l', DIM> l;
447
448 // const size_t nb_gauss_pts = matGradPtr->size2();
449 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
450 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*matDPtr);
451 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
452 auto t_logCPlastic = getFTensor2SymmetricFromMat<DIM>(*matLogCPlastic);
453 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
454 commonDataPtr->matHenckyStress.resize(nb_gauss_pts, size_symm, false);
455 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
456
457 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
458 t_T(i, j) = t_D(i, j, k, l) * (t_logC(k, l) - t_logCPlastic(k, l));
459 t_T(i, j) /= scaleStress;
460 ++t_logC;
461 ++t_T;
462 ++t_D;
463 ++t_logCPlastic;
464 }
465
467 }
468
469private:
470 boost::shared_ptr<CommonData> commonDataPtr;
471 boost::shared_ptr<MatrixDouble> matDPtr;
472 boost::shared_ptr<MatrixDouble> matLogCPlastic;
473 const double scaleStress;
474};
475
476// ![Piola Stress]
477template <int DIM, typename DomainEleOp, int S>
479 : public DomainEleOp {
480
482 boost::shared_ptr<CommonData> common_data)
484 commonDataPtr(common_data) {
485 std::fill(&DomainEleOp::doEntities[MBEDGE],
486 &DomainEleOp::doEntities[MBMAXTYPE], false);
487 }
488
489 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
491
492 FTensor::Index<'i', DIM> i;
493 FTensor::Index<'j', DIM> j;
494 FTensor::Index<'k', DIM> k;
495 FTensor::Index<'l', DIM> l;
496
497 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
498
499 // const size_t nb_gauss_pts = matGradPtr->size2();
500 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
501#ifdef HENCKY_SMALL_STRAIN
502 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*commonDataPtr->matDPtr);
503#endif
504 auto t_logC = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matLogC);
505 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
506 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
507 commonDataPtr->matFirstPiolaStress.resize(nb_gauss_pts, DIM * DIM, false);
508 commonDataPtr->matSecondPiolaStress.resize(nb_gauss_pts, size_symm, false);
509 auto t_P = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matFirstPiolaStress);
510 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
511 auto t_S =
512 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
513 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
514
515 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
516
517#ifdef HENCKY_SMALL_STRAIN
518 t_P(i, j) = t_D(i, j, k, l) * t_grad(k, l);
519#else
521 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
522 t_S(k, l) = t_T(i, j) * t_logC_dC(i, j, k, l);
523 t_P(i, l) = t_F(i, k) * t_S(k, l);
524#endif
525
526 ++t_grad;
527 ++t_logC;
528 ++t_logC_dC;
529 ++t_P;
530 ++t_T;
531 ++t_S;
532#ifdef HENCKY_SMALL_STRAIN
533 ++t_D;
534#endif
535 }
536
538 }
539
540private:
541 boost::shared_ptr<CommonData> commonDataPtr;
542};
543// ![Piola Stress]
544
545//! [Op Hencky Tangent impl]
546template <int DIM, typename DomainEleOp, int S>
547struct OpHenckyTangentImpl<DIM, GAUSS, DomainEleOp, S> : public DomainEleOp {
549 boost::shared_ptr<CommonData> common_data,
550 boost::shared_ptr<MatrixDouble> mat_D_ptr = nullptr)
552 commonDataPtr(common_data) {
553 std::fill(&DomainEleOp::doEntities[MBEDGE],
554 &DomainEleOp::doEntities[MBMAXTYPE], false);
555 if (mat_D_ptr)
556 matDPtr = mat_D_ptr;
557 else
558 matDPtr = commonDataPtr->matDPtr;
559 }
560
561 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
563
564 FTensor::Index<'i', DIM> i;
565 FTensor::Index<'j', DIM> j;
566 FTensor::Index<'k', DIM> k;
567 FTensor::Index<'l', DIM> l;
568 FTensor::Index<'m', DIM> m;
569 FTensor::Index<'n', DIM> n;
570 FTensor::Index<'o', DIM> o;
571 FTensor::Index<'p', DIM> p;
572
573 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
574 // const size_t nb_gauss_pts = matGradPtr->size2();
575 const size_t nb_gauss_pts = DomainEleOp::getGaussPts().size2();
576 commonDataPtr->matTangent.resize(nb_gauss_pts, DIM * DIM * DIM * DIM);
577 auto dP_dF =
578 getFTensor4FromMat<DIM, DIM, DIM, DIM>(commonDataPtr->matTangent);
579
580 auto t_D = getFTensor4DdgFromMat<DIM, DIM, S>(*matDPtr);
581 auto t_eig_val = getFTensor1FromMat<DIM>(commonDataPtr->matEigVal);
582 auto t_eig_vec = getFTensor2FromMat<DIM, DIM>(commonDataPtr->matEigVec);
583 auto t_T = getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matHenckyStress);
584 auto t_S =
585 getFTensor2SymmetricFromMat<DIM>(commonDataPtr->matSecondPiolaStress);
586 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(commonDataPtr->matGradPtr));
587 auto t_logC_dC = getFTensor4DdgFromMat<DIM, DIM>(commonDataPtr->matLogCdC);
588
589 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
590
591#ifdef HENCKY_SMALL_STRAIN
592 dP_dF(i, j, k, l) = t_D(i, j, k, l);
593#else
594
596 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
597
598 // rare case when two eigen values are equal
599 auto nb_uniq = get_uniq_nb<DIM>(&t_eig_val(0));
601 dC_dF(i, j, k, l) = (t_kd(i, l) * t_F(k, j)) + (t_kd(j, l) * t_F(k, i));
602
603 auto TL = EigenMatrix::getDiffDiffMat(t_eig_val, t_eig_vec, f, d_f, dd_f,
604 t_T, nb_uniq);
605 TL(i, j, k, l) *= 4;
606 FTensor::Ddg<double, DIM, DIM> P_D_P_plus_TL;
607 P_D_P_plus_TL(i, j, k, l) =
608 TL(i, j, k, l) +
609 (t_logC_dC(i, j, o, p) * t_D(o, p, m, n)) * t_logC_dC(m, n, k, l);
610 P_D_P_plus_TL(i, j, k, l) *= 0.5;
611 dP_dF(i, j, m, n) = t_kd(i, m) * (t_kd(k, n) * t_S(k, j));
612 dP_dF(i, j, m, n) +=
613 t_F(i, k) * (P_D_P_plus_TL(k, j, o, p) * dC_dF(o, p, m, n));
614
615#endif
616
617 ++dP_dF;
618
619 ++t_grad;
620 ++t_eig_val;
621 ++t_eig_vec;
622 ++t_logC_dC;
623 ++t_S;
624 ++t_T;
625 ++t_D;
626 }
627
629 }
630
631private:
632 boost::shared_ptr<CommonData> commonDataPtr;
633 boost::shared_ptr<MatrixDouble> matDPtr;
634};
635
636//! [Op Hencky Tangent impl]
637template <int DIM, typename AssemblyDomainEleOp, int S>
639 : public AssemblyDomainEleOp {
641 const std::string row_field_name, const std::string col_field_name,
642 boost::shared_ptr<CommonData> elastic_common_data_ptr,
643 boost::shared_ptr<VectorDouble> coeff_expansion_ptr);
644
645 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
646 EntitiesFieldData::EntData &col_data);
647
648private:
649 boost::shared_ptr<CommonData> elasticCommonDataPtr;
650 boost::shared_ptr<VectorDouble> coeffExpansionPtr;
651};
652
653template <int DIM, typename AssemblyDomainEleOp, int S>
656 const std::string row_field_name, const std::string col_field_name,
657 boost::shared_ptr<CommonData> elastic_common_data_ptr,
658 boost::shared_ptr<VectorDouble> coeff_expansion_ptr)
659 : AssemblyDomainEleOp(row_field_name, col_field_name,
660 AssemblyDomainEleOp::OPROWCOL),
661 elasticCommonDataPtr(elastic_common_data_ptr),
662 coeffExpansionPtr(coeff_expansion_ptr) {
663 this->sYmm = false;
664}
665
666template <int DIM, typename AssemblyDomainEleOp, int S>
667MoFEMErrorCode
669 iNtegrate(EntitiesFieldData::EntData &row_data,
670 EntitiesFieldData::EntData &col_data) {
672
673 auto &locMat = AssemblyDomainEleOp::locMat;
674
675 const auto nb_integration_pts = row_data.getN().size1();
676 const auto nb_row_base_functions = row_data.getN().size2();
677 auto t_w = this->getFTensor0IntegrationWeight();
678
679 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
680 auto t_row_diff_base = row_data.getFTensor1DiffN<DIM>();
681 auto t_D = getFTensor4DdgFromMat<DIM, DIM, 0>(*elasticCommonDataPtr->matDPtr);
682 auto t_grad =
683 getFTensor2FromMat<DIM, DIM>(*(elasticCommonDataPtr->matGradPtr));
684 auto t_logC_dC =
685 getFTensor4DdgFromMat<DIM, DIM>(elasticCommonDataPtr->matLogCdC);
688
689 FTensor::Index<'i', DIM> i;
690 FTensor::Index<'j', DIM> j;
691 FTensor::Index<'k', DIM> k;
692 FTensor::Index<'l', DIM> l;
693 FTensor::Index<'m', DIM> m;
694 FTensor::Index<'n', DIM> n;
695 FTensor::Index<'o', DIM> o;
696
698 t_coeff_exp(i, j) = 0;
699 for (auto d = 0; d != SPACE_DIM; ++d) {
700 t_coeff_exp(d, d) = (*coeffExpansionPtr)[d];
701 }
702
703 t_eigen_strain(i, j) = (t_D(i, j, k, l) * t_coeff_exp(k, l));
704
705 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
706
707 t_F(i, j) = t_grad(i, j) + t_kd(i, j);
708
709 double alpha = this->getMeasure() * t_w;
710 auto rr = 0;
711 for (; rr != AssemblyDomainEleOp::nbRows / DIM; ++rr) {
712 auto t_mat =
713 getFTensor1FromMat<DIM, 1,
714 DataLayoutTraits<DataLayout::CoeffsByGauss>>(
715 locMat, rr * DIM);
716 auto t_col_base = col_data.getFTensor0N(gg, 0);
717 for (auto cc = 0; cc != AssemblyDomainEleOp::nbCols; cc++) {
718#ifdef HENCKY_SMALL_STRAIN
719 t_mat(i) -=
720 (t_row_diff_base(j) * t_eigen_strain(i, j)) * (t_col_base * alpha);
721#else
722 t_mat(i) -= (t_row_diff_base(j) *
723 (t_F(i, o) * ((t_D(m, n, k, l) * t_coeff_exp(k, l)) *
724 t_logC_dC(m, n, o, j)))) *
725 (t_col_base * alpha);
726#endif
727
728 ++t_mat;
729 ++t_col_base;
730 }
731
732 ++t_row_diff_base;
733 }
734 for (; rr != nb_row_base_functions; ++rr)
735 ++t_row_diff_base;
736
737 ++t_w;
738 ++t_grad;
739 ++t_logC_dC;
740 ++t_D;
741 }
742
744}
745
746//! [Hencky integrators]
747template <typename DomainEleOp> struct HenckyIntegrators {
748 template <int DIM, IntegrationType I>
750
751 template <int DIM, IntegrationType I>
753
754 template <int DIM, IntegrationType I>
756
757 template <int DIM, IntegrationType I, int S>
760
761 template <int DIM, IntegrationType I, int S>
764
765 template <int DIM, IntegrationType I, int S>
768
769 template <int DIM, IntegrationType I, int S>
772
773 template <int DIM, IntegrationType I, int S>
775
776 template <int DIM, IntegrationType I, typename AssemblyDomainEleOp, int S>
779};
780//! [Hencky integrators]
781
782//! [Add material block operations]
783template <int DIM>
784MoFEMErrorCode
786 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
787 std::string block_name,
788 boost::shared_ptr<MatrixDouble> mat_D_Ptr, Sev sev,
789 double scale = 1) {
791
792 PetscBool plane_strain_flag = PETSC_FALSE;
793 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-plane_strain",
794 &plane_strain_flag, PETSC_NULLPTR);
795
796 struct OpMatBlocks : public DomainEleOp {
797 OpMatBlocks(boost::shared_ptr<MatrixDouble> m, double bulk_modulus_K,
798 double shear_modulus_G, MoFEM::Interface &m_field, Sev sev,
799 std::vector<const CubitMeshSets *> meshset_vec_ptr,
800 double scale, PetscBool plane_strain_flag)
801 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE), matDPtr(m),
802 bulkModulusKDefault(bulk_modulus_K),
803 shearModulusGDefault(shear_modulus_G), scaleYoungModulus(scale),
804 planeStrainFlag(plane_strain_flag) {
805 CHK_THROW_MESSAGE(extractBlockData(m_field, meshset_vec_ptr, sev),
806 "Can not get data from block");
807 }
808
809 MoFEMErrorCode doWork(int side, EntityType type,
810 EntitiesFieldData::EntData &data) {
812
813 for (auto &b : blockData) {
814
815 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
816 CHKERR getMatDPtr(matDPtr, b.bulkModulusK * scaleYoungModulus,
817 b.shearModulusG * scaleYoungModulus,
818 planeStrainFlag);
820 }
821 }
822
823 CHKERR getMatDPtr(matDPtr, bulkModulusKDefault * scaleYoungModulus,
824 shearModulusGDefault * scaleYoungModulus,
825 planeStrainFlag);
827 }
828
829 private:
830 boost::shared_ptr<MatrixDouble> matDPtr;
831 const double scaleYoungModulus;
832 const PetscBool planeStrainFlag;
833
834 struct BlockData {
835 double bulkModulusK;
836 double shearModulusG;
837 Range blockEnts;
838 };
839
840 double bulkModulusKDefault;
841 double shearModulusGDefault;
842 std::vector<BlockData> blockData;
843
844 MoFEMErrorCode
845 extractBlockData(MoFEM::Interface &m_field,
846 std::vector<const CubitMeshSets *> meshset_vec_ptr,
847 Sev sev) {
849
850 for (auto m : meshset_vec_ptr) {
851 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock") << *m;
852 std::vector<double> block_data;
853 CHKERR m->getAttributes(block_data);
854 if (block_data.size() != 2) {
855 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
856 "Expected that block has two attribute");
857 }
858 auto get_block_ents = [&]() {
859 Range ents;
860 CHKERR
861 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
862 return ents;
863 };
864
865 double young_modulus = block_data[0];
866 double poisson_ratio = block_data[1];
867 double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
868 double shear_modulus_G = young_modulus / (2 * (1 + poisson_ratio));
869
870 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock")
871 << "E = " << young_modulus << " nu = " << poisson_ratio;
872
873 blockData.push_back(
874 {bulk_modulus_K, shear_modulus_G, get_block_ents()});
875 }
876 MOFEM_LOG_CHANNEL("WORLD");
878 }
879
880 // Compute elasticity tensor D
881 MoFEMErrorCode getMatDPtr(boost::shared_ptr<MatrixDouble> mat_D_ptr,
882 double bulk_modulus_K, double shear_modulus_G,
883 PetscBool is_plane_strain) {
885 //! [Calculate elasticity tensor]
886 auto set_material_stiffness = [&]() {
887 FTensor::Index<'i', DIM> i;
888 FTensor::Index<'j', DIM> j;
889 FTensor::Index<'k', DIM> k;
890 FTensor::Index<'l', DIM> l;
892 double A = (SPACE_DIM == 2 && !is_plane_strain)
893 ? 2 * shear_modulus_G /
894 (bulk_modulus_K + (4. / 3.) * shear_modulus_G)
895 : 1;
896 auto t_D = getFTensor4DdgFromMat<DIM, DIM, 0>(*mat_D_ptr);
897 t_D(i, j, k, l) =
898 2 * shear_modulus_G * ((t_kd(i, k) ^ t_kd(j, l)) / 4.) +
899 A * (bulk_modulus_K - (2. / 3.) * shear_modulus_G) * t_kd(i, j) *
900 t_kd(k, l);
901 };
902 //! [Calculate elasticity tensor]
903 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
904 mat_D_ptr->resize(1, size_symm * size_symm);
905 set_material_stiffness();
907 }
908 };
909
910 double E = 1.0;
911 double nu = 0.3;
912
913 PetscOptionsBegin(PETSC_COMM_WORLD, "", "", "none");
914 CHKERR PetscOptionsScalar("-young_modulus", "Young modulus", "", E, &E,
915 PETSC_NULLPTR);
916 CHKERR PetscOptionsScalar("-poisson_ratio", "poisson ratio", "", nu, &nu,
917 PETSC_NULLPTR);
918 PetscOptionsEnd();
919
920 double bulk_modulus_K = E / (3 * (1 - 2 * nu));
921 double shear_modulus_G = E / (2 * (1 + nu));
922 pip.push_back(new OpMatBlocks(
923 mat_D_Ptr, bulk_modulus_K, shear_modulus_G, m_field, sev,
924
925 // Get blockset using regular expression
926 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
927
928 (boost::format("%s(.*)") % block_name).str()
929
930 )),
931 scale, plane_strain_flag
932
933 ));
934
936}
937//! [Add material block operations]
938
939//! [commonDataFactory]
940template <int DIM, IntegrationType I, typename DomainEleOp>
942 MoFEM::Interface &m_field,
943 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
944 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
945
946 auto common_ptr = boost::make_shared<HenckyOps::CommonData>();
947 common_ptr->matDPtr = boost::make_shared<MatrixDouble>();
948 common_ptr->matGradPtr = boost::make_shared<MatrixDouble>();
949
950 CHK_THROW_MESSAGE(addMatBlockOps<DIM>(m_field, pip, block_name,
951 common_ptr->matDPtr, sev, scale),
952 "addMatBlockOps");
953
955
956 pip.push_back(new OpCalculateVectorFieldGradient<DIM, DIM>(
957 field_name, common_ptr->matGradPtr));
958 pip.push_back(new typename H::template OpCalculateEigenVals<DIM, I>(
959 field_name, common_ptr));
960 pip.push_back(
961 new typename H::template OpCalculateLogC<DIM, I>(field_name, common_ptr));
962 pip.push_back(new typename H::template OpCalculateLogC_dC<DIM, I>(
963 field_name, common_ptr));
964 // Assumes constant D matrix per entity
965 pip.push_back(new typename H::template OpCalculateHenckyStress<DIM, I, 0>(
966 field_name, common_ptr));
967 pip.push_back(new typename H::template OpCalculatePiolaStress<DIM, I, 0>(
968 field_name, common_ptr));
969
970 return common_ptr;
971}
972//! [commonDataFactory]
973
974//! [opFactoryDomainRhs]
975template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
976MoFEMErrorCode opFactoryDomainRhs(
977 MoFEM::Interface &m_field,
978 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
979 std::string field_name, boost::shared_ptr<HenckyOps::CommonData> common_ptr,
980 Sev sev) {
982
983 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
984 A>::template LinearForm<I>;
986 typename B::template OpGradTimesTensor<1, DIM, DIM>;
987 pip.push_back(
988 new OpInternalForcePiola("U", common_ptr->getMatFirstPiolaStress()));
989
991}
992
993template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
994MoFEMErrorCode opFactoryDomainRhs(
995 MoFEM::Interface &m_field,
996 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
997 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
999
1000 auto common_ptr = commonDataFactory<DIM, I, DomainEleOp>(
1001 m_field, pip, field_name, block_name, sev, scale);
1002 CHKERR opFactoryDomainRhs<DIM, A, I, DomainEleOp>(m_field, pip, field_name,
1003 common_ptr, sev);
1004
1006}
1007//! [opFactoryDomainRhs]
1008
1009//! [opFactoryDomainLhs]
1010template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
1011MoFEMErrorCode opFactoryDomainLhs(
1012 MoFEM::Interface &m_field,
1013 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1014 std::string field_name, boost::shared_ptr<HenckyOps::CommonData> common_ptr,
1015 Sev sev) {
1017
1018 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
1019 A>::template BiLinearForm<I>;
1020 using OpKPiola = typename B::template OpGradTensorGrad<1, DIM, DIM, -1>;
1021
1023 // Assumes constant D matrix per entity
1024 pip.push_back(new typename H::template OpHenckyTangent<DIM, I, 0>(
1025 field_name, common_ptr));
1026 pip.push_back(
1027 new OpKPiola(field_name, field_name, common_ptr->getMatTangent()));
1028
1030}
1031
1032template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
1033MoFEMErrorCode opFactoryDomainLhs(
1034 MoFEM::Interface &m_field,
1035 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1036 std::string field_name, std::string block_name, Sev sev, double scale = 1) {
1038
1039 auto common_ptr = commonDataFactory<DIM, I, DomainEleOp>(
1040 m_field, pip, field_name, block_name, sev, scale);
1041 CHKERR opFactoryDomainLhs<DIM, A, I, DomainEleOp>(m_field, pip, field_name,
1042 common_ptr, sev);
1043
1045}
1046//! [opFactoryDomainLhs]
1047
1048} // namespace HenckyOps
1049
1050#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.
[HenckyOps]
Definition HenckyOps.hpp:12
auto get_uniq_nb(double *ptr)
Definition HenckyOps.hpp:25
auto sort_eigen_vals(FTensor::Tensor1< double, DIM > &eig, FTensor::Tensor2< double, DIM, DIM > &eigen_vec)
Definition HenckyOps.hpp:33
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]
static const double eps
Definition HenckyOps.hpp:14
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]
bool is_eq(const double &a, const double &b)
Definition HenckyOps.hpp:20
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
[Hencky common data]
Definition HenckyOps.hpp:71
MatrixDouble matEigVec
Definition HenckyOps.hpp:77
boost::shared_ptr< MatrixDouble > matLogCPlastic
Definition HenckyOps.hpp:74
MatrixDouble matHenckyStress
Definition HenckyOps.hpp:82
MatrixDouble matLogCdC
Definition HenckyOps.hpp:79
MatrixDouble matEigVal
Definition HenckyOps.hpp:76
MatrixDouble matFirstPiolaStress
Definition HenckyOps.hpp:80
boost::shared_ptr< MatrixDouble > matDPtr
Definition HenckyOps.hpp:73
MatrixDouble matSecondPiolaStress
Definition HenckyOps.hpp:81
MatrixDouble matLogC
Definition HenckyOps.hpp:78
MatrixDouble matTangent
Definition HenckyOps.hpp:83
boost::shared_ptr< MatrixDouble > matGradPtr
Definition HenckyOps.hpp:72
[Hencky integrators]
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:125
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:126
double scale
Definition plastic.cpp:123
constexpr auto size_symm
Definition plastic.cpp:42
double H
Hardening.
Definition plastic.cpp:128