v0.16.3
Loading...
Searching...
No Matches
EshelbianMat.cpp
Go to the documentation of this file.
1/**
2 * \file EshelbianMat.cpp
3 * \brief Implementation of automatic differentiation
4 */
5
6#include <MoFEM.hpp>
7using namespace MoFEM;
8
9#include <MatElastic.hpp>
10#include <MatrixFunction.hpp>
11
14#include <EshelbianAux.hpp>
17
19
20#include <boost/math/constants/constants.hpp>
21#include <regex>
22
23namespace EshelbianPlasticity {
24
25std::vector<PhysicalEquations::FieldDefinition>
27 std::vector<FieldDefinition> fields;
28 auto set_fields = [&]<FieldApproximationBase Base>() {
32 fields = {{ep.logDeviator, Orders::logDeviator(ep.spaceOrder), 5},
33 {ep.logJacobian, Orders::logJacobian(ep.spaceOrder), 1},
35 Orders::auxiliaryLogStress(ep.spaceOrder), 5}};
36 } else {
37 fields = {{ep.stretchTensor,
38 (getFeatures() & noStretchMask).any()
39 ? -1
40 : Orders::stretch(ep.spaceOrder),
41 6}};
42 }
44 };
46 "Get material field orders failed");
47 return fields;
48}
49
50std::vector<std::string>
52 std::vector<std::string> fields;
53 for (const auto &field : getMaterialFieldDefinitions(ep))
54 if (field.order >= 0)
55 fields.push_back(field.name);
56 return fields;
57}
58
59std::vector<std::pair<std::string, std::string>>
61 std::vector<std::pair<std::string, std::string>> blocks;
62 // Eliminated stretch and the updated plastic flow direction couple P/bubble.
63 if ((getFeatures() & noStretchMask).any() || ep.plasticVolume) {
64 blocks.emplace_back(ep.bubbleField, ep.bubbleField);
65 blocks.emplace_back(ep.bubbleField, ep.piolaStress);
66 }
67 for (const auto &field : getMaterialFields(ep))
68 blocks.emplace_back(field, field);
70 blocks.emplace_back(ep.logDeviator, ep.logJacobian);
71 blocks.emplace_back(ep.logDeviator, ep.auxiliaryLogStress);
72 for (const auto &field : {ep.logDeviator, ep.logJacobian})
73 for (const auto &mechanical :
74 {ep.piolaStress, ep.bubbleField, ep.rotAxis})
75 blocks.emplace_back(field, mechanical);
76 } else if (getFeatures().test(DIRECT_STRETCH)) {
77 for (const auto &field : {ep.piolaStress, ep.bubbleField, ep.rotAxis})
78 blocks.emplace_back(ep.stretchTensor, field);
79 }
80 return blocks;
81}
82
83std::vector<std::pair<std::string, std::string>>
85 std::vector<std::pair<std::string, std::string>> blocks;
86 for (const auto &field : getMaterialFields(ep))
87 blocks.emplace_back(ep.spatialL2Disp, field);
88 if ((getFeatures() & noStretchMask).none()) {
89 blocks.emplace_back(ep.bubbleField, ep.bubbleField);
90 blocks.emplace_back(ep.piolaStress, ep.piolaStress);
91 blocks.emplace_back(ep.bubbleField, ep.piolaStress);
92 }
94 for (const auto &field :
96 blocks.emplace_back(ep.auxiliaryLogStress, field);
97 return blocks;
98}
99
102 const MaterialModel material_model,
103 const Features features) {
107
108 double alpha_grad_u = 0;
109 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, PETSC_NULLPTR,
110 "-neo_hookean_viscosity_alpha_grad_u",
111 &alpha_grad_u, PETSC_NULLPTR);
112 PetscBool h1_update = ep.physicalH1Update;
113 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, PETSC_NULLPTR,
114 "-physical_h1_update", &h1_update, PETSC_NULLPTR);
115 const bool plastic_solver =
116 ep.plasticVolume &&
121 ep.solverType ==
123 ep.solverType ==
125 const std::pair<bool, const char *> unsupported[] = {
126 {material_model != Neohookean, "requires -material neo_hookean"},
127 {ep.stretchSelector != LOG, "requires -stretches log"},
128 {ep.rotSelector != LARGE_ROT, "requires -rotations large"},
130 "requires the symmetric row convention"},
131 {ep.gradApproximator != NO_H1_CONFIGURATION, "requires -grad no_h1"},
132 {alpha_grad_u != 0,
133 "requires zero -neo_hookean_viscosity_alpha_grad_u"},
134 {!plastic_solver &&
136 "requires time_solver without dynamic relaxation or plastic "
137 "incremental optimization"},
138 {h1_update == PETSC_TRUE, "does not yet support -physical_h1_update"},
139 {ep.crackingOn || ep.interfaceCrack,
140 "does not yet support -cracking_on or -cohesive_interface_on"},
141 {!ep.internalStressTagName.empty(),
142 "does not yet support internal stress"},
143 {ep.meshTransferSourceMeshFileSpecified == PETSC_TRUE,
144 "does not yet support material mesh transfer"}};
145 for (const auto &[invalid, reason] : unsupported) {
146 if (invalid)
148 "-auxiliary_logarithmic_stress %s", reason);
149 }
150
152}
153
158
159 Range sdf_contact_faces;
160 for (const auto &block :
161 ep.mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
162 std::regex("CONTACT_SDF(.*)"))) {
163 CHKERR block->getMeshsetIdEntitiesByDimension(
164 ep.mField.get_moab(), SPACE_DIM - 1, sdf_contact_faces, true);
165 }
166 const auto nonempty = [](const auto &ptr) { return ptr && !ptr->empty(); };
167 const std::pair<bool, const char *> unsupported_data[] = {
168 {nonempty(ep.externalStrainVecPtr), "external strain prescriptions"},
169 {nonempty(ep.bcSpatialPressureVecPtr), "follower pressure loads"},
170 {nonempty(ep.contactFaces) || !sdf_contact_faces.empty(),
171 "contact meshsets"},
172 {nonempty(ep.frontEdges) || nonempty(ep.crackFaces) ||
173 nonempty(ep.interfaceFaces),
174 "front, crack or interface meshsets"}};
175 for (const auto &[local_active, capability] : unsupported_data) {
176 int active = local_active;
177 CHKERR MPI_Allreduce(MPI_IN_PLACE, &active, 1, MPI_INT, MPI_MAX,
178 ep.mField.get_comm());
179 if (active)
181 "-auxiliary_logarithmic_stress does not yet support %s",
182 capability);
183 }
184
186}
187
189 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
190 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const FieldState state) {
192 data_ptr->physicsPtr = ep.physicalEquations;
193 const bool previous = state == PREVIOUS;
194 auto strain_ptr = previous ? data_ptr->getLogStretchTensor0AtPts()
195 : data_ptr->getLogStretchTensorAtPts();
196 auto values = previous ? ep.solTSStep : SmartPetscObj<Vec>();
198 auto &fields =
199 previous ? data_ptr->auxiliaryData0 : data_ptr->auxiliaryData;
200 if (!fields)
201 fields = boost::make_shared<AuxiliaryLogarithmicStressData>();
202 CHKERR pushAuxiliaryLogarithmicFields(ep, pipeline, fields, strain_ptr,
203 values);
204 } else if ((getFeatures() & noStretchMask).any()) {
205 CHKERR pushStretchFromStress(ep, pipeline, data_ptr, strain_ptr,
206 previous ? data_ptr->getApproxP0AtPts()
207 : data_ptr->getApproxPAtPts());
208 } else {
209 pipeline.push_back(new OpCalculateTensor2SymmetricFieldValues<3>(
210 ep.stretchTensor, strain_ptr, values, MBTET));
211 }
213}
214
216 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
217 boost::shared_ptr<DataAtIntegrationPts> data_ptr) {
219 if (getFeatures().test(DIRECT_STRETCH)) {
221 ep.stretchTensor, data_ptr->getLogStretchDotTensorAtPts(), MBTET));
222 pipeline.push_back(new OpCalculateVectorFieldGradientDot<6, 3>(
223 ep.stretchTensor, data_ptr->getGradLogStretchDotTensorAtPts(), MBTET));
224 }
226}
227
229 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
230 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
231 boost::shared_ptr<MatrixDouble> strain_ptr,
232 boost::shared_ptr<MatrixDouble> stress_ptr) {
234 data_ptr->physicsPtr = ep.physicalEquations;
235 auto external_pressure_ptr = boost::make_shared<VectorDouble>();
237 external_pressure_ptr, ep.externalStrainVecPtr, ep.timeScaleMap))
238 pipeline.push_back(op);
239 pipeline.push_back(returnOpCalculateStretchFromStress(
240 std::move(data_ptr), ep.physicalEquations, std::move(strain_ptr),
241 std::move(stress_ptr), std::move(external_pressure_ptr)));
243}
244
246 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
247 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const bool rhs,
248 const bool lhs) {
251 if (rhs || lhs)
253 lhs);
254 } else if (getFeatures().test(DIRECT_STRETCH)) {
255 pipeline.push_back(
256 returnOpJacobian(rhs, lhs, data_ptr, ep.physicalEquations));
257 }
259}
260
261/** Material Helmholtz derivative with respect to the explicit elastic state. */
264 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
265 boost::shared_ptr<MatrixDouble> state_gradient_ptr)
266 : VolUserDataOperator(NOSPACE, OPSPACE), dataAtPts(std::move(data_ptr)),
267 stateGradientPtr(std::move(state_gradient_ptr)) {
271 "Helmholtz state-gradient operator has a null data pointer");
272 }
273
274 MoFEMErrorCode doWork(int, EntityType, EntData &) override {
276 constexpr int state_size = 6;
277 const int nb_integration_pts = getGaussPts().size2();
279 auto get_state_gradient =
281 DL>::size(*stateGradientPtr, nb_integration_pts);
282 auto t_state_gradient = get_state_gradient();
283 auto t_work = dataAtPts->getFTensorAdjointPdU(nb_integration_pts);
284 auto t_plastic_f = dataAtPts->getFTensorPlasticF(nb_integration_pts);
285 FTENSOR_INDEX(state_size, L);
286 for (int gg = 0; gg != nb_integration_pts; ++gg) {
287 // At equilibrium the direct stretch row identifies this assembled
288 // stress-work derivative with the material gradient. Jp=1 for the
289 // trace-free plastic approximation.
290 const double det_plastic_f = determinantTensor3by3(t_plastic_f);
291 t_state_gradient(L) = det_plastic_f * t_work(L);
292 ++t_state_gradient;
293 ++t_work;
294 ++t_plastic_f;
295 }
297 }
298
299private:
300 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
301 boost::shared_ptr<MatrixDouble> stateGradientPtr;
302};
303
305 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
306 boost::shared_ptr<DataAtIntegrationPts> data_ptr) {
308 auto gradient_at_points = boost::make_shared<MatrixDouble>();
309 pipeline.push_back(
310 new OpCalculateHelmholtzStateGradient(data_ptr, gradient_at_points));
311 using OpAssembleGradient = FormsIntegrators<VolUserDataOperator>::Assembly<
313 pipeline.push_back(
314 new OpAssembleGradient(ep.stretchTensor, gradient_at_points));
316}
317
319 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &,
320 boost::shared_ptr<DataAtIntegrationPts>, bool) {
323 "Selected material does not implement auxiliary logarithmic stress");
325}
326
328 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &,
329 boost::shared_ptr<DataAtIntegrationPts>, bool) {
332 "Selected material does not evaluate auxiliary logarithmic stress");
334}
335
337 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
338 boost::shared_ptr<DataAtIntegrationPts> data_ptr) {
340 if ((getFeatures() & noStretchMask).any())
343 CHKERR pushAuxiliaryLogarithmicStressOps(ep, pipeline, data_ptr, false);
345 }
346
347 if (!ep.internalStressTagName.empty()) {
348 switch (ep.meshTransferInterpOrder) {
349 case 0:
350 pipeline.push_back(
352 break;
353 case 1:
354 pipeline.push_back(
356 break;
357 default:
359 "Unsupported mesh transfer interpolation order %d, for "
360 "internal stress",
362 }
363 TimeScale::ScalingFun default_scaling = [](double) { return 1; };
364 auto time_scale =
365 boost::make_shared<EshelbianCore::DynamicRelaxationTimeScale>(
366 "internal_stress_history.txt", false, default_scaling);
367 if (ep.internalStressVoigt)
368 pipeline.push_back(new OpSpatialPhysicalInternalStress<true>(
369 ep.stretchTensor, data_ptr, time_scale));
370 else
371 pipeline.push_back(new OpSpatialPhysicalInternalStress<false>(
372 ep.stretchTensor, data_ptr, time_scale));
373 }
375 ep.stretchTensor, data_ptr, ep.externalStrainVecPtr, ep.timeScaleMap))
376 pipeline.push_back(op);
377 else if (ep.externalStrainVecPtr && !ep.externalStrainVecPtr->empty())
378 SETERRQ(
380 "OpSpatialPhysicalExternalStrain not implemented for this material");
381
382 pipeline.push_back(
385}
386
388 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
389 boost::shared_ptr<DataAtIntegrationPts> data_ptr) {
391 if ((getFeatures() & noStretchMask).any()) {
392 const bool heterogeneous = getFeatures().test(NON_HOMOGENEOUS_MATERIAL);
393 pipeline.push_back(new OpSpatialConsistency_dP_dP(
394 ep.piolaStress, ep.piolaStress, data_ptr, heterogeneous));
395 pipeline.push_back(new OpSpatialConsistency_dBubble_dP(
396 ep.bubbleField, ep.piolaStress, data_ptr, heterogeneous));
397 pipeline.push_back(new OpSpatialConsistency_dBubble_dBubble(
398 ep.bubbleField, ep.bubbleField, data_ptr, heterogeneous));
399 } else if (getFeatures().test(AUXILIARY_LOGARITHMIC_STRESS)) {
400 CHKERR pushAuxiliaryLogarithmicStressOps(ep, pipeline, data_ptr, true);
401 } else {
402 pipeline.push_back(returnOpSpatialPhysical_du_du(
403 ep.stretchTensor, ep.stretchTensor, data_ptr, ep.alphaU));
404 pipeline.push_back(new OpSpatialPhysical_du_dP(
405 ep.stretchTensor, ep.piolaStress, data_ptr, true));
406 pipeline.push_back(new OpSpatialPhysical_du_dBubble(
407 ep.stretchTensor, ep.bubbleField, data_ptr, true));
408 pipeline.push_back(
412 pipeline.push_back(new OpSpatialRotation_domega_du(
413 ep.rotAxis, ep.stretchTensor, data_ptr, false));
414 }
416}
417
419 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
420 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
421 boost::shared_ptr<double> total_energy_ptr) {
423 if (auto op =
424 returnOpCalculateHelmholtzFreeEnergy(data_ptr, total_energy_ptr)) {
425 // Energy uses the physical strain recovered from stress for these models.
427 CHKERR pushStretchFromStress(ep, pipeline, data_ptr,
428 data_ptr->getLogStretchTotalTensorAtPts());
429 pipeline.push_back(op);
430 }
432}
433
435 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
436 boost::shared_ptr<DataAtIntegrationPts> data_ptr) {
438 if (usesStressBasedStrain()) {
439 CHKERR pushStretchFromStress(ep, pipeline, data_ptr);
440 } else {
441 // These fields represent mechanical stretch; this force evaluation does
442 // not reconstruct physical strain for imposed internal stress or strain.
443 CHKERR pushMaterialFields(ep, pipeline, data_ptr);
444 }
446}
447
449 const bool eval_rhs, const bool eval_lhs,
450 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
451 boost::shared_ptr<PhysicalEquations> physics_ptr) {
452 return nullptr;
453}
454
456 const std::string &field_name,
457 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const double alpha_u) {
458 return nullptr;
459}
460
462 const std::string &field_name,
463 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
464 boost::shared_ptr<ExternalStrainVec> external_strain_vec_ptr,
465 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv) {
466 return nullptr;
467}
468
470 std::string row_field, std::string col_field,
471 boost::shared_ptr<DataAtIntegrationPts> data_ptr, const double alpha) {
472 return nullptr;
473}
474
476 const std::string &field_name,
477 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
478 SmartPetscObj<Vec> assemble_vec,
479 boost::shared_ptr<TopologicalData> topo_ptr, const double alpha_u,
480 boost::shared_ptr<double> J_ptr) {
481 return nullptr;
482}
483
485 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
486 boost::shared_ptr<double> total_helmholtz_free_energy_ptr) {
487 return nullptr;
488}
489
491
493 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
494 boost::shared_ptr<PhysicalEquations> physics_ptr,
495 boost::shared_ptr<MatrixDouble> strain_ptr) {
496 return nullptr;
497}
498
500 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
501 boost::shared_ptr<PhysicalEquations> physics_ptr,
502 boost::shared_ptr<MatrixDouble> strain_ptr,
503 VectorPtr external_pressure_ptr) {
505 std::move(data_ptr), std::move(physics_ptr), std::move(strain_ptr));
506}
507
509 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
510 boost::shared_ptr<PhysicalEquations> physics_ptr,
511 boost::shared_ptr<MatrixDouble> strain_ptr,
512 boost::shared_ptr<MatrixDouble> stress_ptr,
513 VectorPtr external_pressure_ptr) {
515 std::move(data_ptr), std::move(physics_ptr), std::move(strain_ptr),
516 std::move(external_pressure_ptr));
517}
518
520 VectorPtr external_pressure_ptr,
521 boost::shared_ptr<ExternalStrainVec> external_strain_vec_ptr,
522 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv) {
523 return nullptr;
524}
525
527 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
528 boost::shared_ptr<PhysicalEquations> physics_ptr) {
529 return nullptr;
530};
531
533 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
534 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
535 MaterialPostProcData &output) {
537 if ((getFeatures() & noStretchMask).any()) {
538 pipeline.push_back(
539 returnOpJacobian(true, false, data_ptr, ep.physicalEquations));
540 } else {
541 CHKERR pushMaterialEvaluation(ep, pipeline, data_ptr, true, false);
542 }
544 CHKERR pushAuxiliaryLogarithmicPostProc(pipeline, data_ptr, output);
545 } else if (auto op =
546 returnOpCalculateHelmholtzFreeEnergy(data_ptr, nullptr)) {
547 pipeline.push_back(op);
548 }
549 output.symmetricFields["LogSpatialStretch"] =
550 data_ptr->getLogStretchTensorAtPts();
551 output.symmetricFields["SpatialStretch"] = data_ptr->getStretchTensorAtPts();
552 if ((getFeatures() & noStretchMask).none())
553 output.vectorFields["EiegnLogStreach"] = data_ptr->getEigenVals();
555}
556
558 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
559 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
560 SmartPetscObj<Vec> variation, MaterialPostProcData *output) {
563 auto values = boost::make_shared<AuxiliaryLogarithmicStressData>();
565 ep, pipeline, values, data_ptr->getVarLogStreachPts(), variation);
566 if (output)
567 CHKERR pushAuxiliaryLogarithmicStatePostProc(pipeline, values, "Var",
568 *output);
569 } else if ((getFeatures() & noStretchMask).any()) {
570 pipeline.push_back(
572 } else {
574 ep.stretchTensor, data_ptr->getVarLogStreachPts(), variation, MBTET));
575 }
576 if (output)
577 output->symmetricFields["VarLogSpatialStretch"] =
578 data_ptr->getVarLogStreachPts();
580}
581
583 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
584 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
585 SmartPetscObj<Vec> residual, MaterialPostProcData &output) {
588 auto values = boost::make_shared<AuxiliaryLogarithmicStressData>();
589 auto residual_stretch = boost::make_shared<MatrixDouble>();
590 CHKERR pushAuxiliaryLogarithmicFields(ep, pipeline, values,
591 residual_stretch, residual);
592 CHKERR pushAuxiliaryLogarithmicStatePostProc(pipeline, values, "Res",
593 output);
594 } else if (getFeatures().test(DIRECT_STRETCH)) {
595 auto residual_stretch = boost::make_shared<MatrixDouble>();
597 ep.stretchTensor, residual_stretch, residual, MBTET));
598 output.symmetricFields["ResLogSpatialStretch"] = residual_stretch;
599 }
601}
602
605 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
606 SmartPetscObj<Vec> residual, MaterialPostProcData &output) {
608 auto &pipeline = fe.getOpPtrVector();
609 fe.getUserPolynomialBase() = boost::make_shared<CGGUserPolynomialBase>(
610 nullptr, !getFeatures().test(AUXILIARY_LOGARITHMIC_STRESS));
611 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
612 pipeline, {HDIV, H1, L2}, ep.materialH1Positions, ep.frontAdjEdges);
614 ep.piolaStress, data_ptr->getApproxPAtPts()));
615 pipeline.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>(
616 ep.rotAxis, data_ptr->getRotAxisAtPts(), MBTET));
617 pipeline.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>(
618 ep.spatialL2Disp, data_ptr->getSmallWL2AtPts(), MBTET));
619
621 const bool add_bubble = ep.mField.check_field(ep.bubbleField);
622 if (add_bubble)
623 pipeline.push_back(new OpCalculateHTensorTensorField<3, 3>(
624 ep.bubbleField, data_ptr->getApproxPAtPts(), MBMAXTYPE));
625 CHKERR VecSetDM(ep.solTSStep.get(), PETSC_NULLPTR);
626 pipeline.push_back(new OpCalculateHVecTensorField<3, 3>(
627 ep.piolaStress, data_ptr->getApproxP0AtPts(), nullptr, ep.solTSStep));
628 if (add_bubble)
629 pipeline.push_back(new OpCalculateHTensorTensorField<3, 3>(
630 ep.bubbleField, data_ptr->getApproxP0AtPts(), nullptr, ep.solTSStep,
631 MBMAXTYPE));
632 CHKERR pushMaterialFields(ep, pipeline, data_ptr, PREVIOUS);
633 CHKERR pushMaterialFields(ep, pipeline, data_ptr, CURRENT);
634 pipeline.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>(
635 ep.rotAxis, data_ptr->getRotAxis0AtPts(), ep.solTSStep, MBTET));
636 pipeline.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>(
637 ep.spatialH1Disp, data_ptr->getSmallWH1AtPts()));
639 ep.spatialH1Disp, data_ptr->getSmallWGradH1AtPts()));
641 pipeline, ep.plasticHField, data_ptr->getPlasticH(), MBTET);
642 pipeline.push_back(new OpCalculateRotationAndSpatialGradient(data_ptr));
643 CHKERR pushMaterialEvaluation(ep, pipeline, data_ptr, true, false);
644 CHKERR pushAuxiliaryLogarithmicPostProc(pipeline, data_ptr, output);
645 output.symmetricFields["SpatialStretch"] =
646 data_ptr->getStretchTensorAtPts();
647 if (residual)
648 CHKERR pushPostProcResidual(ep, pipeline, data_ptr, residual, output);
649 } else {
650 CHKERR pushMaterialFields(ep, pipeline, data_ptr, CURRENT);
651 }
652 output.symmetricFields["LogSpatialStretch"] =
653 data_ptr->getLogStretchTensorAtPts();
655}
656
657} // namespace EshelbianPlasticity
658
660#include <impl/HMHHencky.cpp>
661#include <impl/HMHNeohookean.cpp>
662namespace EshelbianPlasticity {
663
666 const char *list_materials[] = {"stvenant_kirchhoff", "mooney_rivlin",
667 "hencky", "neo_hookean", "meta"};
668 PetscInt choice_material = MooneyRivlin;
669 PetscBool no_stretch = PETSC_FALSE;
670 PetscBool auxiliary_logarithmic_stress = PETSC_FALSE;
671 PetscOptionsBegin(ep.mField.get_comm(), "", "Material physical equations",
672 "none");
673 CHKERR PetscOptionsEList("-material", "material model", "", list_materials,
674 LastMaterial, list_materials[choice_material],
675 &choice_material, PETSC_NULLPTR);
676 CHKERR PetscOptionsBool("-no_stretch", "do not solve for stretch", "",
677 no_stretch, &no_stretch, PETSC_NULLPTR);
678 CHKERR PetscOptionsBool(
679 "-auxiliary_logarithmic_stress",
680 "independent logarithmic deviator, volume and auxiliary stress", "",
681 PETSC_FALSE, &auxiliary_logarithmic_stress, PETSC_NULLPTR);
682 PetscOptionsEnd();
683
684 const auto material_model = static_cast<MaterialModel>(choice_material);
685 if (auxiliary_logarithmic_stress && no_stretch &&
686 material_model == Neohookean)
687 SETERRQ(
689 "-auxiliary_logarithmic_stress cannot be combined with -no_stretch");
691 features.set(auxiliary_logarithmic_stress
693 : (no_stretch ? NO_STRETCH_LINEAR : DIRECT_STRETCH));
694 CHKERR checkOptions(ep, material_model, features);
695 if (!ep.dataAtPts)
696 ep.dataAtPts = boost::make_shared<DataAtIntegrationPts>();
697 const std::map<std::string, std::string> material_model_names_dictionary = {
698 {"grad", "stretchH1AtPts"}, {"P", "PAtPts"}, {"P_dF", "PAtPts_du"}};
699 MatOps::MatPiolaResponse::useDeformationGradient = true;
700 boost::shared_ptr<MatOps::PhysicalEquations> mat_physical_equations_ptr;
701
702 switch (material_model) {
704 MOFEM_LOG("EP", Sev::inform) << "St. Venant-Kirchhoff material model";
705 mat_physical_equations_ptr = MatOps::createMatOpsPhysicalEquationsPtr<
708 material_model_names_dictionary),
709 MatOps::MatOpsTagsRegistry::setTagName("StVenantKirchhoff", 0));
710 break;
711 case MooneyRivlin:
712 MOFEM_LOG("EP", Sev::inform) << "Mooney-Rivlin material model";
713 mat_physical_equations_ptr = MatOps::createMatOpsPhysicalEquationsPtr<
716 material_model_names_dictionary),
717 MatOps::MatOpsTagsRegistry::setTagName("MooneyRivlinWriggersEq63", 0));
718 break;
719 case Hencky:
720 MOFEM_LOG("EP", Sev::inform) << "Hencky material model";
722 boost::make_shared<HMHHencky>(ep.mField, 5., 0.25, features);
723 break;
724 case Neohookean:
725 MOFEM_LOG("EP", Sev::inform) << "Neo-Hookean material model";
727 boost::make_shared<HMHNeohookean>(ep.mField, 1., 2., features);
728 break;
729 case Meta:
730 MOFEM_LOG("EP", Sev::inform) << "Meta Material model";
731 mat_physical_equations_ptr =
732 MatOps::createMatOpsPhysicalEquationsPtr<MatOps::PIOLA_RESPONSE::META,
735 material_model_names_dictionary),
736 MatOps::MatOpsTagsRegistry::setTagName("MetaPiolaResponse", 0));
737 break;
738 default:
739 SETERRQ(ep.mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown material");
740 }
741
742 if (mat_physical_equations_ptr) {
743 CHKERR mat_physical_equations_ptr->getOptions(&ep.mField);
744 CHKERR mat_physical_equations_ptr->recordTape();
745 if (material_model == Meta)
746 ep.physicalEquations = boost::make_shared<MatPhysicalEquations>(
747 boost::static_pointer_cast<MatOps::MatPiolaResponse>(
748 mat_physical_equations_ptr),
749 material_model, features);
750 else
751 ep.physicalEquations = boost::make_shared<MatElasticPhysicalEquations>(
752 boost::static_pointer_cast<MatOps::MatElastic>(
753 mat_physical_equations_ptr),
754 material_model, features);
755 }
756 ep.dataAtPts->physicsPtr = ep.physicalEquations;
757 MOFEM_LOG("EP", Sev::inform) << "No stretch: -no_stretch "
758 << ((ep.physicalEquations->getFeatures() &
760 .any()
761 ? "yes"
762 : "no");
764}
765
766}; // namespace EshelbianPlasticity
Material and stress-work blocks for the independent D/theta/Td fields.
Distinct kinematic and material copies for diagnostic output.
Auxilary functions for Eshelbian plasticity.
Eshelbian plasticity interface.
Direct logarithmic Neo-Hookean material adapter.
Plasticity implementation of incremental optimization.
#define FTENSOR_INDEX(DIM, I)
constexpr int SPACE_DIM
FieldApproximationBase
approximation base
Definition definitions.h:58
#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()
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#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
@ 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.
const char features[]
virtual bool check_field(const std::string &name) const =0
check if field is in database
#define MOFEM_LOG(channel, severity)
Log.
MoFEMErrorCode pushAuxiliaryLogarithmicPostProc(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data, MaterialPostProcData &output)
MoFEMErrorCode pushAuxiliaryLogarithmicStatePostProc(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, boost::shared_ptr< AuxiliaryLogarithmicStressData > values, const std::string &prefix, MaterialPostProcData &output)
MoFEMErrorCode addCalculatePlasticLogarithmicStretchFieldValues(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, const std::string &field_name, boost::shared_ptr< MatrixDouble > tensor_values, const EntityType zero_type, SmartPetscObj< DM > data_dm, SmartPetscObj< Vec > data_vector)
boost::shared_ptr< VectorDouble > VectorPtr
MoFEMErrorCode pushAuxiliaryLogarithmicFields(const EshelbianCore &ep, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, boost::shared_ptr< AuxiliaryLogarithmicStressData > values, boost::shared_ptr< MatrixDouble > reconstructed_log_stretch, SmartPetscObj< Vec > state=nullptr)
@ MODEL_3D
Definition MatOps.hpp:193
boost::shared_ptr< PhysicalEquations > createMatOpsPhysicalEquationsPtr(boost::shared_ptr< MatOpsData > mat_ops_data_ptr, int tag)
boost::shared_ptr< MatOpsData > createMatOpsDataPtr()
Definition MatOps.cpp:709
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
static auto determinantTensor3by3(T &t)
Calculate the determinant of a 3x3 matrix or a tensor of rank 2.
constexpr AssemblyType A
constexpr auto field_name
boost::shared_ptr< ExternalStrainVec > externalStrainVecPtr
static PetscBool physicalH1Update
static enum StretchSelector stretchSelector
boost::shared_ptr< Range > frontAdjEdges
boost::shared_ptr< Range > contactFaces
MoFEM::Interface & mField
const std::string spatialL2Disp
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
static enum SolverType solverType
const std::string materialH1Positions
static PetscBool crackingOn
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
const std::string spatialH1Disp
@ TestIncrementalOptimizationConstraintDerivative
@ TestIncrementalOptimizationLayout
@ TestIncrementalOptimizationTransaction
@ TestIncrementalOptimizationObjectiveDerivative
@ TestEquilibratedMechanicalValue
const std::string logDeviator
const std::string plasticHField
const std::string piolaStress
const std::string logJacobian
boost::shared_ptr< Range > interfaceFaces
static PetscBool physicalTimeFlg
const std::string bubbleField
static constexpr enum SymmetrySelector symmetrySelector
const std::string auxiliaryLogStress
boost::shared_ptr< PhysicalEquations > physicalEquations
const std::string rotAxis
static std::string internalStressTagName
static PetscBool internalStressVoigt
static PetscBool plasticVolume
static PetscBool meshTransferSourceMeshFileSpecified
static PetscBool interfaceCrack
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
boost::shared_ptr< Range > crackFaces
boost::shared_ptr< PressureBcVec > bcSpatialPressureVecPtr
static int meshTransferInterpOrder
SmartPetscObj< Vec > solTSStep
boost::shared_ptr< Range > frontEdges
const std::string stretchTensor
MoFEMErrorCode withFieldOrders(Op &&op) const
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
MoFEMErrorCode doWork(int, EntityType, EntData &) override
Operator for linear form, usually to calculate values on right hand side.
OpCalculateHelmholtzStateGradient(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< MatrixDouble > state_gradient_ptr)
MoFEMErrorCode pushMaterialRates(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr)
virtual MoFEMErrorCode pushHelmholtzStateGradient(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr)
Assemble the physical Helmholtz state derivative at equilibrium.
MoFEMErrorCode pushMaterialFields(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, FieldState state=CURRENT)
Evaluate the selected fields, or recover stretch from the matching stress.
std::vector< FieldDefinition > getMaterialFieldDefinitions(const EshelbianCore &ep) const
virtual VolUserDataOperator * returnOpCalculateExternalPressure(VectorPtr external_pressure_ptr, boost::shared_ptr< ExternalStrainVec > external_strain_vec_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv)
std::vector< std::pair< std::string, std::string > > getMaterialEmptyBlocks(const EshelbianCore &ep) const
MoFEMErrorCode pushPostProcResidual(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > residual, MaterialPostProcData &output)
virtual VolUserDataOperator * returnOpCalculateVarStretchFromStress(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr)
MoFEMErrorCode pushEnergyEvaluation(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< double > total_energy_ptr)
MoFEMErrorCode checkSetup(const EshelbianCore &ep) const
Check material capabilities after geometry and boundary setup.
MoFEMErrorCode pushMaterialEvaluation(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, bool rhs, bool lhs)
Evaluate constitutive data after kinematics and before material assembly.
MoFEMErrorCode pushMaterialResidual(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr)
virtual UserDataOperator * returnOpJacobian(const bool eval_rhs, const bool eval_lhs, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr)
virtual VolUserDataOperator * returnOpSpatialPhysical(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha_u)
virtual 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)
virtual VolUserDataOperator * returnOpCalculateHelmholtzFreeEnergy(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< double > total_helmholtz_free_energy_ptr)
static MoFEMErrorCode create(EshelbianCore &ep)
Select and configure the material before registering fields and DMs.
virtual MoFEMErrorCode pushAuxiliaryLogarithmicStressOps(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, bool lhs)
Assemble the selected material field group after kinematic reconstruction.
MoFEMErrorCode pushMaterialTangent(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr)
MoFEMErrorCode pushSkeletonEvaluation(const EshelbianCore &ep, VolumeElementForcesAndSourcesCoreOnSide &fe, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > residual, MaterialPostProcData &output)
MoFEMErrorCode pushMaterialForceFields(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr)
std::vector< std::string > getMaterialFields(const EshelbianCore &ep) const
Active material unknowns used by the element, DMs and field split.
virtual bool providesHelmholtzFreeEnergy() const
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)
@ NO_STRETCH_LINEAR
No-stretch linear formulation.
@ DIRECT_STRETCH
Direct stretch formulation.
@ AUXILIARY_LOGARITHMIC_STRESS
Auxiliary logarithmic stress formulation.
virtual MoFEMErrorCode pushAuxiliaryLogarithmicMaterialEvaluation(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, bool lhs=false)
Evaluate the auxiliary material copy and energies without assembly.
virtual VolUserDataOperator * returnOpCalculateStretchFromStress(boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< PhysicalEquations > physics_ptr, boost::shared_ptr< MatrixDouble > strain_ptr=nullptr)
static MoFEMErrorCode checkOptions(const EshelbianCore &ep, MaterialModel material_model, Features features)
std::vector< std::pair< std::string, std::string > > getMaterialCouplings(const EshelbianCore &ep) const
Material-dependent blocks; each pair also represents its transpose.
virtual VolUserDataOperator * returnOpSpatialPhysical_du_du(std::string row_field, std::string col_field, boost::shared_ptr< DataAtIntegrationPts > data_ptr, const double alpha)
MoFEMErrorCode pushStretchFromStress(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< MatrixDouble > strain_ptr=nullptr, boost::shared_ptr< MatrixDouble > stress_ptr=nullptr)
MoFEMErrorCode pushPostProc(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, MaterialPostProcData &output)
MoFEMErrorCode pushMaterialVariation(const EshelbianCore &ep, boost::ptr_deque< UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > variation, MaterialPostProcData *output=nullptr)
static int setTagName(std::string name, int tag=-1)
Definition MatOps.cpp:29
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
Data on single entity (This is passed as argument to DataOperator::doWork)
@ OPSPACE
operator do Work is execute on space data
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
auto & getUserPolynomialBase()
Get the User Polynomial Base object.
boost::ptr_deque< UserDataOperator > & getOpPtrVector()
Use to push back operator for row operator.
Interface for managing meshsets containing materials and boundary conditions.
Calculate tenor field using tensor base, i.e. Hdiv/Hcurl.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Calculate symmetric tensor field rates ant integratio pts.
Calculate symmetric tensor field values at integration pts.
Get field gradients time derivative at integration pts for scalar field rank 0, i....
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for MatrixDouble vector field values calculation.
intrusive_ptr for managing petsc objects
std::function< double(double)> ScalingFun
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.