21using Material = NeoHookeanLogarithmicMaterial;
22using MaterialData = AuxiliaryLogarithmicStressMaterialData;
27 OpReconstructAuxiliaryLogarithmicStretch(
28 boost::shared_ptr<AuxiliaryLogarithmicStressData> values,
35 const int nb_gauss = getGaussPts().size2();
44 *logStretchPtr, nb_gauss);
46 auto t_theta = get_theta();
50 for (
int gg = 0; gg != nb_gauss; ++gg) {
51 t_h(
i,
j) = t_d(
i,
j) + (t_theta(0) / 3.) * t_identity(
i,
j);
60 boost::shared_ptr<AuxiliaryLogarithmicStressData>
valuesPtr;
69 static const auto t_projection = [] {
71 const auto &t_basis = Tensor2SymmetricDeviatorBasis::getBasis();
79 t_projection(n0,
a) = t_basis(n0, n0,
a);
80 t_projection(n1,
a) = t_basis(n0, n1,
a);
81 t_projection(n2,
a) = t_basis(n0, n2,
a);
82 t_projection(n3,
a) = t_basis(n1, n1,
a);
83 t_projection(n4,
a) = t_basis(n1, n2,
a);
84 t_projection(n5,
a) = t_basis(n2, n2,
a);
92 1. / 3., 0., 1. / 3.);
98 if (!std::all_of(values.data().begin(), values.data().end(),
99 [](
const double value) { return std::isfinite(value); }))
101 "Auxiliary logarithmic material or stress-work values are not "
109 OpCalculateAuxiliaryLogarithmicMaterial(
110 boost::shared_ptr<DataAtIntegrationPts> data,
111 boost::shared_ptr<MaterialData> material_data,
118 if (!std::isfinite(alphaU))
120 "Neo-Hookean deviator viscosity must be finite");
125 const int nb_gauss = getGaussPts().size2();
126 const auto parameters =
parameterFun(getFEEntityHandle());
128 calculateMaterial(parameters, nb_gauss);
131 getFEMethod()->snes) {
134 CHKERR SNESSetFunctionDomainError(getFEMethod()->snes);
142 CHKERR calculateTangent(nb_gauss);
154 const int nb_gauss) {
156 const auto fields =
dataAtPts->auxiliaryData;
158 *fields->logDeviator, nb_gauss);
161 *fields->logJacobian, nb_gauss);
164 *fields->stress, nb_gauss);
165 auto get_elastic_stress =
170 auto get_compliance =
187 auto t_theta = get_theta();
188 auto t_stress = get_stress();
189 auto t_elastic_stress = get_elastic_stress();
190 std::optional<
decltype(t_d)> t_dot_d;
194 *fields->logDeviatorDot, nb_gauss)());
195 auto t_dm = get_dm();
196 auto t_compliance = get_compliance();
197 auto t_energy = get_energy();
198 auto t_volume = get_volume();
199 auto t_rd = get_rd();
200 auto t_rtheta = get_rtheta();
201 auto t_rt = get_rt();
202 auto t_work =
dataAtPts->getFTensorAdjointPdU(nb_gauss);
203 auto t_plastic_f =
dataAtPts->getFTensorPlasticF(nb_gauss);
204 const auto &t_projection = getPackedDeviatorBasis();
205 const auto &t_volume_projection = getPackedVolumeBasis();
210 for (
int gg = 0; gg != nb_gauss; ++gg) {
212 t_current_d(
a) = t_d(
a);
213 t_current_stress(
a) = t_stress(
a);
215 t_current_stress(
a) -=
alphaU * (*t_dot_d)(
a);
216 t_elastic_stress(
a) = t_current_stress(
a);
221 double deviatoric_energy;
226 t_energy(MaterialData::DEVIATORIC) = deviatoric_energy;
227 t_energy(MaterialData::VOLUMETRIC) = volume.
energy;
229 t_volume(MaterialData::JACOBIAN) = volume.
jacobian;
236 t_rd(
a) = det_plastic_f * (t_stress(
a) - t_projection(
L,
a) * t_work(
L));
238 t_volume_projection(
L) * t_work(
L));
267 "Auxiliary tangent evaluation requires the current geometry "
269 if (
dataAtPts->nbUniq.size() != nb_gauss)
271 "Auxiliary work curvature requires the current stretch spectrum");
273 auto get_compliance =
291 auto get_thetatheta =
300 auto get_thetaomega =
309 auto t_compliance = get_compliance();
310 auto t_volume = get_volume();
311 auto t_dd = get_dd();
312 auto t_dtheta = get_dtheta();
313 auto t_dt = get_dt();
314 auto t_td = get_td();
315 auto t_thetatheta = get_thetatheta();
316 auto t_tt = get_tt();
317 auto t_domega = get_domega();
318 auto t_thetaomega = get_thetaomega();
319 auto t_fd = get_fd();
320 auto t_ftheta = get_ftheta();
321 auto t_work =
dataAtPts->getFTensorAdjointPdU(nb_gauss);
322 auto t_work_omega =
dataAtPts->getFTensorAdjointPdUdOmega(nb_gauss);
323 auto t_fh =
dataAtPts->getFTensorAdjointPdUdP(nb_gauss);
324 auto t_adjoint_p =
dataAtPts->getFTensorAdjointPdstretch(nb_gauss);
325 auto t_eigen_values =
dataAtPts->getFTensorEigenVals(nb_gauss);
326 auto t_eigen_vectors =
dataAtPts->getFTensorEigenVecs(nb_gauss);
327 auto t_plastic_f =
dataAtPts->getFTensorPlasticF(nb_gauss);
328 const auto &t_basis = Tensor2SymmetricDeviatorBasis::getBasis();
329 const auto &t_projection = getPackedDeviatorBasis();
330 const auto &t_volume_projection = getPackedVolumeBasis();
332 return std::exp(value);
342 const double alpha_u_shift =
alphaU * getTSa();
344 for (
int gg = 0; gg != nb_gauss; ++gg) {
346 t_symmetric_adjoint(
i,
j) = (t_adjoint_p(
i,
j) || t_adjoint_p(
j,
i)) / 2.;
348 t_eigen_values, t_eigen_vectors, exp_fun, exp_fun, exp_fun,
349 t_symmetric_adjoint,
dataAtPts->nbUniq[gg]);
354 (t_basis(
i,
j,
a) * (t_curvature(
i,
j,
k,
l) * t_basis(
k,
l, b)));
356 t_dtheta(
a, n0) = -det_plastic_f * (t_projection(
L,
a) * t_work(
L)) / 3.;
358 det_plastic_f * (t_volume(MaterialData::SECOND_DERIVATIVE) -
359 (t_volume_projection(
L) * t_work(
L)) / 3.);
360 t_dt(
a, b) = det_plastic_f * t_identity(
a, b);
361 t_td(
a, b) = det_plastic_f *
362 (t_identity(
a, b) + alpha_u_shift * t_compliance(
a, b));
363 t_tt(
a, b) = -det_plastic_f * t_compliance(
a, b);
365 -det_plastic_f * (t_projection(
L,
a) * t_work_omega(
k,
L));
366 t_thetaomega(n0,
k) =
367 -det_plastic_f * (t_volume_projection(
L) * t_work_omega(
k,
L));
371 t_reference_fh(
i,
j,
L) = t_fh(
i,
k,
L) * t_plastic_f(
k,
j);
372 t_fd(
i,
j,
a) = t_reference_fh(
i,
j,
L) * t_projection(
L,
a);
373 t_ftheta(
i,
j, z) = (t_reference_fh(
i,
j,
L) * t_volume_projection(
L)) *
374 t_scalar_component(z);
396 for (
const auto &values :
403 CHKERR validateValues(*values);
409template <
int RowDim,
int ColDim>
410struct OpAuxiliaryCoefficientMass :
public OpBase {
411 OpAuxiliaryCoefficientMass(
const std::string &row_field,
412 const std::string &col_field,
MatrixPtr values,
413 const bool assemble_transpose =
true)
415 sYmm = row_field == col_field;
416 assembleTranspose = assemble_transpose && !sYmm;
425 DL>::get(*valuesPtr, nbIntegrationPts);
426 auto t_values = get_values();
427 auto t_w = getFTensor0IntegrationWeight();
429 for (
int gg = 0; gg != nbIntegrationPts; ++gg) {
430 const double alpha = t_w * getMeasure();
432 for (; rr != nbRows / RowDim; ++rr) {
434 auto t_m = getLocMat<RowDim, ColDim>(RowDim * rr);
435 for (
int cc = 0; cc != nbCols / ColDim; ++cc) {
436 t_m(
a, b) += (alpha * t_row * t_col) * t_values(
a, b);
442 for (; rr < nbRowBaseFunctions; ++rr)
454template <
int BASE_DIM,
int FIELD_DIM>
464 OpFormatDeviator(
const std::string &name,
MatrixPtr coordinates,
465 MaterialPostProcData &output)
469 output.symmetricFields[name] =
tensorPtr;
474 const int nb_gauss = getGaussPts().size2();
475 auto get_coordinates =
477 *coordinatesPtr, nb_gauss);
480 *tensorPtr, nb_gauss);
481 auto t_coordinates = get_coordinates();
482 auto t_tensor = get_tensor();
484 for (
int gg = 0; gg != nb_gauss; ++gg) {
485 const auto t_deviator =
486 Tensor2SymmetricDeviatorBasis::getTensor(t_coordinates);
487 t_tensor(
i,
j) = t_deviator(
i,
j);
500 OpFormatMaterial(boost::shared_ptr<DataAtIntegrationPts> data,
501 MaterialPostProcData &output)
513 const int nb_gauss = getGaussPts().size2();
514 const auto fields =
dataAtPts->auxiliaryData;
515 const auto material =
dataAtPts->auxiliaryMaterialData;
518 *material->energy, nb_gauss);
521 *material->volume, nb_gauss);
522 for (
const auto &values_ptr :
524 values_ptr->resize(nb_gauss,
false);
527 dataAtPts->energyAtPts.resize(nb_gauss,
false);
528 auto t_material_energy = get_energy();
529 auto t_volume = get_volume();
533 for (
int gg = 0; gg != nb_gauss; ++gg) {
534 const double physical_energy =
535 t_material_energy(MaterialData::DEVIATORIC) +
536 t_material_energy(MaterialData::VOLUMETRIC);
537 if (!std::isfinite(physical_energy))
539 "Logarithmic material diagnostic output is not representable");
540 t_physical = physical_energy;
541 t_energy = physical_energy;
542 t_jacobian = t_volume(MaterialData::JACOBIAN);
553 boost::shared_ptr<DataAtIntegrationPts>
dataAtPts;
562 const EshelbianCore &ep, boost::ptr_deque<UserDataOperator> &pipeline,
563 boost::shared_ptr<AuxiliaryLogarithmicStressData> values,
568 !values || !reconstructed_log_stretch)
570 "Auxiliary field evaluation requires the auxiliary layout and "
571 "valid output storage");
572 pipeline.push_back(
new OpCalculateTensor2SymmetricDeviatorFieldValues<3>(
574 values->logDeviator));
577 pipeline.push_back(
new OpCalculateTensor2SymmetricDeviatorFieldValues<3>(
580 pipeline.push_back(
new OpReconstructAuxiliaryLogarithmicStretch(
581 std::move(values), std::move(reconstructed_log_stretch)));
596 auto get_material_energy =
598 *material.
energy, nb_gauss);
599 mixed_energy.resize(nb_gauss,
false);
601 auto t_stress = get_stress();
602 auto t_material_energy = get_material_energy();
605 for (
int gg = 0; gg != nb_gauss; ++gg) {
606 const double energy = t_stress(
a) * t_d(
a) -
607 t_material_energy(MaterialData::CONJUGATE) +
608 t_material_energy(MaterialData::VOLUMETRIC);
609 if (!std::isfinite(energy))
611 "Mixed stored-energy contribution is not representable");
623 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
624 boost::shared_ptr<DataAtIntegrationPts> data,
625 boost::shared_ptr<AuxiliaryLogarithmicStressMaterialData> material_data,
628 if (!data || !data->auxiliaryData || !material_data || !parameters)
630 "Auxiliary material operators require field data, material data "
631 "and an element parameter callback");
637 "Auxiliary material operators require the symmetric "
638 "no_h1 formulation");
643 ep.
logDeviator, data->auxiliaryData->logDeviatorDot, MBTET,
false));
644 pipeline.push_back(
new OpCalculateAuxiliaryLogarithmicMaterial(
645 std::move(data), std::move(material_data), std::move(parameters),
652 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
653 boost::shared_ptr<AuxiliaryLogarithmicStressMaterialData> material_data,
657 pipeline.push_back(
new OpAuxiliaryResidual<5>(
659 pipeline.push_back(
new OpAuxiliaryResidual<1>(
661 pipeline.push_back(
new OpAuxiliaryResidual<5>(
666 pipeline.push_back(
new OpAuxiliaryCoefficientMass<5, 5>(
668 pipeline.push_back(
new OpAuxiliaryCoefficientMass<5, 1>(
670 pipeline.push_back(
new OpAuxiliaryCoefficientMass<1, 1>(
672 pipeline.push_back(
new OpAuxiliaryCoefficientMass<5, 5>(
674 material_data->tangentDeviatorStress,
false));
675 pipeline.push_back(
new OpAuxiliaryCoefficientMass<5, 5>(
677 material_data->tangentStressDeviator,
false));
678 pipeline.push_back(
new OpAuxiliaryCoefficientMass<5, 5>(
680 material_data->tangentStress));
681 pipeline.push_back(
new OpAuxiliaryCoefficientMass<5, 3>(
683 pipeline.push_back(
new OpAuxiliaryCoefficientMass<1, 3>(
686 constexpr auto work_sign = []()
constexpr {
return -1.; };
687 pipeline.push_back(
new OpBaseTensorBase<3, 5>(
690 pipeline.push_back(
new OpBaseTensorBase<3, 1>(
693 pipeline.push_back(
new OpBaseTensorBase<9, 5>(
696 pipeline.push_back(
new OpBaseTensorBase<9, 1>(
703 boost::ptr_deque<UserDataOperator> &,
704 boost::shared_ptr<AuxiliaryLogarithmicStressData> values,
709 "Auxiliary postprocessing requires evaluated material fields");
712 output.
scalarFields[prefix +
"theta"] = values->logJacobian;
718 boost::shared_ptr<DataAtIntegrationPts> data,
721 if (!data || !data->auxiliaryData || !data->auxiliaryMaterialData)
723 "Auxiliary postprocessing requires field and material producers");
726 pipeline.push_back(
new OpFormatDeviator(
727 "D_m", data->auxiliaryMaterialData->materialDeviator, output));
728 pipeline.push_back(
new OpFormatMaterial(std::move(data), output));
Material and stress-work blocks for the independent D/theta/Td fields.
Distinct kinematic and material copies for diagnostic output.
AuxiliaryLogarithmicMaterialParameters parameterFun
boost::shared_ptr< MaterialData > materialData
VectorPtr physicalEnergyPtr
boost::shared_ptr< AuxiliaryLogarithmicStressData > valuesPtr
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
Evaluation of independent logarithmic material fields.
Eshelbian plasticity interface.
#define FTENSOR_INDEXES(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()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_OPERATION_UNSUCCESSFUL
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
boost::function< T(const T)> Fun
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.
MoFEMErrorCode pushAuxiliaryLogarithmicPostProc(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data, MaterialPostProcData &output)
boost::shared_ptr< MatrixDouble > MatrixPtr
VolumeElementForcesAndSourcesCore::UserDataOperator VolUserDataOperator
MoFEMErrorCode pushAuxiliaryLogarithmicMaterialEvaluation(const EshelbianCore &ep, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, boost::shared_ptr< DataAtIntegrationPts > data, boost::shared_ptr< AuxiliaryLogarithmicStressMaterialData > material_data, AuxiliaryLogarithmicMaterialParameters parameters, bool lhs=false)
MoFEMErrorCode pushAuxiliaryLogarithmicStatePostProc(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, boost::shared_ptr< AuxiliaryLogarithmicStressData > values, const std::string &prefix, MaterialPostProcData &output)
std::function< NeoHookeanLogarithmicMaterial::Parameters(EntityHandle)> AuxiliaryLogarithmicMaterialParameters
Return parameters already checked by the material's setup validation.
MoFEMErrorCode evaluateAuxiliaryMixedStoredEnergy(const AuxiliaryLogarithmicStressData &fields, const AuxiliaryLogarithmicStressMaterialData &material, VectorDouble &mixed_energy)
DataLayoutTraits< DataLayout::GaussByCoeffs > DL
MoFEMErrorCode pushAuxiliaryLogarithmicMaterialOps(const EshelbianCore &ep, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, boost::shared_ptr< AuxiliaryLogarithmicStressMaterialData > material_data, bool lhs)
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)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
UBlasVector< double > VectorDouble
implementation of Data Operators for Forces and Sources
decltype(GetFTensor2SymmetricFromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2SymmetricFromMatType
decltype(GetFTensor1FromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor1FromMatType
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
static auto determinantTensor3by3(T &t)
Calculate the determinant of a 3x3 matrix or a tensor of rank 2.
decltype(GetFTensor3FromMatImpl< Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor3FromMatType
decltype(GetFTensor2FromMatImpl< Tensor_Dim0, Tensor_Dim1, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2FromMatType
MoFEM::Interface & mField
static enum RotSelector gradApproximator
const std::string logDeviator
const std::string piolaStress
const std::string logJacobian
const std::string bubbleField
static constexpr enum SymmetrySelector symmetrySelector
const std::string auxiliaryLogStress
boost::shared_ptr< PhysicalEquations > physicalEquations
const std::string rotAxis
MatrixPtr elasticStress
5, Td-alphaU*dotD
Map::DataMapMat symmetricFields
Map::DataMapVec scalarFields
Coordinates tMaterialDeviator
double firstDerivative
d[g(exp(theta))]/d theta
double secondDerivative
d2[g(exp(theta))]/d theta2
static MoFEMErrorCode evaluateInverse(const Parameters ¶meters, const Coordinates &t_stress, InverseState &state)
Recover Dm(Td), its compliance and conjugate energy; no state is cached.
static MoFEMErrorCode evaluateDeviator(const Parameters ¶meters, const Coordinates &t_deviator, double &energy, Coordinates *stress_ptr=nullptr, Tangent *hessian_ptr=nullptr)
Evaluate f(D), optionally its five-component gradient and Hessian.
static MoFEMErrorCode evaluateVolume(const Parameters ¶meters, double theta, VolumeState &state)
Evaluate g(J) = K*(J-1)^2/2 and its logarithmic-volume derivatives.
@ AUXILIARY_LOGARITHMIC_STRESS
Auxiliary logarithmic stress formulation.
virtual MPI_Comm & get_comm() const =0
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.
Approximate field values for given petsc vector.
Specialization for MatrixDouble vector field values calculation.
intrusive_ptr for managing petsc objects
@ CTX_SNESSETFUNCTION
Setting up nonlinear function evaluation.
@ CTX_TSSETIJACOBIAN
Setting up implicit Jacobian.