v0.16.3
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
19
20static auto calc_effective_elastic_params(double E, double nu,
21 double diagonal_strain) {
22 const double c10 = E / (4.0 * (1.0 + nu));
23 // The coefficient of 0.5 * log(J)^2 is the Lame parameter lambda.
24 const double lambda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu));
25 const double shear_modulus_G =
26 2.0 * c10 * std::exp(-2.0 * diagonal_strain / 3.0);
27 const double bulk_modulus_K = lambda + 2.0 * shear_modulus_G / 3.0;
28 const double young_modulus =
29 shear_modulus_G * (3.0 * lambda + 2.0 * shear_modulus_G) /
31 const double poisson_ratio = lambda / (2.0 * (lambda + shear_modulus_G));
32
35}
36
38
39 HMHHencky(MoFEM::Interface &m_field, const double E, const double nu,
40 const Features features)
41 : PhysicalEquations(Hencky, features), mField(m_field), E(E), nu(nu) {
42 CHK_THROW_MESSAGE(getOptions(), "getOptions failed");
44 "Can not get data from block");
45 for (const auto &block : blockData) {
46 if (block.matType != HenckyMatType::HOMOGENEOUS) {
48 MOFEM_LOG("WORLD", Sev::verbose)
49 << "Found non-homogeneous material block: " << block.blockName;
50 break;
51 }
52 }
53 }
54
55 static constexpr int StrideMatD =
57
58 template <int STRIDEMATD = 0> struct OpHenckyJacobian : public OpJacobian {
59 OpHenckyJacobian(boost::shared_ptr<DataAtIntegrationPts> data_ptr,
60 boost::shared_ptr<HMHHencky> hencky_ptr)
61 : OpJacobian(H1, OPLAST), dataAtGaussPts(data_ptr),
62 henckyPtr(hencky_ptr) {
63 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
64 doEntities[MBVERTEX] = true;
65 }
66
67 MoFEMErrorCode doWork(int side, EntityType type,
68 EntitiesFieldData::EntData &data) {
70 CHKERR henckyPtr->computeMaterialParamsAtPts<STRIDEMATD>(this, data,
73 }
74
75 MoFEMErrorCode evaluateRhs(EntData &data) { return 0; }
76 MoFEMErrorCode evaluateLhs(EntData &data) { return 0; }
77
78 private:
79 boost::shared_ptr<DataAtIntegrationPts> dataAtGaussPts;
80 boost::shared_ptr<HMHHencky> henckyPtr;
81 };
82
84 returnOpJacobian(const bool eval_rhs, const bool eval_lhs,
85 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
86 boost::shared_ptr<PhysicalEquations> physics_ptr) override {
87
88 auto hencky_ptr = boost::dynamic_pointer_cast<HMHHencky>(physics_ptr);
89
91 return new OpHenckyJacobian<StrideMatD>(data_ptr, hencky_ptr);
92 return new OpHenckyJacobian<0>(data_ptr, hencky_ptr);
93 }
94
95 template <int STRIDEMATD = 0>
97
98 OpSpatialPhysical(const std::string &field_name,
99 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
100 const double alpha_u);
101
102 MoFEMErrorCode integrate(EntData &data);
103
104 MoFEMErrorCode integrateHencky(EntData &data);
105
106 private:
107 const double alphaU;
108 };
109
112 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
113 const double alpha_u) override {
115 return new OpSpatialPhysical<StrideMatD>(field_name, data_ptr, alpha_u);
116 } else {
117 return new OpSpatialPhysical<0>(field_name, data_ptr, alpha_u);
118 }
119 }
120
123 const std::string &field_name,
124 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
125 boost::shared_ptr<ExternalStrainVec> &external_strain_vec_ptr,
126 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv);
127
128 MoFEMErrorCode integrate(EntData &data);
129
130 private:
131 boost::shared_ptr<ExternalStrainVec> externalStrainVecPtr;
132 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
133 };
134
136 const std::string &field_name,
137 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
138 boost::shared_ptr<ExternalStrainVec> external_strain_vec_ptr,
139 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv) override {
140 return new OpSpatialPhysicalExternalStrain(field_name, data_ptr,
141 external_strain_vec_ptr, smv);
142 }
143
144 template <int STRIDEMATD = 0>
146 const double alphaU;
147 OpSpatialPhysical_du_du(std::string row_field, std::string col_field,
148 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
149 const double alpha);
150 MoFEMErrorCode integrate(EntData &row_data, EntData &col_data);
151 MoFEMErrorCode integrateHencky(EntData &row_data, EntData &col_data);
152
153 private:
154 MatrixDouble dP;
155 };
156
158 std::string row_field, std::string col_field,
159 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
160 const double alpha) override {
161
163 return new OpSpatialPhysical_du_du<StrideMatD>(row_field, col_field,
164 data_ptr, alpha);
165 } else {
166 return new OpSpatialPhysical_du_du<0>(row_field, col_field, data_ptr,
167 alpha);
168 }
169 }
170
171 /**
172 * @brief Calculate energy density for Hencky material model
173 *
174 *
175 * \f[
176 *
177 * \Psi(\log{\mathbf{U}}) = \frac{1}{2} U_{IJ} D_{IJKL} U_{KL} = \frac{1}{2}
178 * U_{IJ} T_{IJ}
179 *
180 * \f]
181 * where \f$T_{IJ} = D_{IJKL} U_{KL}\f$ is a a Hencky stress.
182 *
183 */
184 template <int STRIDEMATD>
186
188 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
189 boost::shared_ptr<double> total_helmholtz_free_energy_ptr);
190 MoFEMErrorCode doWork(int side, EntityType type, EntData &data);
191
192 private:
193 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
194 boost::shared_ptr<double> totalHelmholtzFreeEnergyPtr;
195 };
196
199 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
200 boost::shared_ptr<double> total_helmholtz_free_energy_ptr) override {
201
204 data_ptr, total_helmholtz_free_energy_ptr);
205 } else {
207 data_ptr, total_helmholtz_free_energy_ptr);
208 }
209 }
210
211 bool providesHelmholtzFreeEnergy() const override { return true; }
212
213 template <int STRIDEMATD = 0>
216 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
217 boost::shared_ptr<MatrixDouble> strain_ptr,
218 boost::shared_ptr<MatrixDouble> stress_ptr,
219 boost::shared_ptr<HMHHencky> hencky_ptr);
220 MoFEMErrorCode doWork(int side, EntityType type, EntData &data);
221
222 private:
223 boost::shared_ptr<DataAtIntegrationPts>
224 dataAtPts; ///< data at integration pts
225 boost::shared_ptr<MatrixDouble> strainPtr;
226 boost::shared_ptr<MatrixDouble> stressPtr;
227 boost::shared_ptr<HMHHencky> henckyPtr;
228 };
229
231 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
232 boost::shared_ptr<PhysicalEquations> physics_ptr,
233 boost::shared_ptr<MatrixDouble> strain_ptr) override {
235 std::move(data_ptr), std::move(physics_ptr), std::move(strain_ptr),
236 nullptr, nullptr);
237 }
238
240 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
241 boost::shared_ptr<PhysicalEquations> physics_ptr,
242 boost::shared_ptr<MatrixDouble> strain_ptr,
243 boost::shared_ptr<MatrixDouble> stress_ptr,
244 VectorPtr external_pressure_ptr) override {
245 auto hencky_ptr = boost::dynamic_pointer_cast<HMHHencky>(physics_ptr);
246
249 data_ptr,
250 strain_ptr ? strain_ptr : data_ptr->getLogStretchTensorAtPts(),
251 stress_ptr ? stress_ptr : data_ptr->getApproxPAtPts(), hencky_ptr);
252 } else {
254 data_ptr,
255 strain_ptr ? strain_ptr : data_ptr->getLogStretchTensorAtPts(),
256 stress_ptr ? stress_ptr : data_ptr->getApproxPAtPts(), hencky_ptr);
257 }
258 }
259
261 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
262 boost::shared_ptr<PhysicalEquations> physics_ptr) override {
263 auto hencky_ptr = boost::dynamic_pointer_cast<HMHHencky>(physics_ptr);
264
267 data_ptr, data_ptr->getVarLogStreachPts(), data_ptr->getVarPiolaPts(),
268 hencky_ptr);
269 } else {
271 data_ptr, data_ptr->getVarLogStreachPts(), data_ptr->getVarPiolaPts(),
272 hencky_ptr);
273 }
274 }
275
276 MoFEMErrorCode getOptions() {
278 PetscOptionsBegin(PETSC_COMM_WORLD, "hencky_", "", "none");
279
280 CHKERR PetscOptionsScalar("-young_modulus", "Young modulus", "", E, &E,
281 PETSC_NULLPTR);
282 CHKERR PetscOptionsScalar("-poisson_ratio", "poisson ratio", "", nu, &nu,
283 PETSC_NULLPTR);
284 CHKERR PetscOptionsBool("-effective_neohookean_stiffness",
285 "Use effective Neo-Hookean stiffness", "",
287 &effectiveNehookeanStiffness, PETSC_NULLPTR);
288 CHKERR PetscOptionsScalar("-effective_diagonal_strain",
289 "Diagonal logarithmic strain for effective "
290 "Neo-Hookean stiffness",
292 &effectiveDiagonalStrain, PETSC_NULLPTR);
293
294 PetscOptionsEnd();
295
296 MOFEM_LOG("EP", Sev::inform)
297 << "Hencky: E = " << E << " nu = " << nu
298 << " effective_neohookean_stiffness = "
299 << (effectiveNehookeanStiffness ? "true" : "false")
300 << " effective_diagonal_strain = " << effectiveDiagonalStrain;
301
302 CHKERRG(ierr);
303
305 }
306
307 MoFEMErrorCode extractBlockData(Sev sev) {
308 return extractBlockData(
309
310 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
311
312 (boost::format("(.*)%s(.*)") % "_ELASTIC").str()
313
314 )),
315
316 sev);
317 }
318
319 MoFEMErrorCode
320 extractBlockData(std::vector<const CubitMeshSets *> meshset_vec_ptr,
321 Sev sev) {
323
324 for (auto m : meshset_vec_ptr) {
325 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock") << *m;
326 std::string block_name = m->getName();
327
328 auto block_name_heterogeneous = "(.*)HETEROGENEOUS_ELASTIC(.*)";
329 auto block_name_analytical = "(.*)ANALYTICAL_ELASTIC(.*)";
330 std::regex reg_name_heterogeneous(block_name_heterogeneous);
331 std::regex reg_name_analytical(block_name_analytical);
332 const bool is_heterogeneous =
333 std::regex_match(block_name, reg_name_heterogeneous);
334 const bool is_analytical =
335 std::regex_match(block_name, reg_name_analytical);
336
337 std::vector<double> block_data;
338 CHKERR m->getAttributes(block_data);
339 if (block_data.size() < 2) {
340 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
341 "Expected that block has atleast two attributes");
342 }
343 auto get_block_ents = [&]() {
344 Range ents;
345 CHKERR mField.get_moab().get_entities_by_handle(m->meshset, ents, true);
346 return ents;
347 };
348
349 double young_modulus = block_data[0];
350 double poisson_ratio = block_data[1];
351
353 if (is_heterogeneous) {
355 } else if (is_analytical) {
356 mat_type = HenckyMatType::ANALYTICAL;
357 }
358
360 mat_type == HenckyMatType::HOMOGENEOUS) {
361 const auto effective_params = calc_effective_elastic_params(
363 young_modulus = effective_params.youngModulus;
364 poisson_ratio = effective_params.poissonRatio;
365 }
366
367 double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
368 double shear_modulus_G = young_modulus / (2 * (1 + poisson_ratio));
369
370 MOFEM_TAG_AND_LOG("WORLD", sev, "MatBlock")
371 << "E = " << young_modulus << " nu = " << poisson_ratio;
372
373 blockData.push_back({block_name, young_modulus, poisson_ratio,
374 bulk_modulus_K, shear_modulus_G, get_block_ents(),
375 mat_type});
376 }
377 MOFEM_LOG_CHANNEL("WORLD");
379 }
380
381 template <int STRIDEMATD, typename OP_PTR>
383 OP_PTR op_ptr, EntitiesFieldData::EntData &data,
384 boost::shared_ptr<DataAtIntegrationPts> dataAtGaussPts) {
386
387 auto getMaterialParams = [&](double E, double nu) {
390 }
391
392 const double bulk_modulus_K = E / (3 * (1 - 2 * nu));
393 const double shear_modulus_G = E / (2 * (1 + nu));
394 const double lambda = bulk_modulus_K - 2 * shear_modulus_G / 3;
396 lambda};
397 };
398
399 auto fe_ent = op_ptr->getNumeredEntFiniteElementPtr()->getEnt();
400 int nb_integration_pts = op_ptr->getGaussPts().size2();
401
402 dataAtGaussPts->muAtPts.resize(nb_integration_pts, false);
403 dataAtGaussPts->lambdaAtPts.resize(nb_integration_pts, false);
404 dataAtGaussPts->muAtPts.clear();
405 dataAtGaussPts->lambdaAtPts.clear();
406
407 dataAtGaussPts->youngModulusAtPts.resize(nb_integration_pts, false);
408 dataAtGaussPts->youngModulusAtPts.clear();
409
410 auto t_young_modulus =
411 getFTensor0FromVec(dataAtGaussPts->youngModulusAtPts);
412 auto t_mu = getFTensor0FromVec(dataAtGaussPts->muAtPts);
413 auto t_lambda = getFTensor0FromVec(dataAtGaussPts->lambdaAtPts);
414
415 MatrixSizeHelper<
416 GetFTensor4DdgFromMatType<SPACE_DIM, SPACE_DIM, STRIDEMATD, DL>,
417 DL>::size(dataAtGaussPts->matD, nb_integration_pts);
418 MatrixSizeHelper<
419 GetFTensor4DdgFromMatType<SPACE_DIM, SPACE_DIM, STRIDEMATD, DL>,
420 DL>::size(dataAtGaussPts->matAxiatorD, nb_integration_pts);
421 MatrixSizeHelper<
422 GetFTensor4DdgFromMatType<SPACE_DIM, SPACE_DIM, STRIDEMATD, DL>,
423 DL>::size(dataAtGaussPts->matDeviatorD, nb_integration_pts);
424 MatrixSizeHelper<
425 GetFTensor4DdgFromMatType<SPACE_DIM, SPACE_DIM, STRIDEMATD, DL>,
426 DL>::size(dataAtGaussPts->matInvD, nb_integration_pts);
427
428 dataAtGaussPts->matD.clear();
429 dataAtGaussPts->matAxiatorD.clear();
430 dataAtGaussPts->matDeviatorD.clear();
431 dataAtGaussPts->matInvD.clear();
432
438
439 auto t_D = getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, STRIDEMATD>(
440 dataAtGaussPts->matD);
441 auto t_axiator_D = getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, STRIDEMATD>(
442 dataAtGaussPts->matAxiatorD);
443 auto t_deviator_D = getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, STRIDEMATD>(
444 dataAtGaussPts->matDeviatorD);
445 auto t_inv_D = getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, STRIDEMATD>(
446 dataAtGaussPts->matInvD);
447
448 auto next = [&]() {
449 ++t_young_modulus;
450 ++t_mu;
451 ++t_lambda;
452 ++t_D;
453 ++t_axiator_D;
454 ++t_deviator_D;
455 ++t_inv_D;
456 };
457
458 auto evalMatD = [&](double bulk_modulus_K, double shear_modulus_G) {
460 t_axiator_D(i, j, k, l) = (bulk_modulus_K - (2. / 3.) * shear_modulus_G) *
461 t_kd(i, j) * t_kd(k, l);
462 t_deviator_D(i, j, k, l) =
463 2 * shear_modulus_G * ((t_kd(i, k) ^ t_kd(j, l)) / 4.);
464 t_D(i, j, k, l) = t_axiator_D(i, j, k, l) + t_deviator_D(i, j, k, l);
466 };
467
468 auto evalInvMatDPtr = [&](double bulk_modulus_K, double shear_modulus_G) {
470 const double A = 1. / (2. * shear_modulus_G);
471 const double B =
472 (1. / (9. * bulk_modulus_K)) - (1. / (6. * shear_modulus_G));
473 t_inv_D(i, j, k, l) =
474 A * ((t_kd(i, k) ^ t_kd(j, l)) / 4.) + B * t_kd(i, j) * t_kd(k, l);
476 };
477
478 // from block data (MAT_ELASTIC) or (ANALYTICAL_ELASTIC) if provided,
479 // otherwise from command line options
480 for (auto &b : this->blockData) {
481 if (b.blockEnts.find(op_ptr->getFEEntityHandle()) != b.blockEnts.end()) {
482
483 if (b.matType == HMHHencky::HenckyMatType::ANALYTICAL) {
484 VectorDouble analytical_elastic;
485 analytical_elastic = getAnalyticalElastic(op_ptr, b.blockName);
486
487 auto t_analytical_elastic = getFTensor0FromVec(analytical_elastic);
488
489 for (int gg = 0; gg != nb_integration_pts; ++gg) {
490 const auto material_params =
491 getMaterialParams(t_analytical_elastic, b.poissonRatio);
492 t_young_modulus = material_params.youngModulus;
493 t_mu = material_params.shearModulusG;
494 t_lambda = material_params.lambda;
495
496 CHKERR evalMatD(material_params.bulkModulusK,
497 material_params.shearModulusG);
498 CHKERR evalInvMatDPtr(material_params.bulkModulusK,
499 material_params.shearModulusG);
500 ++t_analytical_elastic;
501 next();
502 }
503
504 } else if (b.matType == HMHHencky::HenckyMatType::HETEROGENEOUS) {
505 Tag tag_heterogenous_mat;
506 CHKERR op_ptr->getPtrFE()->mField.get_moab().tag_get_handle(
508 tag_heterogenous_mat);
509 int tag_length;
510 CHKERR op_ptr->getPtrFE()->mField.get_moab().tag_get_length(
511 tag_heterogenous_mat, tag_length);
512 if (tag_length != 1) {
513 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
514 "heterogeneous Young's modulus tag should be 1 but is %d",
515 tag_length);
516 }
518 // Constant interpolation (element-wise)
519 double elem_young_mod = 0.0;
520 CHKERR op_ptr->getPtrFE()->mField.get_moab().tag_get_data(
521 tag_heterogenous_mat, &fe_ent, 1, &elem_young_mod);
522
523 for (int gg = 0; gg != nb_integration_pts; ++gg) {
524 const auto material_params =
525 getMaterialParams(elem_young_mod, b.poissonRatio);
526 t_young_modulus = material_params.youngModulus;
527 t_mu = material_params.shearModulusG;
528 t_lambda = material_params.lambda;
529
530 CHKERR evalMatD(material_params.bulkModulusK,
531 material_params.shearModulusG);
532 CHKERR evalInvMatDPtr(material_params.bulkModulusK,
533 material_params.shearModulusG);
534 next();
535 }
537 // Linear interpolation (vertex-based)
538 const EntityHandle *vert_conn;
539 int vert_num;
540 CHKERR op_ptr->getPtrFE()->mField.get_moab().get_connectivity(
541 fe_ent, vert_conn, vert_num, true);
542
543 VectorDouble vert_young_mod(vert_num);
544 CHKERR op_ptr->getPtrFE()->mField.get_moab().tag_get_data(
545 tag_heterogenous_mat, vert_conn, vert_num, &vert_young_mod[0]);
546
547 auto t_shape_n = data.getFTensor0N();
548 int nb_shape_fn = data.getN(NOBASE).size2();
549
550 for (int gg = 0; gg != nb_integration_pts; ++gg) {
551 t_young_modulus = 0; // Initialize to zero before accumulation
552 auto t_vert_young_mod = getFTensor0FromVec(vert_young_mod);
553 for (int bb = 0; bb != nb_shape_fn; ++bb) {
554 t_young_modulus += t_vert_young_mod * t_shape_n;
555 ++t_vert_young_mod;
556 ++t_shape_n;
557 }
558 const auto material_params =
559 getMaterialParams(t_young_modulus, b.poissonRatio);
560 t_young_modulus = material_params.youngModulus;
561 t_mu = material_params.shearModulusG;
562 t_lambda = material_params.lambda;
563
564 CHKERR evalMatD(material_params.bulkModulusK,
565 material_params.shearModulusG);
566 CHKERR evalInvMatDPtr(material_params.bulkModulusK,
567 material_params.shearModulusG);
568 next();
569 }
570 } else {
571 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
572 "Unsupported heterogeneous Young's modulus interpolation "
573 "order %d",
575 }
576 } else {
577 // MAT_ELASTIC block with homogeneous material properties
578 for (int gg = 0; gg != nb_integration_pts; ++gg) {
579 t_young_modulus = b.youngModulus;
580 t_mu = b.shearModulusG;
581 t_lambda = b.bulkModulusK - 2 * b.shearModulusG / 3;
582
583 CHKERR evalMatD(b.bulkModulusK, b.shearModulusG);
584 CHKERR evalInvMatDPtr(b.bulkModulusK, b.shearModulusG);
585 next();
586 }
587 }
589 }
590 }
591
592 // From command line options if no block data is provided
593 const auto material_params = getMaterialParams(this->E, this->nu);
594
595 for (int gg = 0; gg != nb_integration_pts; ++gg) {
596 t_young_modulus = material_params.youngModulus;
597 t_mu = material_params.shearModulusG;
598 t_lambda = material_params.lambda;
599 CHKERR evalMatD(material_params.bulkModulusK,
600 material_params.shearModulusG);
601 CHKERR evalInvMatDPtr(material_params.bulkModulusK,
602 material_params.shearModulusG);
603 next();
604 }
605
607 }
608
610
611 OpTopoSpatialPhysical(const std::string &field_name,
612 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
613 SmartPetscObj<Vec> assemble_vec,
614 boost::shared_ptr<TopologicalData> topo_ptr,
615 const double alpha_u,
616 boost::shared_ptr<double> J_ptr);
617
618 MoFEMErrorCode integrate(EntData &data) override;
619
620 MoFEMErrorCode integrateHencky(EntData &data);
621
622 MoFEMErrorCode assemble(int row_side, EntityType row_type,
623 EntData &data) override;
624
625 private:
626 const double alphaU;
627 boost::shared_ptr<TopologicalData> topoDataPtr;
628 SmartPetscObj<Vec> assembleVec;
629 boost::shared_ptr<double> JPtr;
630 double locJ;
631 };
632
633 virtual VolUserDataOperator *
635 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
636 SmartPetscObj<Vec> assemble_vec,
637 boost::shared_ptr<TopologicalData> topo_ptr,
638 const double alpha_u,
639 boost::shared_ptr<double> J_ptr) override {
640 return new OpTopoSpatialPhysical(field_name, data_ptr, assemble_vec,
641 topo_ptr, alpha_u, J_ptr);
642 }
643
644private:
646
657 std::vector<BlockData> blockData;
658
659 double E;
660 double nu;
661 PetscBool effectiveNehookeanStiffness = PETSC_FALSE;
663
664 // Set verbosity level, it verbile can changes that informatno is pronated
665 // only once at particular level
666};
667
668template <int STRIDEMATD>
670 const std::string &field_name,
671 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const double alpha_u)
672 : OpAssembleVolume(field_name, data_ptr, OPROW), alphaU(alpha_u) {}
673
674template <int STRIDEMATD>
675MoFEMErrorCode
681
682template <int STRIDEMATD>
683MoFEMErrorCode
686
688 auto t_L = FTensor::SymmLTensor<double, 3>();
689
690 int nb_dofs = data.getIndices().size();
691 int nb_integration_pts = data.getN().size1();
692 auto v = getVolume();
693 auto t_w = getFTensor0IntegrationWeight();
694 auto t_approx_P_adjoint_log_du =
695 dataAtPts->getFTensorAdjointPdU(nb_integration_pts);
696 auto t_log_stretch_h1 =
697 dataAtPts->getFTensorLogStretchTotal(nb_integration_pts);
698 auto t_dot_log_u = dataAtPts->getFTensorLogStretchDot(nb_integration_pts);
699 auto t_plasticF = dataAtPts->getFTensorPlasticF(nb_integration_pts);
700
701 auto t_D = getFTensor4DdgFromMat<3, 3, STRIDEMATD>(dataAtPts->matD);
702
703 FTensor::Index<'i', 3> i;
704 FTensor::Index<'j', 3> j;
705 FTensor::Index<'k', 3> k;
706 FTensor::Index<'l', 3> l;
707 auto get_ftensor2 = [](auto &v) {
709 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
710 };
711
712 int nb_base_functions = data.getN().size2();
713 auto t_row_base_fun = data.getFTensor0N();
714
715 for (int gg = 0; gg != nb_integration_pts; ++gg) {
716 const double det_plasticF = determinantTensor3by3(t_plasticF);
717 const double a = v * t_w * det_plasticF;
718 auto t_nf = get_ftensor2(nF);
719
721 t_T(i, j) =
722 t_D(i, j, k, l) * (t_log_stretch_h1(k, l) + alphaU * t_dot_log_u(k, l));
724 t_residual(L) =
725 a * (t_approx_P_adjoint_log_du(L) - t_L(i, j, L) * t_T(i, j));
726
727 int bb = 0;
728 for (; bb != nb_dofs / 6; ++bb) {
729 t_nf(L) -= t_row_base_fun * t_residual(L);
730 ++t_nf;
731 ++t_row_base_fun;
732 }
733 for (; bb != nb_base_functions; ++bb)
734 ++t_row_base_fun;
735
736 ++t_D;
737 ++t_w;
738 ++t_approx_P_adjoint_log_du;
739 ++t_dot_log_u;
740 ++t_log_stretch_h1;
741 ++t_plasticF;
742 }
743
745}
746
747template <int STRIDEMATD>
749 std::string row_field, std::string col_field,
750 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const double alpha)
751 : OpAssembleVolume(row_field, col_field, data_ptr, OPROWCOL, false),
752 alphaU(alpha) {
753 sYmm = false;
754}
755
757 const std::string &field_name,
758 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
759 boost::shared_ptr<ExternalStrainVec> &external_strain_vec_ptr,
760 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv)
761 : OpAssembleVolume(field_name, data_ptr, OPROW),
762 externalStrainVecPtr(external_strain_vec_ptr), scalingMethodsMap(smv) {}
763
764MoFEMErrorCode
767
769
770 double time = OpAssembleVolume::getFEMethod()->ts_t;
773 }
774 // get entity of tet
775 EntityHandle fe_ent = OpAssembleVolume::getFEEntityHandle();
776 // iterate over all block data
777
778 for (auto &ext_strain_block : (*externalStrainVecPtr)) {
779 // check if finite element entity is part of the EXTERNALSTRAIN block
780 if (ext_strain_block.ents.find(fe_ent) != ext_strain_block.ents.end()) {
781
782 double scale = 1;
783 if (scalingMethodsMap.find(ext_strain_block.blockName) !=
784 scalingMethodsMap.end()) {
785 scale *=
786 scalingMethodsMap.at(ext_strain_block.blockName)->getScale(time);
787 } else {
788 MOFEM_LOG("SELF", Sev::warning)
789 << "No scaling method found for " << ext_strain_block.blockName;
790 }
791
792 int nb_dofs = data.getIndices().size();
793 int nb_integration_pts = data.getN().size1();
794 auto v = getVolume();
795 auto t_w = getFTensor0IntegrationWeight();
796 auto t_plasticF = dataAtPts->getFTensorPlasticF(nb_integration_pts);
798
799 double external_strain_val;
800 VectorDouble v_external_strain;
801 auto block_name = "(.*)ANALYTICAL_EXTERNALSTRAIN(.*)";
802 std::regex reg_name(block_name);
803 if (std::regex_match(ext_strain_block.blockName, reg_name)) {
804 VectorDouble analytical_external_strain;
805 std::string block_name_tmp;
806 std::tie(block_name_tmp, v_external_strain) =
807 getAnalyticalExternalStrain(this, analytical_external_strain,
808 ext_strain_block.blockName);
809 } else {
810 // get ExternalStrain data from block
811 external_strain_val = scale * ext_strain_block.val;
812 // fill with same scalar value for all integration points
813 v_external_strain.resize(nb_integration_pts);
814 std::fill(v_external_strain.begin(), v_external_strain.end(),
815 external_strain_val);
816 }
817 auto t_external_strain = getFTensor0FromVec(v_external_strain);
818 double bulk_modulus_K = ext_strain_block.bulkModulusK;
819 auto t_L = FTensor::SymmLTensor<double, 3>();
820
821 FTensor::Index<'i', 3> i;
822 FTensor::Index<'j', 3> j;
823 FTensor::Index<'k', 3> k;
824 FTensor::Index<'l', 3> l;
825 auto get_ftensor2 = [](auto &v) {
827 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
828 };
829
830 int nb_base_functions = data.getN().size2();
831 auto t_row_base_fun = data.getFTensor0N();
832 for (int gg = 0; gg != nb_integration_pts; ++gg) {
833 auto tr = 3.0 * t_external_strain;
834 const double det_plasticF = determinantTensor3by3(t_plasticF);
835 const double a = v * t_w * det_plasticF;
836 auto t_nf = get_ftensor2(nF);
837
839
840 t_T(i, j) = -bulk_modulus_K * tr * t_kd(i, j);
841
843 t_residual(L) = a * (t_L(i, j, L) * t_T(i, j));
844
845 int bb = 0;
846 for (; bb != nb_dofs / 6; ++bb) {
847 t_nf(L) += t_row_base_fun * t_residual(L);
848 ++t_nf;
849 ++t_row_base_fun;
850 }
851 for (; bb != nb_base_functions; ++bb)
852 ++t_row_base_fun;
853 ++t_external_strain;
854 ++t_w;
855 ++t_plasticF;
856 }
857 }
858 }
859
861}
862
863template <int STRIDEMATD>
864MoFEMErrorCode
866 EntData &col_data) {
868 CHKERR integrateHencky(row_data, col_data);
870}
871
872template <int STRIDEMATD>
874 EntData &row_data, EntData &col_data) {
876
879 auto t_L = FTensor::SymmLTensor<double, 3>();
880 auto t_diff = FTensor::DiffTensor<double>();
881
882 int nb_integration_pts = row_data.getN().size1();
883 int row_nb_dofs = row_data.getIndices().size();
884 int col_nb_dofs = col_data.getIndices().size();
885
886 auto get_ftensor2 = [](MatrixDouble &m, const int r, const int c) {
888 size_symm>(
889
890 &m(r + 0, c + 0), &m(r + 0, c + 1), &m(r + 0, c + 2), &m(r + 0, c + 3),
891 &m(r + 0, c + 4), &m(r + 0, c + 5),
892
893 &m(r + 1, c + 0), &m(r + 1, c + 1), &m(r + 1, c + 2), &m(r + 1, c + 3),
894 &m(r + 1, c + 4), &m(r + 1, c + 5),
895
896 &m(r + 2, c + 0), &m(r + 2, c + 1), &m(r + 2, c + 2), &m(r + 2, c + 3),
897 &m(r + 2, c + 4), &m(r + 2, c + 5),
898
899 &m(r + 3, c + 0), &m(r + 3, c + 1), &m(r + 3, c + 2), &m(r + 3, c + 3),
900 &m(r + 3, c + 4), &m(r + 3, c + 5),
901
902 &m(r + 4, c + 0), &m(r + 4, c + 1), &m(r + 4, c + 2), &m(r + 4, c + 3),
903 &m(r + 4, c + 4), &m(r + 4, c + 5),
904
905 &m(r + 5, c + 0), &m(r + 5, c + 1), &m(r + 5, c + 2), &m(r + 5, c + 3),
906 &m(r + 5, c + 4), &m(r + 5, c + 5)
907
908 );
909 };
910
911 FTENSOR_INDEXES(SPACE_DIM, i, j, k, l, m, n);
912
913 auto v = getVolume();
914 auto t_w = getFTensor0IntegrationWeight();
915
916 int row_nb_base_functions = row_data.getN().size2();
917 auto t_row_base_fun = row_data.getFTensor0N();
918
919 auto get_dP = [&]() {
920 auto get_stress =
921 MatrixSizeHelper<GetFTensor2FromMatType<size_symm, size_symm, -1, DL>,
922 DL>::size(dP, nb_integration_pts);
923 auto ts_a = getTSa();
924
925 auto t_D = getFTensor4DdgFromMat<3, 3, STRIDEMATD>(dataAtPts->matD);
927 if constexpr (!STRIDEMATD) {
928 t_dP_tmp(L, J) = -(1 + alphaU * ts_a) *
929 (t_L(i, j, L) * ((t_D(i, j, m, n) * t_diff(m, n, k, l)) *
930 t_L(k, l, J)));
931 }
932 // allocate FTensors
934 L_left(i, j, L) = t_L(i, j, L);
936 L_right(k, l, J) = t_L(k, l, J);
938
941 auto t_approx_P_adjoint__dstretch =
942 dataAtPts->getFTensorAdjointPdstretch(nb_integration_pts);
943 auto t_eigen_vals = dataAtPts->getFTensorEigenVals(nb_integration_pts);
944 auto t_eigen_vecs = dataAtPts->getFTensorEigenVecs(nb_integration_pts);
945 auto &nbUniq = dataAtPts->nbUniq;
946
947 auto t_dP = get_stress();
948 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
949 if constexpr (STRIDEMATD) {
950 temp(i, j, k, l) = t_D(i, j, m, n) * t_diff(m, n, k, l);
951
952 t_dP_tmp(L, J) =
953 -(1 + alphaU * ts_a) *
954 (L_left(i, j, L) * (temp(i, j, k, l) * L_right(k, l, J)));
955
956 ++t_D;
957 }
958
959 // Work of symmetric tensor on undefined tensor is equal to the work
960 // of the symmetric part of it
962 t_sym(i, j) = (t_approx_P_adjoint__dstretch(i, j) ||
963 t_approx_P_adjoint__dstretch(j, i));
964 t_sym(i, j) /= 2.0;
965 auto t_diff2_uP2 = EigenMatrix::getDiffDiffMat(
966 t_eigen_vals, t_eigen_vecs, EshelbianCore::f, EshelbianCore::d_f,
967 EshelbianCore::dd_f, t_sym, nbUniq[gg]);
968 t_dP(L, J) = t_L(i, j, L) *
969 ((t_diff2_uP2(i, j, k, l) + t_diff2_uP2(k, l, i, j)) *
970 t_L(k, l, J)) /
971 2. +
972 t_dP_tmp(L, J);
973
974 ++t_dP;
975 ++t_approx_P_adjoint__dstretch;
976 ++t_eigen_vals;
977 ++t_eigen_vecs;
978 }
979 } else {
980 auto t_dP = get_stress();
981 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
982 if constexpr (STRIDEMATD) {
983 temp(i, j, k, l) = t_D(i, j, m, n) * t_diff(m, n, k, l);
984
985 t_dP_tmp(L, J) =
986 -(1 + alphaU * ts_a) *
987 (L_left(i, j, L) * (temp(i, j, k, l) * L_right(k, l, J)));
988
989 ++t_D;
990 }
991 t_dP(L, J) = t_dP_tmp(L, J);
992
993 ++t_dP;
994 }
995 }
996
997 return get_stress();
998 };
999
1000 auto t_dP = get_dP();
1001 auto t_plasticF = dataAtPts->getFTensorPlasticF(nb_integration_pts);
1002
1003 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1004 const double det_plasticF = determinantTensor3by3(t_plasticF);
1005 const double a = v * t_w * det_plasticF;
1006
1007 int rr = 0;
1008 for (; rr != row_nb_dofs / 6; ++rr) {
1009 auto t_col_base_fun = col_data.getFTensor0N(gg, 0);
1010 auto t_m = get_ftensor2(K, 6 * rr, 0);
1011 for (int cc = 0; cc != col_nb_dofs / 6; ++cc) {
1012 const double b = a * t_row_base_fun * t_col_base_fun;
1013 t_m(L, J) -= b * t_dP(L, J);
1014 ++t_m;
1015 ++t_col_base_fun;
1016 }
1017 ++t_row_base_fun;
1018 }
1019
1020 for (; rr != row_nb_base_functions; ++rr) {
1021 ++t_row_base_fun;
1022 }
1023
1024 ++t_w;
1025 ++t_dP;
1026 ++t_plasticF;
1027 }
1029}
1030
1031template <int STRIDEMATD>
1033 STRIDEMATD>::OpCalculateHelmholtzFreeEnergy(
1034 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1035 boost::shared_ptr<double> total_helmholtz_free_energy_ptr)
1036 : VolUserDataOperator(NOSPACE, OPSPACE), dataAtPts(data_ptr),
1037 totalHelmholtzFreeEnergyPtr(total_helmholtz_free_energy_ptr) {
1038
1039 if (!dataAtPts) {
1041 "dataAtPts is not allocated. Please set it before "
1042 "using this operator.");
1043 }
1044}
1045
1046template <int STRIDEMATD>
1047MoFEMErrorCode
1049 int side, EntityType type, EntData &data) {
1051
1056
1057 int nb_integration_pts = getGaussPts().size2();
1058 auto t_log_u = dataAtPts->getFTensorLogStretchTotal(nb_integration_pts);
1059
1060#ifndef NDEBUG
1061 auto &mat_d = dataAtPts->matD;
1062 if (mat_d.size2() != size_symm * size_symm) {
1063 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1064 "wrong matD size, number of columns should be %d but is %zu",
1065 size_symm * size_symm, mat_d.size2());
1066 }
1067 if constexpr (STRIDEMATD != 0) {
1068 if (mat_d.size1() != nb_integration_pts) {
1069 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1070 "wrong matD size, number of rows should be %d but is %zu",
1071 nb_integration_pts, mat_d.size1());
1072 }
1073 }
1074#endif
1075
1076 auto t_D = getFTensor4DdgFromMat<3, 3, STRIDEMATD>(dataAtPts->matD);
1077
1078 dataAtPts->energyAtPts.resize(nb_integration_pts, false);
1079 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
1080
1081 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
1082
1083 t_energy = 0.5 * (t_log_u(i, j) * (t_D(i, j, k, l) * t_log_u(k, l)));
1084
1085 ++t_D;
1086 ++t_log_u;
1087 ++t_energy;
1088 }
1089
1090 if (totalHelmholtzFreeEnergyPtr) {
1091 auto t_w = getFTensor0IntegrationWeight();
1092 auto t_energy = getFTensor0FromVec(dataAtPts->energyAtPts);
1093 double loc_energy = 0;
1094 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
1095 loc_energy += t_energy * t_w;
1096 ++t_w;
1097 ++t_energy;
1098 }
1099 *totalHelmholtzFreeEnergyPtr += getMeasure() * loc_energy;
1100 }
1101
1103}
1104
1105template <int STRIDEMATD>
1108 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1109 boost::shared_ptr<MatrixDouble> strain_ptr,
1110 boost::shared_ptr<MatrixDouble> stress_ptr,
1111 boost::shared_ptr<HMHHencky> hencky_ptr)
1112 : VolUserDataOperator(H1, OPLAST), dataAtPts(data_ptr),
1113 strainPtr(strain_ptr), stressPtr(stress_ptr), henckyPtr(hencky_ptr) {
1114 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
1115 doEntities[MBVERTEX] = true;
1116}
1117
1118template <int STRIDEMATD>
1120 int side, EntityType type, EntData &data) {
1122
1129
1130 auto nb_integration_pts = stressPtr->size1();
1131#ifndef NDEBUG
1132 if (nb_integration_pts != getGaussPts().size2()) {
1133 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1134 "inconsistent number of integration points");
1135 }
1136#endif // NDEBUG
1137
1138 CHKERR henckyPtr->computeMaterialParamsAtPts<STRIDEMATD>(this, data,
1139 dataAtPts);
1140
1141 auto get_strain =
1142 MatrixSizeHelper<GetFTensor2SymmetricFromMatType<3, -1, DL>, DL>::size(
1143 *strainPtr, nb_integration_pts);
1144 auto t_strain = get_strain();
1145 auto t_stress = getFTensor2FromMat<SPACE_DIM, SPACE_DIM, -1, DL>(*stressPtr);
1146 auto t_inv_D = getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, STRIDEMATD>(
1147 dataAtPts->matInvD);
1148#ifndef NDEBUG
1149 auto t_D =
1150 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, STRIDEMATD>(dataAtPts->matD);
1151#endif
1152
1153 // note: add rotation, so we can extract rigid body motion, work then with
1154 // symmetric part.
1155 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
1156 t_strain(i, j) = t_inv_D(i, j, k, l) * t_stress(k, l);
1157
1158#ifndef NDEBUG
1159 FTensor::Tensor2_symmetric<double, 3> t_stress_symm_debug;
1160 t_stress_symm_debug(i, j) = (t_stress(i, j) || t_stress(j, i)) / 2;
1161 FTensor::Tensor2_symmetric<double, 3> t_stress_symm_debug_diff;
1162 t_stress_symm_debug_diff(i, j) =
1163 t_D(i, j, k, l) * t_strain(k, l) - t_stress_symm_debug(i, j);
1164 double nrm =
1165 t_stress_symm_debug_diff(i, j) * t_stress_symm_debug_diff(i, j);
1166 double nrm0 = t_stress_symm_debug(i, j) * t_stress_symm_debug(i, j) +
1167 std::numeric_limits<double>::epsilon();
1168 constexpr double eps = 1e-10;
1169 if (std::fabs(std::sqrt(nrm / nrm0)) > eps) {
1170 MOFEM_LOG("SELF", Sev::error)
1171 << "Stress symmetry check failed: " << std::endl
1172 << t_stress_symm_debug_diff << std::endl
1173 << t_stress;
1175 "Norm is too big: " + std::to_string(nrm / nrm0));
1176 }
1177 ++t_D;
1178#endif
1179
1180 ++t_strain;
1181 ++t_stress;
1182 ++t_inv_D;
1183 }
1184
1186}
1187
1188template <typename OP_PTR>
1189std::tuple<std::string, VectorDouble>
1191 const std::string block_name) {
1192
1193 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
1194
1195 auto ts_time = op_ptr->getTStime();
1196 auto ts_time_step = op_ptr->getTStimeStep();
1199 ts_time_step = EshelbianCore::physicalDt;
1200 }
1201
1202 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
1203
1204 auto v_analytical_expr = analytical_externalstrain_function(
1205 ts_time_step, ts_time, nb_gauss_pts, m_ref_coords, block_name);
1206
1207#ifndef NDEBUG
1208 if (v_analytical_expr.size() != nb_gauss_pts)
1210 "Wrong number of integration pts");
1211#endif // NDEBUG
1212
1213 return std::make_tuple(block_name, v_analytical_expr);
1214};
1215
1216template <typename OP_PTR>
1217VectorDouble getAnalyticalElastic(OP_PTR op_ptr, const std::string block_name) {
1218
1219 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
1220
1221 auto ts_time = op_ptr->getTStime();
1222 auto ts_time_step = op_ptr->getTStimeStep();
1223
1226 ts_time_step = EshelbianCore::physicalStepNumber;
1227 }
1228
1229 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
1230
1231 auto v_analytical_expr = analytical_elastic_function(
1232 ts_time_step, ts_time, nb_gauss_pts, m_ref_coords, block_name);
1233
1234#ifndef NDEBUG
1235 if (v_analytical_expr.size() != nb_gauss_pts)
1237 "Wrong number of integration pts");
1238#endif // NDEBUG
1239
1240 return v_analytical_expr;
1241}
1242
1243// Topo
1244
1246 const std::string &field_name,
1247 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1248 SmartPetscObj<Vec> assemble_vec,
1249 boost::shared_ptr<TopologicalData> topo_ptr, const double alpha_u,
1250 boost::shared_ptr<double> J_ptr)
1251 : OpAssembleVolume(field_name, data_ptr, OPROW), alphaU(alpha_u),
1252 JPtr(J_ptr), topoDataPtr(topo_ptr), assembleVec(assemble_vec) {}
1253
1256 CHKERR integrateHencky(data);
1258}
1259
1260MoFEMErrorCode
1263
1264 FTensor::Index<'L', size_symm> L;
1265 auto t_L = FTensor::SymmLTensor<double, 3>();
1266
1267 int nb_dofs = data.getIndices().size();
1268 int nb_integration_pts = data.getN().size1();
1269 auto v = getVolume();
1270
1271 FTENSOR_INDEXES(SPACE_DIM, i, j, k, l, I, J);
1272
1273 auto get_ftensor1 = [](auto &v) {
1275 &v[0], &v[1], &v[2]);
1276 };
1277
1278 locJ = 0;
1279 int nb_base_functions = data.getN().size2();
1280
1281 auto integrate = [&](auto t_D) {
1283
1284 auto t_w = getFTensor0IntegrationWeight();
1285 auto t_det = topoDataPtr->getFTensorDetJacobian(nb_integration_pts);
1286 auto t_inv_jac = topoDataPtr->getFTensorInvJacobian(nb_integration_pts);
1287
1288 auto t_var_log_u = dataAtPts->getFTensorVarLogStreach(nb_integration_pts);
1289 auto t_approx_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
1290 auto t_approx_P_adjoint_log_du =
1291 dataAtPts->getFTensorAdjointPdU(nb_integration_pts);
1292 auto t_h_dlog_u =
1293 dataAtPts->getFTensorSmallHdLogStretch(nb_integration_pts);
1294 auto t_log_stretch_h1 =
1295 dataAtPts->getFTensorLogStretchTotal(nb_integration_pts);
1296
1297 // Swithc off rate effects for now, as we don't have the dot_log_u at the
1298 // pts; we would need to compute it from the solution, which is not
1299 // straightforward
1300 // auto t_dot_log_u =
1301 // dataAtPts->getFTensorLogStretchDot(nb_integration_pts);
1302
1303 auto t_diff_base = data.getFTensor1DiffN<SPACE_DIM>();
1304 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1305 const double a = v * t_w;
1306
1308 t_T(i, j) = t_D(i, j, k, l) *
1309 (t_log_stretch_h1(k, l) /*+ alphaU * t_dot_log_u(k, l)*/);
1310
1311 FTensor::Tensor1<double, size_symm> t_stress_residual;
1312 t_stress_residual(L) = t_L(i, j, L) * t_T(i, j);
1313
1315 t_residual(L) = t_approx_P_adjoint_log_du(L) - t_stress_residual(L);
1316
1317 locJ -= (a * t_det) * t_residual(L) * t_var_log_u(L);
1318
1320 t_cof(I, J) = t_det * t_inv_jac(J, I);
1321
1322 const double var_stress_residual = t_var_log_u(L) * t_stress_residual(L);
1323
1324 // detJ cancels the 1 / detJ from the Piola transform; the remaining
1325 // derivative is from J(k, n) * P(i, n).
1327 t_approx_P_adjoint_log_du_dX;
1328 t_approx_P_adjoint_log_du_dX(L, I, J) =
1329 t_h_dlog_u(i, I, L) * t_approx_P(i, J);
1330
1332 t_residual_dX(I, J) =
1333 t_var_log_u(L) * t_approx_P_adjoint_log_du_dX(L, I, J) -
1334 var_stress_residual * t_cof(I, J);
1335
1336 auto t_nf = get_ftensor1(nF);
1337 int bb = 0;
1338 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1339 t_nf(i) -= a * t_residual_dX(i, j) * t_diff_base(j);
1340 ++t_nf;
1341 ++t_diff_base;
1342 }
1343 for (; bb != nb_base_functions; ++bb)
1344 ++t_diff_base;
1345
1346 ++t_w;
1347 ++t_det;
1348 ++t_inv_jac;
1349 ++t_var_log_u;
1350 ++t_approx_P;
1351 ++t_approx_P_adjoint_log_du;
1352 ++t_h_dlog_u;
1353 ++t_log_stretch_h1;
1354 // ++t_dot_log_u;
1355 ++t_D;
1356 }
1358 };
1359
1360 if (!dataAtPts->physicsPtr->getFeatures().test(
1362 CHKERR integrate(
1363 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matD));
1364 } else {
1365 CHKERR integrate(
1366 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matD));
1367 }
1368
1370}
1371
1373 EntityType row_type,
1374 EntData &data) {
1376 if (assembleVec) {
1377 double *vec_ptr = nF.data().data();
1378 const int nb_dofs = data.getIndices().size();
1379 int *ind_ptr = data.getIndices().data().data();
1380 CHKERR VecSetValues(assembleVec, nb_dofs, ind_ptr, vec_ptr, ADD_VALUES);
1381 }
1382 if (row_type == MBVERTEX) {
1383 if (JPtr) {
1384 *JPtr += locJ;
1385 }
1386 }
1388}
1389
1390} // namespace EshelbianPlasticity
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
const double alphaU
std::string type
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
#define FTENSOR_INDEXES(DIM,...)
#define FTENSOR_INDEX(DIM, I)
constexpr double a
static PetscErrorCode ierr
static const double eps
constexpr int SPACE_DIM
Kronecker Delta class symmetric.
@ NOBASE
Definition definitions.h:59
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ H1
continuous field
Definition definitions.h:85
@ 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.
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
double bulk_modulus_K
double shear_modulus_G
const char features[]
constexpr auto t_kd
#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.
VectorDouble analytical_externalstrain_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, const std::string block_name)
std::tuple< std::string, VectorDouble > getAnalyticalExternalStrain(OP_PTR op_ptr, VectorDouble &analytical_expr, const std::string block_name)
static auto calc_effective_elastic_params(double E, double nu, double diagonal_strain)
Definition HMHHencky.cpp:20
VectorDouble analytical_elastic_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, const std::string block_name)
EntitiesFieldData::EntData EntData
VectorDouble getAnalyticalElastic(OP_PTR op_ptr, const std::string block_name)
static constexpr auto size_symm
boost::shared_ptr< VectorDouble > VectorPtr
constexpr IntegrationType I
constexpr AssemblyType A
constexpr auto field_name
FTensor::Index< 'm', 3 > m
void temp(int x, int y=10)
Definition simple.cpp:4
static enum StretchSelector stretchSelector
static enum RotSelector gradApproximator
static double physicalDt
static std::string heterogeneousYoungModTagName
static int physicalStepNumber
static PetscBool physicalTimeFlg
static double currentPhysicalTime
static boost::function< double(const double)> f
static boost::function< double(const double)> dd_f
static boost::function< double(const double)> d_f
static int meshTransferInterpOrder
Calculate energy density for Hencky material model.
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
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)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode evaluateLhs(EntData &data)
Definition HMHHencky.cpp:76
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Definition HMHHencky.cpp:67
boost::shared_ptr< DataAtIntegrationPts > dataAtGaussPts
Definition HMHHencky.cpp:79
OpHenckyJacobian(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< HMHHencky > hencky_ptr)
Definition HMHHencky.cpp:59
MoFEMErrorCode evaluateRhs(EntData &data)
Definition HMHHencky.cpp:75
boost::shared_ptr< HMHHencky > henckyPtr
Definition HMHHencky.cpp:80
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
boost::shared_ptr< ExternalStrainVec > externalStrainVecPtr
OpSpatialPhysicalExternalStrain(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< ExternalStrainVec > &external_strain_vec_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv)
MoFEMErrorCode integrate(EntData &row_data, EntData &col_data)
MoFEMErrorCode integrateHencky(EntData &row_data, EntData &col_data)
OpSpatialPhysical_du_du(std::string row_field, std::string col_field, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha)
MoFEMErrorCode integrateHencky(EntData &data)
OpSpatialPhysical(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha_u)
OpTopoSpatialPhysical(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > assemble_vec, boost::shared_ptr< TopologicalData > topo_ptr, const double alpha_u, boost::shared_ptr< double > J_ptr)
MoFEMErrorCode assemble(int row_side, EntityType row_type, EntData &data) override
MoFEMErrorCode integrate(EntData &data) override
boost::shared_ptr< TopologicalData > topoDataPtr
MoFEMErrorCode computeMaterialParamsAtPts(OP_PTR op_ptr, EntitiesFieldData::EntData &data, boost::shared_ptr< DataAtIntegrationPts > dataAtGaussPts)
virtual VolUserDataOperator * returnOpTopoSpatialPhysical(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > assemble_vec, boost::shared_ptr< TopologicalData > topo_ptr, const double alpha_u, boost::shared_ptr< double > J_ptr) override
VolUserDataOperator * returnOpCalculateStretchFromStress(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, VectorPtr external_pressure_ptr) override
VolUserDataOperator * returnOpSpatialPhysicalExternalStrain(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< ExternalStrainVec > external_strain_vec_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv) override
VolUserDataOperator * returnOpSpatialPhysical(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha_u) override
HMHHencky(MoFEM::Interface &m_field, const double E, const double nu, const Features features)
Definition HMHHencky.cpp:39
MoFEMErrorCode extractBlockData(Sev sev)
std::vector< BlockData > blockData
static constexpr int StrideMatD
Definition HMHHencky.cpp:55
UserDataOperator * returnOpJacobian(const bool eval_rhs, const bool eval_lhs, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr) override
Definition HMHHencky.cpp:84
MoFEMErrorCode extractBlockData(std::vector< const CubitMeshSets * > meshset_vec_ptr, Sev sev)
bool providesHelmholtzFreeEnergy() const override
VolUserDataOperator * returnOpCalculateStretchFromStress(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr, boost::shared_ptr< MatrixDouble > strain_ptr) override
VolUserDataOperator * returnOpCalculateHelmholtzFreeEnergy(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< double > total_helmholtz_free_energy_ptr) override
VolUserDataOperator * returnOpSpatialPhysical_du_du(std::string row_field, std::string col_field, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha) override
VolUserDataOperator * returnOpCalculateVarStretchFromStress(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr) override
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)
EntityHandle getFEEntityHandle() const
Return finite element entity handle.
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
PetscReal ts_t
Current time value.
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