https://mooseframework.inl.gov
ComputeLagrangianStressPK2.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 
14 {
16  return params;
17 }
18 
20  : ComputeLagrangianStressPK1(parameters),
21  _E(declareProperty<RankTwoTensor>(_base_name + "green_lagrange_strain")),
22  _S(declareProperty<RankTwoTensor>(_base_name + "pk2_stress")),
23  _C(declareProperty<RankFourTensor>(_base_name + "pk2_jacobian"))
24 {
25 }
26 
27 void
29 {
30  // PK2 has its own sigma-wrap structure: sigma = (1/J_ust) F_ust * S * F_ust^T. The PK1 base's
31  // sigma-chain (which assumes pk1_jacobian = constitutive dPK1/dF_stab + _d_F_stab_d_F_ust)
32  // doesn't fit here, so compute sigma and cauchy_jacobian directly from S and dS/dE.
33  //
34  // The R4 chain for `_cauchy_jacobian` is Jacobian-only; the wrap to `_cauchy_stress` is
35  // not. Gate accordingly.
36  const bool need_jacobian = _fe_problem.currentlyComputingJacobian() ||
39  {
40  const Real J_ust = _F_ust[_qp].det();
41  _cauchy_stress[_qp] = _F_ust[_qp] * _S[_qp] * _F_ust[_qp].transpose() / J_ust;
42 
43  if (!need_jacobian)
44  return;
45 
46  // cauchy_jacobian = dsigma/d(dL). sigma depends on dL only through S(E(F_stab(dL))); the
47  // F_ust factors in the wrap are CONSTANT w.r.t. dL (F_ust does not depend on dL --
48  // dL is computed from F_stab via the kinematic helper, and F-bar relates F_stab to
49  // F_ust). So:
50  // dsigma/d(dL) = (1/J_ust) F_ust * dS/d(dL) * F_ust^T
51  // = (1/J_ust) F_ust * _C * dE/d(F_stab) * inverse(d(dL)/d(F_stab)) * F_ust^T.
52  usingTensorIndices(i_, j_, k_, l_);
53  const auto I2 = RankTwoTensor::Identity();
54  const RankFourTensor dE_dFstab = 0.5 * (I2.template times<i_, l_, j_, k_>(_F[_qp].transpose()) +
55  _F[_qp].transpose().template times<i_, k_, j_, l_>(I2));
56  const RankFourTensor dE_d_dL = dE_dFstab * _d_deformation_gradient_increment_d_F[_qp].inverse();
57  const RankFourTensor dS_d_dL = _C[_qp] * dE_d_dL;
59  }
60  else
61  {
63  if (need_jacobian)
65  }
66 }
67 
68 void
70 {
71  // Green-Lagrange strain uses the F-bar-stabilized F (`_F` from the strain calc) so
72  // the constitutive law receives the stabilized strain -- F-bar's purpose is precisely
73  // to feed a volumetrically-corrected strain into the constitutive update.
74  _E[_qp] = 0.5 * (_F[_qp].transpose() * _F[_qp] - RankTwoTensor::Identity());
75 
76  // PK2 update (constitutive). This populates `_S` (always needed) and `_C` (= dPK2/dE,
77  // Jacobian-only). PK2-subclass implementers that want to skip `_C` on residual sweeps
78  // can check `_fe_problem.currentlyComputingJacobian()` themselves; the wrap below
79  // doesn't read `_C` in the residual path.
81 
82  const bool need_jacobian = _fe_problem.currentlyComputingJacobian() ||
84 
85  // PK2 -> PK1 wrap uses the *unstabilized* F so the residual matches OLD. The constitutive
86  // PK2 still carries the F-bar effect via its dependence on E (Green-Lagrange of F_stab).
88  {
89  _pk1_stress[_qp] = _F_ust[_qp] * _S[_qp];
90  if (!need_jacobian)
91  return;
92 
93  usingTensorIndices(i_, j_, k_, l_);
94  // dE/d(F_stab) (E is computed from F_stab).
95  RankFourTensor dE_dFstab =
96  0.5 * (RankTwoTensor::Identity().times<i_, l_, j_, k_>(_F[_qp].transpose()) +
97  _F[_qp].transpose().times<i_, k_, j_, l_>(RankTwoTensor::Identity()));
98  // Chain dE/d(F_ust) = dE/d(F_stab) * d(F_stab)/d(F_ust). With F-bar off
99  // _d_F_stab_d_F_ust = IdentityFour and this collapses to dE_dFstab.
100  const RankFourTensor dE_dFust = dE_dFstab * _d_F_stab_d_F_ust[_qp];
101 
102  // dPK1/d(F_ust) = d(F_ust)/d(F_ust) * S + F_ust * dS/d(F_ust)
103  // d(F_ust)/d(F_ust)*S gives I x S^T (per the existing template, with S^T because
104  // PK1 = F*S and we differentiate F).
105  // F_ust * dS/d(F_ust) via dS/dE * dE/d(F_ust).
106  const RankFourTensor termA =
107  RankTwoTensor::Identity().times<i_, k_, j_, l_>(_S[_qp].transpose());
108  _pk1_jacobian[_qp] = termA + (_C[_qp] * dE_dFust).singleProductI(_F_ust[_qp]);
109  // Bypass-F-bar variant: same Term A; sigma chain uses dE_dFstab (without
110  // _d_F_stab_d_F_ust). Used by specialty kernels whose coupled variable bypasses
111  // F-bar.
112  _pk1_jacobian_bypass_fbar[_qp] = termA + (_C[_qp] * dE_dFstab).singleProductI(_F_ust[_qp]);
113  }
114  // Small deformations: PK1 = PK2 = sigma; PK2 chain to PK1 still needs the F-bar local
115  // contribution through dE/d(F_stab) * d(F_stab)/d(F_ust). For specialty bypass paths,
116  // skip the F-bar factor.
117  else
118  {
119  _pk1_stress[_qp] = _S[_qp];
120  if (!need_jacobian)
121  return;
124  }
125 }
const MaterialProperty< RankTwoTensor > & _F
F-bar-stabilized deformation gradient (= the strain calc&#39;s published _F).
Native interface for providing the 1st Piola Kirchhoff stress.
RankFourTensorTempl< T > singleProductJ(const RankTwoTensorTempl< T > &) const
const MaterialProperty< RankFourTensor > & _d_F_stab_d_F_ust
d(F_stab)/d(F_ust).
FEProblemBase & _fe_problem
virtual void computeQpPK2Stress()=0
Provide the PK2 stress and dPK2/dC.
ComputeLagrangianStressPK2(const InputParameters &parameters)
static InputParameters validParams()
virtual void computeQpPK1Stress() override
Wrap PK2 -> PK1.
static InputParameters validParams()
bool _large_kinematics
If true use large deformations.
const MaterialProperty< RankTwoTensor > & _F_ust
Unstabilized deformation gradient (= F_actual at alpha = 1).
MaterialProperty< RankTwoTensor > & _pk1_stress
The 1st Piola-Kirchhoff stress.
const bool & currentlyComputingResidualAndJacobian() const
static RankTwoTensorTempl Identity()
unsigned int _qp
MaterialProperty< RankFourTensor > & _pk1_jacobian
The derivative of the 1st PK stress wrt the deformation gradient (F that the stress material consumes...
MaterialProperty< RankFourTensor > & _pk1_jacobian_bypass_fbar
Variant of _pk1_jacobian computed WITHOUT the F-bar chain factor _d_F_stab_d_F_ust in the sigma-via-d...
const MaterialProperty< RankFourTensor > & _d_deformation_gradient_increment_d_F
d(spatial velocity gradient increment)/d(F_stab).
MaterialProperty< RankTwoTensor > & _cauchy_stress
The Cauchy stress.
MaterialProperty< RankTwoTensor > & _E
Green-Lagrange strain.
MaterialProperty< RankFourTensor > & _C
2nd PK tangent (dS/dF)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
RankFourTensorTempl< T > singleProductI(const RankTwoTensorTempl< T > &) const
RankFourTensorTempl< T > times(const RankTwoTensorTempl< T > &b) const
virtual void computeQpCauchyStress() override
Wrap PK1 -> sigma.
MaterialProperty< RankTwoTensor > & _S
2nd PK stress
const bool & currentlyComputingJacobian() const
MaterialProperty< RankFourTensor > & _cauchy_jacobian
The derivative of the Cauchy stress wrt the increment in the spatial velocity gradient.