v0.15.0
Loading...
Searching...
No Matches
HMHHencky.cpp
Go to the documentation of this file.
1/**
2 * @file Hencky.cpp
3 * @brief Implementation of Hencky material
4 * @date 2024-08-31
5 *
6 * @copyright Copyright (c) 2024
7 *
8 */
9
10namespace EshelbianPlasticity {
11
13
14 HMHHencky(MoFEM::Interface &m_field, const double E, const double nu)
15 : PhysicalEquations(0, 0), mField(m_field), E(E), nu(nu) {}
16
17 MoFEMErrorCode recordTape(const int tag, DTensor2Ptr *t_h) { return 0; }
18
19 struct OpHenckyJacobian : public OpJacobian {
20 OpHenckyJacobian(boost::shared_ptr<DataAtIntegrationPts> data_ptr,
21 boost::shared_ptr<HMHHencky> hencky_ptr)
22 : OpJacobian(), dataAtGaussPts(data_ptr), henckyPtr(hencky_ptr) {
24 "getOptions failed");
25 CHK_THROW_MESSAGE(henckyPtr->extractBlockData(Sev::verbose),
26 "Can not get data from block");
27 }
28
29 MoFEMErrorCode doWork(int side, EntityType type,
30 EntitiesFieldData::EntData &data) {
32
33 for (auto &b : henckyPtr->blockData) {
34 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
35 dataAtGaussPts->mu = b.shearModulusG;
36 dataAtGaussPts->lambda = b.bulkModulusK - 2 * b.shearModulusG / 3;
37 CHKERR henckyPtr->getMatDPtr(dataAtGaussPts->getMatDPtr(),
38 dataAtGaussPts->getMatAxiatorDPtr(),
39 dataAtGaussPts->getMatDeviatorDPtr(),
40 b.bulkModulusK, b.shearModulusG);
42 }
43 }
44 const auto E = henckyPtr->E;
45 const auto nu = henckyPtr->nu;
46
47 double bulk_modulus_K = E / (3 * (1 - 2 * nu));
48 double shear_modulus_G = E / (2 * (1 + nu));
49
52
53 CHKERR henckyPtr->getMatDPtr(dataAtGaussPts->getMatDPtr(),
54 dataAtGaussPts->getMatAxiatorDPtr(),
55 dataAtGaussPts->getMatDeviatorDPtr(),
57
59 }
60
61 MoFEMErrorCode evaluateRhs(EntData &data) { return 0; }
62 MoFEMErrorCode evaluateLhs(EntData &data) { return 0; }
63
64 private:
65 boost::shared_ptr<DataAtIntegrationPts> dataAtGaussPts;
66 boost::shared_ptr<HMHHencky> henckyPtr;
67 };
68
69 virtual OpJacobian *
70 returnOpJacobian(const int tag, const bool eval_rhs, const bool eval_lhs,
71 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
72 boost::shared_ptr<PhysicalEquations> physics_ptr) {
73 return (new OpHenckyJacobian(
74 data_ptr, boost::dynamic_pointer_cast<HMHHencky>(physics_ptr)));
75 }
76
78
79 OpSpatialPhysical(const std::string &field_name,
80 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
81 const double alpha_u);
82
83 MoFEMErrorCode integrate(EntData &data);
84
85 MoFEMErrorCode integrateHencky(EntData &data);
86
87 MoFEMErrorCode integratePolyconvexHencky(EntData &data);
88
89 private:
90 const double alphaU;
91 PetscBool polyConvex = PETSC_FALSE;
92 };
93
94 virtual VolUserDataOperator *
96 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
97 const double alpha_u) {
98 return new OpSpatialPhysical(field_name, data_ptr, alpha_u);
99 }
100
102 const double alphaU;
103 OpSpatialPhysical_du_du(std::string row_field, std::string col_field,
104 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
105 const double alpha);
106 MoFEMErrorCode integrate(EntData &row_data, EntData &col_data);
107 MoFEMErrorCode integrateHencky(EntData &row_data, EntData &col_data);
108 MoFEMErrorCode integratePolyconvexHencky(EntData &row_data,
109 EntData &col_data);
110
111 private:
112 PetscBool polyConvex = PETSC_FALSE;
113
114 MatrixDouble dP;
115 };
116
118 std::string row_field, std::string col_field,
119 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const double alpha) {
120 return new OpSpatialPhysical_du_du(row_field, col_field, data_ptr, alpha);
121 }
122
123 /**
124 * @brief Calculate energy density for Hencky material model
125 *
126 *
127 * \f[
128 *
129 * \Psi(\log{\mathbf{U}}) = \frac{1}{2} U_{IJ} D_{IJKL} U_{KL} = \frac{1}{2}
130 * U_{IJ} T_{IJ}
131 *
132 * \f]
133 * where \f$T_{IJ} = D_{IJKL} U_{KL}\f$ is a a Hencky stress.
134 *
135 */
137
138 OpCalculateEnergy(boost::shared_ptr<DataAtIntegrationPts> data_ptr,
139 boost::shared_ptr<double> total_energy_ptr);
140 MoFEMErrorCode doWork(int side, EntityType type, EntData &data);
141
142 private:
143 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
144 boost::shared_ptr<double> totalEnergyPtr;
145 };
146
148 returnOpCalculateEnergy(boost::shared_ptr<DataAtIntegrationPts> data_ptr,
149 boost::shared_ptr<double> total_energy_ptr) {
150 return new OpCalculateEnergy(data_ptr, total_energy_ptr);
151 }
152
155 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
156 boost::shared_ptr<MatrixDouble> strain_ptr,
157 boost::shared_ptr<MatrixDouble> stress_ptr,
158 boost::shared_ptr<HMHHencky> hencky_ptr);
159 MoFEMErrorCode doWork(int side, EntityType type, EntData &data);
160
161 private:
162 boost::shared_ptr<DataAtIntegrationPts>
163 dataAtPts; ///< data at integration pts
164 boost::shared_ptr<MatrixDouble> strainPtr;
165 boost::shared_ptr<MatrixDouble> stressPtr;
166 boost::shared_ptr<HMHHencky> henckyPtr;
167 };
168
170 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
171 boost::shared_ptr<PhysicalEquations> physics_ptr) {
173 data_ptr, data_ptr->getLogStretchTensorAtPts(),
174 data_ptr->getApproxPAtPts(),
175 boost::dynamic_pointer_cast<HMHHencky>(physics_ptr));
176 }
177
179 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
180 boost::shared_ptr<PhysicalEquations> physics_ptr) {
182 data_ptr, data_ptr->getVarLogStreachPts(), data_ptr->getVarPiolaPts(),
183 boost::dynamic_pointer_cast<HMHHencky>(physics_ptr));
184 }
185
186 MoFEMErrorCode getOptions(boost::shared_ptr<DataAtIntegrationPts> data_ptr) {
188 PetscOptionsBegin(PETSC_COMM_WORLD, "hencky_", "", "none");
189
190 CHKERR PetscOptionsScalar("-young_modulus", "Young modulus", "", E, &E,
191 PETSC_NULLPTR);
192 CHKERR PetscOptionsScalar("-poisson_ratio", "poisson ratio", "", nu, &nu,
193 PETSC_NULLPTR);
194
195 PetscOptionsEnd();
196
198 << "Hencky: E = " << E << " nu = " << nu;
199 getOptionsSeverityLevels = Sev::verbose;
200
201 CHKERRG(ierr);
202
204 }
205
206 MoFEMErrorCode extractBlockData(Sev sev) {
207 return extractBlockData(
208
209 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
210
211 (boost::format("%s(.*)") % "MAT_ELASTIC").str()
212
213 )),
214
215 sev);
216 }
217
218 MoFEMErrorCode
219 extractBlockData(std::vector<const CubitMeshSets *> meshset_vec_ptr,
220 Sev sev) {
222
223 for (auto m : meshset_vec_ptr) {
224 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock") << *m;
225 std::vector<double> block_data;
226 CHKERR m->getAttributes(block_data);
227 if (block_data.size() < 2) {
228 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
229 "Expected that block has atleast two attributes");
230 }
231 auto get_block_ents = [&]() {
232 Range ents;
233 CHKERR mField.get_moab().get_entities_by_handle(m->meshset, ents, true);
234 return ents;
235 };
236
237 double young_modulus = block_data[0];
238 double poisson_ratio = block_data[1];
239 double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
240 double shear_modulus_G = young_modulus / (2 * (1 + poisson_ratio));
241
242 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock")
243 << "E = " << young_modulus << " nu = " << poisson_ratio;
244
245 blockData.push_back({bulk_modulus_K, shear_modulus_G, get_block_ents()});
246 }
247 MOFEM_LOG_CHANNEL("WORLD");
249 }
250
251 MoFEMErrorCode getMatDPtr(boost::shared_ptr<MatrixDouble> mat_D_ptr,
252 boost::shared_ptr<MatrixDouble> mat_axiator_D_ptr,
253 boost::shared_ptr<MatrixDouble> mat_deviator_D_ptr,
254 double bulk_modulus_K, double shear_modulus_G) {
256 //! [Calculate elasticity tensor]
257 auto set_material_stiffness = [&]() {
263 auto t_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, 0>(
264 &*(mat_D_ptr->data().begin()));
265 auto t_axiator_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, 0>(
266 &*mat_axiator_D_ptr->data().begin());
267 auto t_deviator_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, 0>(
268 &*mat_deviator_D_ptr->data().begin());
269 t_axiator_D(i, j, k, l) = (bulk_modulus_K - (2. / 3.) * shear_modulus_G) *
270 t_kd(i, j) * t_kd(k, l);
271 t_deviator_D(i, j, k, l) =
272 2 * shear_modulus_G * ((t_kd(i, k) ^ t_kd(j, l)) / 4.);
273 t_D(i, j, k, l) = t_axiator_D(i, j, k, l) + t_deviator_D(i, j, k, l);
274 };
275 //! [Calculate elasticity tensor]
276 constexpr auto size_symm = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
277 mat_D_ptr->resize(size_symm, size_symm, false);
278 mat_axiator_D_ptr->resize(size_symm, size_symm, false);
279 mat_deviator_D_ptr->resize(size_symm, size_symm, false);
280 set_material_stiffness();
282 }
283
284 MoFEMErrorCode
285 getInvMatDPtr(boost::shared_ptr<MatrixDouble> mat_inv_D_ptr,
286 double bulk_modulus_K, double shear_modulus_G) {
288 //! [Calculate elasticity tensor]
289 auto set_material_compilance = [&]() {
295 const double A = 1. / (2. * shear_modulus_G);
296 const double B =
297 (1. / (9. * bulk_modulus_K)) - (1. / (6. * shear_modulus_G));
298 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, 0>(
299 &*(mat_inv_D_ptr->data().begin()));
300 t_inv_D(i, j, k, l) =
301 A * ((t_kd(i, k) ^ t_kd(j, l)) / 4.) + B * t_kd(i, j) * t_kd(k, l);
302 };
303 //! [Calculate elasticity tensor]
304 constexpr auto size_symm = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
305 mat_inv_D_ptr->resize(size_symm, size_symm, false);
306 set_material_compilance();
308 }
309
310private:
312
318 std::vector<BlockData> blockData;
319
320 double E;
321 double nu;
322
323 // Set verbosity level, it verbile can changes that informatno is pronated
324 // only once at particular level
325 Sev getOptionsSeverityLevels = Sev::inform;
326};
327
329 const std::string &field_name,
330 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const double alpha_u)
331 : OpAssembleVolume(field_name, data_ptr, OPROW), alphaU(alpha_u) {
332
333 CHK_MOAB_THROW(PetscOptionsGetBool(PETSC_NULLPTR, "", "-poly_convex",
334 &polyConvex, PETSC_NULLPTR),
335 "get polyconvex option failed");
336}
337
340 if (polyConvex) {
341 CHKERR integratePolyconvexHencky(data);
342 } else {
343 CHKERR integrateHencky(data);
344 }
346}
347
350
352 auto t_L = symm_L_tensor();
353
354 int nb_dofs = data.getIndices().size();
355 int nb_integration_pts = data.getN().size1();
356 auto v = getVolume();
357 auto t_w = getFTensor0IntegrationWeight();
358 auto t_approx_P_adjoint_log_du =
359 getFTensor1FromMat<size_symm>(dataAtPts->adjointPdUAtPts);
360 auto t_log_stretch_h1 =
361 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchTotalTensorAtPts);
362 auto t_dot_log_u =
363 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchDotTensorAtPts);
364
365 auto t_D = getFTensor4DdgFromPtr<3, 3, 0>(&*dataAtPts->matD.data().begin());
366
367 FTensor::Index<'i', 3> i;
368 FTensor::Index<'j', 3> j;
369 FTensor::Index<'k', 3> k;
370 FTensor::Index<'l', 3> l;
371 auto get_ftensor2 = [](auto &v) {
373 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
374 };
375
376 int nb_base_functions = data.getN().size2();
377 auto t_row_base_fun = data.getFTensor0N();
378 for (int gg = 0; gg != nb_integration_pts; ++gg) {
379 double a = v * t_w;
380 auto t_nf = get_ftensor2(nF);
381
383 t_T(i, j) =
384 t_D(i, j, k, l) * (t_log_stretch_h1(k, l) + alphaU * t_dot_log_u(k, l));
386 t_residual(L) =
387 a * (t_approx_P_adjoint_log_du(L) - t_L(i, j, L) * t_T(i, j));
388
389 int bb = 0;
390 for (; bb != nb_dofs / 6; ++bb) {
391 t_nf(L) -= t_row_base_fun * t_residual(L);
392 ++t_nf;
393 ++t_row_base_fun;
394 }
395 for (; bb != nb_base_functions; ++bb)
396 ++t_row_base_fun;
397
398 ++t_w;
399 ++t_approx_P_adjoint_log_du;
400 ++t_dot_log_u;
401 ++t_log_stretch_h1;
402 }
404}
405
406MoFEMErrorCode
409
411 auto t_L = symm_L_tensor();
412
413 int nb_dofs = data.getIndices().size();
414 int nb_integration_pts = data.getN().size1();
415 auto v = getVolume();
416 auto t_w = getFTensor0IntegrationWeight();
417 auto t_approx_P_adjoint_log_du =
418 getFTensor1FromMat<size_symm>(dataAtPts->adjointPdUAtPts);
419 auto t_log_stretch_h1 =
420 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchTotalTensorAtPts);
421 auto t_dot_log_u =
422 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchDotTensorAtPts);
423
424 auto t_D = getFTensor4DdgFromPtr<3, 3, 0>(&*dataAtPts->matD.data().begin());
425
426 FTensor::Index<'i', 3> i;
427 FTensor::Index<'j', 3> j;
428 FTensor::Index<'k', 3> k;
429 FTensor::Index<'l', 3> l;
430 auto get_ftensor2 = [](auto &v) {
432 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
433 };
434
435 constexpr double nohat_k = 1. / 4;
436 constexpr double hat_k = 1. / 8;
437 double mu = dataAtPts->mu;
438 double lambda = dataAtPts->lambda;
439
440 constexpr double third = boost::math::constants::third<double>();
442 auto t_diff_deviator = diff_deviator(diff_tensor());
443
444 int nb_base_functions = data.getN().size2();
445 auto t_row_base_fun = data.getFTensor0N();
446 for (int gg = 0; gg != nb_integration_pts; ++gg) {
447 double a = v * t_w;
448 auto t_nf = get_ftensor2(nF);
449
450 double log_det = t_log_stretch_h1(i, i);
451 double log_det2 = log_det * log_det;
453 t_dev(i, j) = t_log_stretch_h1(i, j) - t_kd(i, j) * (third * log_det);
454 double dev_norm2 = t_dev(i, j) * t_dev(i, j);
455
457 auto A = 2 * mu * std::exp(nohat_k * dev_norm2);
458 auto B = lambda * std::exp(hat_k * log_det2) * log_det;
459 t_T(i, j) =
460
461 A * (t_dev(k, l) * t_diff_deviator(k, l, i, j))
462
463 +
464
465 B * t_kd(i, j)
466
467 +
468
469 alphaU * t_D(i, j, k, l) * t_dot_log_u(k, l);
470
472 t_residual(L) =
473 a * (t_approx_P_adjoint_log_du(L) - t_L(i, j, L) * t_T(i, j));
474
475 int bb = 0;
476 for (; bb != nb_dofs / size_symm; ++bb) {
477 t_nf(L) -= t_row_base_fun * t_residual(L);
478 ++t_nf;
479 ++t_row_base_fun;
480 }
481 for (; bb != nb_base_functions; ++bb)
482 ++t_row_base_fun;
483
484 ++t_w;
485 ++t_approx_P_adjoint_log_du;
486 ++t_dot_log_u;
487 ++t_log_stretch_h1;
488 }
490}
491
493 std::string row_field, std::string col_field,
494 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const double alpha)
495 : OpAssembleVolume(row_field, col_field, data_ptr, OPROWCOL, false),
496 alphaU(alpha) {
497 sYmm = false;
498
499 CHK_MOAB_THROW(PetscOptionsGetBool(PETSC_NULLPTR, "", "-poly_convex",
500 &polyConvex, PETSC_NULLPTR),
501 "get polyconvex option failed");
502}
503
504MoFEMErrorCode
506 EntData &col_data) {
508
509 if (polyConvex) {
510 CHKERR integratePolyconvexHencky(row_data, col_data);
511 } else {
512 CHKERR integrateHencky(row_data, col_data);
513 }
515}
516
517MoFEMErrorCode
519 EntData &col_data) {
521
524 auto t_L = symm_L_tensor();
525 auto t_diff = diff_tensor();
526
527 int nb_integration_pts = row_data.getN().size1();
528 int row_nb_dofs = row_data.getIndices().size();
529 int col_nb_dofs = col_data.getIndices().size();
530
531 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
533 size_symm>(
534
535 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2), &m(r + 0, c + 3),
536 &m(r + 0, c + 4), &m(r + 0, c + 5),
537
538 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2), &m(r + 1, c + 3),
539 &m(r + 1, c + 4), &m(r + 1, c + 5),
540
541 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2), &m(r + 2, c + 3),
542 &m(r + 2, c + 4), &m(r + 2, c + 5),
543
544 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2), &m(r + 3, c + 3),
545 &m(r + 3, c + 4), &m(r + 3, c + 5),
546
547 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2), &m(r + 4, c + 3),
548 &m(r + 4, c + 4), &m(r + 4, c + 5),
549
550 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2), &m(r + 5, c + 3),
551 &m(r + 5, c + 4), &m(r + 5, c + 5)
552
553 );
554 };
555 FTensor::Index<'i', 3> i;
556 FTensor::Index<'j', 3> j;
557 FTensor::Index<'k', 3> k;
558 FTensor::Index<'l', 3> l;
559 FTensor::Index<'m', 3> m;
560 FTensor::Index<'n', 3> n;
561
562 auto v = getVolume();
563 auto t_w = getFTensor0IntegrationWeight();
564
565 auto t_approx_P_adjoint_dstretch =
566 getFTensor2FromMat<3, 3>(dataAtPts->adjointPdstretchAtPts);
567 auto t_eigen_vals = getFTensor1FromMat<3>(dataAtPts->eigenVals);
568 auto t_eigen_vecs = getFTensor2FromMat<3, 3>(dataAtPts->eigenVecs);
569
570 int row_nb_base_functions = row_data.getN().size2();
571 auto t_row_base_fun = row_data.getFTensor0N();
572
573 auto get_dP = [&]() {
574 dP.resize(size_symm * size_symm, nb_integration_pts, false);
575 auto ts_a = getTSa();
576
577 auto t_D = getFTensor4DdgFromPtr<3, 3, 0>(&*dataAtPts->matD.data().begin());
579 t_dP_tmp(L, J) = -(1 + alphaU * ts_a) *
580 (t_L(i, j, L) *
581 ((t_D(i, j, m, n) * t_diff(m, n, k, l)) * t_L(k, l, J)));
582
585 auto t_approx_P_adjoint_dstretch =
586 getFTensor2FromMat<3, 3>(dataAtPts->adjointPdstretchAtPts);
587 auto t_eigen_vals = getFTensor1FromMat<3>(dataAtPts->eigenVals);
588 auto t_eigen_vecs = getFTensor2FromMat<3, 3>(dataAtPts->eigenVecs);
589 auto &nbUniq = dataAtPts->nbUniq;
590
591 auto t_dP = getFTensor2FromMat<size_symm, size_symm>(dP);
592 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
593
594 // Work of symmetric tensor on undefined tensor is equal to the work
595 // of the symmetric part of it
597 t_sym(i, j) = (t_approx_P_adjoint_dstretch(i, j) ||
598 t_approx_P_adjoint_dstretch(j, i));
599 t_sym(i, j) /= 2.0;
600 auto t_diff2_uP2 = EigenMatrix::getDiffDiffMat(
601 t_eigen_vals, t_eigen_vecs, EshelbianCore::f, EshelbianCore::d_f,
602 EshelbianCore::dd_f, t_sym, nbUniq[gg]);
603 t_dP(L, J) = t_L(i, j, L) *
604 ((t_diff2_uP2(i, j, k, l) + t_diff2_uP2(k, l, i, j)) *
605 t_L(k, l, J)) /
606 2. +
607 t_dP_tmp(L, J);
608
609 ++t_dP;
610 ++t_approx_P_adjoint_dstretch;
611 ++t_eigen_vals;
612 ++t_eigen_vecs;
613 }
614 } else {
615 auto t_dP = getFTensor2FromMat<size_symm, size_symm>(dP);
616 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
617 t_dP(L, J) = t_dP_tmp(L, J);
618 ++t_dP;
619 }
620 }
621
622 return getFTensor2FromMat<size_symm, size_symm>(dP);
623 };
624
625 auto t_dP = get_dP();
626 for (int gg = 0; gg != nb_integration_pts; ++gg) {
627 double a = v * t_w;
628
629 int rr = 0;
630 for (; rr != row_nb_dofs / 6; ++rr) {
631 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
632 auto t_m = get_ftensor2(K, 6 * rr, 0);
633 for (int cc = 0; cc != col_nb_dofs / 6; ++cc) {
634 const double b = a * t_row_base_fun * t_col_base_fun;
635 t_m(L, J) -= b * t_dP(L, J);
636 ++t_m;
637 ++t_col_base_fun;
638 }
639 ++t_row_base_fun;
640 }
641
642 for (; rr != row_nb_base_functions; ++rr) {
643 ++t_row_base_fun;
644 }
645
646 ++t_w;
647 ++t_dP;
648 }
650}
651
653 EntData &row_data, EntData &col_data) {
655
658 auto t_L = symm_L_tensor();
659 auto t_diff = diff_tensor();
660
661 int nb_integration_pts = row_data.getN().size1();
662 int row_nb_dofs = row_data.getIndices().size();
663 int col_nb_dofs = col_data.getIndices().size();
664
665 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
667 size_symm>(
668
669 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2), &m(r + 0, c + 3),
670 &m(r + 0, c + 4), &m(r + 0, c + 5),
671
672 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2), &m(r + 1, c + 3),
673 &m(r + 1, c + 4), &m(r + 1, c + 5),
674
675 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2), &m(r + 2, c + 3),
676 &m(r + 2, c + 4), &m(r + 2, c + 5),
677
678 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2), &m(r + 3, c + 3),
679 &m(r + 3, c + 4), &m(r + 3, c + 5),
680
681 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2), &m(r + 4, c + 3),
682 &m(r + 4, c + 4), &m(r + 4, c + 5),
683
684 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2), &m(r + 5, c + 3),
685 &m(r + 5, c + 4), &m(r + 5, c + 5)
686
687 );
688 };
689 FTensor::Index<'i', 3> i;
690 FTensor::Index<'j', 3> j;
691 FTensor::Index<'k', 3> k;
692 FTensor::Index<'l', 3> l;
693 FTensor::Index<'m', 3> m;
694 FTensor::Index<'n', 3> n;
695
696 auto v = getVolume();
697 auto t_w = getFTensor0IntegrationWeight();
698
699 int row_nb_base_functions = row_data.getN().size2();
700 auto t_row_base_fun = row_data.getFTensor0N();
701
702 auto get_dP = [&]() {
703 dP.resize(size_symm * size_symm, nb_integration_pts, false);
704 auto ts_a = getTSa();
705
706 auto t_D = getFTensor4DdgFromPtr<3, 3, 0>(&*dataAtPts->matD.data().begin());
707
708 constexpr double nohat_k = 1. / 4;
709 constexpr double hat_k = 1. / 8;
710 double mu = dataAtPts->mu;
711 double lambda = dataAtPts->lambda;
712
713 constexpr double third = boost::math::constants::third<double>();
715 auto t_diff_deviator = diff_deviator(diff_tensor());
716
717 auto t_approx_P_adjoint_dstretch =
718 getFTensor2FromMat<3, 3>(dataAtPts->adjointPdstretchAtPts);
719 auto t_log_stretch_h1 =
720 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchTotalTensorAtPts);
721 auto t_eigen_vals = getFTensor1FromMat<3>(dataAtPts->eigenVals);
722 auto t_eigen_vecs = getFTensor2FromMat<3, 3>(dataAtPts->eigenVecs);
723 auto &nbUniq = dataAtPts->nbUniq;
724
725 auto t_dP = getFTensor2FromMat<size_symm, size_symm>(dP);
726 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
727
728 double log_det = t_log_stretch_h1(i, i);
729 double log_det2 = log_det * log_det;
731 t_dev(i, j) = t_log_stretch_h1(i, j) - t_kd(i, j) * (third * log_det);
732 double dev_norm2 = t_dev(i, j) * t_dev(i, j);
733
734 auto A = 2 * mu * std::exp(nohat_k * dev_norm2);
735 auto B = lambda * std::exp(hat_k * log_det2) * log_det;
736
737 FTensor::Tensor2_symmetric<double, 3> t_A_diff, t_B_diff;
738 t_A_diff(i, j) =
739 (A * 2 * nohat_k) * (t_dev(k, l) * t_diff_deviator(k, l, i, j));
740 t_B_diff(i, j) = (B * 2 * hat_k) * log_det * t_kd(i, j) +
741 lambda * std::exp(hat_k * log_det2) * t_kd(i, j);
743 t_dT(i, j, k, l) =
744 t_A_diff(i, j) * (t_dev(m, n) * t_diff_deviator(m, n, k, l))
745
746 +
747
748 A * t_diff_deviator(m, n, i, j) * t_diff_deviator(m, n, k, l)
749
750 +
751
752 t_B_diff(i, j) * t_kd(k, l);
753
754 t_dP(L, J) = -t_L(i, j, L) *
755 ((
756
757 t_dT(i, j, k, l)
758
759 +
760
761 (alphaU * ts_a) * (t_D(i, j, m, n) * t_diff(m, n, k, l)
762
763 )) *
764 t_L(k, l, J));
765
766 // Work of symmetric tensor on undefined tensor is equal to the work
767 // of the symmetric part of it
771 t_sym(i, j) = (t_approx_P_adjoint_dstretch(i, j) ||
772 t_approx_P_adjoint_dstretch(j, i));
773 t_sym(i, j) /= 2.0;
774 auto t_diff2_uP2 = EigenMatrix::getDiffDiffMat(
775 t_eigen_vals, t_eigen_vecs, EshelbianCore::f, EshelbianCore::d_f,
776 EshelbianCore::dd_f, t_sym, nbUniq[gg]);
777 t_dP(L, J) += t_L(i, j, L) *
778 ((t_diff2_uP2(i, j, k, l) + t_diff2_uP2(k, l, i, j)) *
779 t_L(k, l, J)) /
780 2.;
781 }
782
783 ++t_dP;
784 ++t_approx_P_adjoint_dstretch;
785 ++t_log_stretch_h1;
786 ++t_eigen_vals;
787 ++t_eigen_vecs;
788 }
789
790 return getFTensor2FromMat<size_symm, size_symm>(dP);
791 };
792
793 auto t_dP = get_dP();
794 for (int gg = 0; gg != nb_integration_pts; ++gg) {
795 double a = v * t_w;
796
797 int rr = 0;
798 for (; rr != row_nb_dofs / 6; ++rr) {
799 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
800 auto t_m = get_ftensor2(K, 6 * rr, 0);
801 for (int cc = 0; cc != col_nb_dofs / 6; ++cc) {
802 const double b = a * t_row_base_fun * t_col_base_fun;
803 t_m(L, J) -= b * t_dP(L, J);
804 ++t_m;
805 ++t_col_base_fun;
806 }
807 ++t_row_base_fun;
808 }
809
810 for (; rr != row_nb_base_functions; ++rr) {
811 ++t_row_base_fun;
812 }
813
814 ++t_w;
815 ++t_dP;
816 }
818}
819
821 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
822 boost::shared_ptr<double> total_energy_ptr)
823 : VolUserDataOperator(NOSPACE, OPSPACE), dataAtPts(data_ptr),
824 totalEnergyPtr(total_energy_ptr) {
825
826 if (!dataAtPts) {
828 "dataAtPts is not allocated. Please set it before "
829 "using this operator.");
830 }
831
832}
833
834MoFEMErrorCode HMHHencky::OpCalculateEnergy::doWork(int side, EntityType type,
835 EntData &data) {
837
842
843 int nb_integration_pts = getGaussPts().size2();
844 auto t_log_u =
845 getFTensor2SymmetricFromMat<3>(dataAtPts->logStretchTotalTensorAtPts);
846
847
848 auto &mat_d = dataAtPts->matD;
849 if (mat_d.size1() != size_symm || mat_d.size2() != size_symm) {
850 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
851 "wrong matD size, should be 6 by 6 but is %d by %d", size_symm,
852 size_symm);
853 }
854
855 auto t_D = getFTensor4DdgFromPtr<3, 3, 0>(mat_d.data().data());
856
857 dataAtPts->energyAtPts.resize(nb_integration_pts, false);
858 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
859
860 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
861
862 t_energy = 0.5 * (t_log_u(i, j) * (t_D(i, j, k, l) * t_log_u(k, l)));
863
864 ++t_log_u;
865 ++t_energy;
866 }
867
868 if (totalEnergyPtr) {
869 auto t_w = getFTensor0IntegrationWeight();
870 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
871 double loc_energy = 0;
872 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
873 loc_energy += t_energy * t_w;
874 ++t_w;
875 ++t_energy;
876 }
877 *totalEnergyPtr += getMeasure() * loc_energy;
878 }
879
881}
882
884 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
885 boost::shared_ptr<MatrixDouble> strain_ptr,
886 boost::shared_ptr<MatrixDouble> stress_ptr,
887 boost::shared_ptr<HMHHencky> hencky_ptr)
888 : VolUserDataOperator(NOSPACE, OPSPACE), dataAtPts(data_ptr),
889 strainPtr(strain_ptr), stressPtr(stress_ptr), henckyPtr(hencky_ptr) {}
890
892 EntityType type,
893 EntData &data) {
895
902
903 auto nb_integration_pts = stressPtr->size2();
904#ifndef NDEBUG
905 if (nb_integration_pts != getGaussPts().size2()) {
906 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
907 "inconsistent number of integration points");
908 }
909#endif // NDEBUG
910
911 auto get_D = [&]() {
913 for (auto &b : henckyPtr->blockData) {
914
915 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
916 dataAtPts->mu = b.shearModulusG;
917 dataAtPts->lambda = b.bulkModulusK - 2 * b.shearModulusG / 3;
918 CHKERR henckyPtr->getMatDPtr(
919 dataAtPts->getMatDPtr(), dataAtPts->getMatAxiatorDPtr(),
920 dataAtPts->getMatDeviatorDPtr(), b.bulkModulusK, b.shearModulusG);
921 CHKERR henckyPtr->getInvMatDPtr(dataAtPts->getMatInvDPtr(),
922 b.bulkModulusK, b.shearModulusG);
924 }
925 }
926
927 const auto E = henckyPtr->E;
928 const auto nu = henckyPtr->nu;
929
930 double bulk_modulus_K = E / (3 * (1 - 2 * nu));
931 double shear_modulus_G = E / (2 * (1 + nu));
932
933 dataAtPts->mu = shear_modulus_G;
934 dataAtPts->lambda = bulk_modulus_K - 2 * shear_modulus_G / 3;
935
936 CHKERR henckyPtr->getMatDPtr(
937 dataAtPts->getMatDPtr(), dataAtPts->getMatAxiatorDPtr(),
938 dataAtPts->getMatDeviatorDPtr(), bulk_modulus_K, shear_modulus_G);
939 CHKERR henckyPtr->getInvMatDPtr(dataAtPts->getMatInvDPtr(), bulk_modulus_K,
942 };
943
944 CHKERR get_D();
945
946 strainPtr->resize(size_symm, nb_integration_pts, false);
947 auto t_strain = getFTensor2SymmetricFromMat<3>(*strainPtr);
948 auto t_stress = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*stressPtr);
949 auto t_inv_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, 0>(
950 &*dataAtPts->matInvD.data().begin());
951#ifndef NDEBUG
952 auto t_D = getFTensor4DdgFromPtr<SPACE_DIM, SPACE_DIM, 0>(
953 &*dataAtPts->matD.data().begin());
954#endif
955
956 const double lambda = dataAtPts->lambda;
957 const double mu = dataAtPts->mu;
959
960 // note: add rotation, so we can extract rigid body motion, work then with
961 // symmetric part.
962 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
963 t_strain(i, j) = t_inv_D(i, j, k, l) * t_stress(k, l);
964
965#ifndef NDEBUG
966 FTensor::Tensor2_symmetric<double, 3> t_stress_symm_debug;
967 t_stress_symm_debug(i, j) = (t_stress(i, j) || t_stress(j, i)) / 2;
968 FTensor::Tensor2_symmetric<double, 3> t_stress_symm_debug_diff;
969 t_stress_symm_debug_diff(i, j) =
970 t_D(i, j, k, l) * t_strain(k, l) - t_stress_symm_debug(i, j);
971 double nrm =
972 t_stress_symm_debug_diff(i, j) * t_stress_symm_debug_diff(i, j);
973 double nrm0 = t_stress_symm_debug(i, j) * t_stress_symm_debug(i, j) +
974 std::numeric_limits<double>::epsilon();
975 constexpr double eps = 1e-10;
976 if (std::fabs(std::sqrt(nrm / nrm0)) > eps) {
977 MOFEM_LOG("SELF", Sev::error)
978 << "Stress symmetry check failed: " << std::endl
979 << t_stress_symm_debug_diff << std::endl
980 << t_stress;
982 "Norm is too big: " + std::to_string(nrm / nrm0));
983 }
984 ++t_D;
985#endif
986
987 ++t_strain;
988 ++t_stress;
989 ++t_inv_D;
990 }
991
993}
994
995} // namespace EshelbianPlasticity
constexpr double third
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
#define FTENSOR_INDEX(DIM, I)
constexpr double a
static PetscErrorCode ierr
static const double eps
constexpr int SPACE_DIM
Kronecker Delta class symmetric.
#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 ...
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ 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
constexpr auto t_kd
auto get_D
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
FTensor::Index< 'i', SPACE_DIM > i
static double lambda
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
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 diff_deviator(FTensor::Ddg< double, 3, 3 > &&t_diff_stress)
static constexpr auto size_symm
constexpr AssemblyType A
double young_modulus
Young modulus.
Definition plastic.cpp:125
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:126
constexpr auto field_name
FTensor::Index< 'm', 3 > m
static enum StretchSelector stretchSelector
static enum RotSelector gradApproximator
static boost::function< double(const double)> f
static boost::function< double(const double)> dd_f
static boost::function< double(const double)> d_f
Calculate energy density for Hencky material model.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpCalculateEnergy(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< double > total_energy_ptr)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpCalculateStretchFromStress(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< HMHHencky > hencky_ptr)
MoFEMErrorCode evaluateRhs(EntData &data)
Definition HMHHencky.cpp:61
boost::shared_ptr< HMHHencky > henckyPtr
Definition HMHHencky.cpp:66
MoFEMErrorCode evaluateLhs(EntData &data)
Definition HMHHencky.cpp:62
OpHenckyJacobian(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< HMHHencky > hencky_ptr)
Definition HMHHencky.cpp:20
boost::shared_ptr< DataAtIntegrationPts > dataAtGaussPts
Definition HMHHencky.cpp:65
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Definition HMHHencky.cpp:29
OpSpatialPhysical_du_du(std::string row_field, std::string col_field, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha)
MoFEMErrorCode integrateHencky(EntData &row_data, EntData &col_data)
MoFEMErrorCode integratePolyconvexHencky(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integratePolyconvexHencky(EntData &data)
OpSpatialPhysical(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha_u)
MoFEMErrorCode integrateHencky(EntData &data)
virtual VolUserDataOperator * returnOpSpatialPhysical(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha_u)
Definition HMHHencky.cpp:95
VolUserDataOperator * returnOpCalculateStretchFromStress(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr)
MoFEMErrorCode extractBlockData(Sev sev)
std::vector< BlockData > blockData
MoFEMErrorCode extractBlockData(std::vector< const CubitMeshSets * > meshset_vec_ptr, Sev sev)
HMHHencky(MoFEM::Interface &m_field, const double E, const double nu)
Definition HMHHencky.cpp:14
virtual OpJacobian * returnOpJacobian(const int tag, const bool eval_rhs, const bool eval_lhs, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr)
Definition HMHHencky.cpp:70
VolUserDataOperator * returnOpCalculateVarStretchFromStress(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr)
VolUserDataOperator * returnOpCalculateEnergy(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< double > total_energy_ptr)
MoFEMErrorCode getMatDPtr(boost::shared_ptr< MatrixDouble > mat_D_ptr, boost::shared_ptr< MatrixDouble > mat_axiator_D_ptr, boost::shared_ptr< MatrixDouble > mat_deviator_D_ptr, double bulk_modulus_K, double shear_modulus_G)
MoFEMErrorCode getOptions(boost::shared_ptr< DataAtIntegrationPts > data_ptr)
VolUserDataOperator * returnOpSpatialPhysical_du_du(std::string row_field, std::string col_field, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha)
MoFEMErrorCode recordTape(const int tag, DTensor2Ptr *t_h)
Definition HMHHencky.cpp:17
MoFEMErrorCode getInvMatDPtr(boost::shared_ptr< MatrixDouble > mat_inv_D_ptr, double bulk_modulus_K, double shear_modulus_G)
virtual moab::Interface & get_moab()=0
bool sYmm
If true assume that matrix is symmetric structure.
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorInt & getIndices() const
Get global indices of dofs on entity.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.