https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ComputeLinearElasticPFFractureStress.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#include "MathUtils.h"
12
14
17{
19 params.addClassDescription("Computes the stress and free energy derivatives for the phase field "
20 "fracture model, with small strain");
21 MooseEnum Decomposition("strain_spectral strain_vol_dev stress_spectral none", "none");
22 params.addParam<MooseEnum>("decomposition_type",
23 Decomposition,
24 "Decomposition approaches. Choices are: " +
25 Decomposition.getRawNames());
26 return params;
27}
28
30 const InputParameters & parameters)
31 : ComputePFFractureStressBase(parameters),
33 _decomposition_type(getParam<MooseEnum>("decomposition_type").getEnum<Decomposition_type>())
34{
35}
36
37void
39{
43 mooseError("Decomposition approach of strain_vol_dev and strain_spectral can only be used with "
44 "isotropic elasticity tensor materials, use stress_spectral for anistropic "
45 "elasticity tensor materials");
46}
47
48void
50{
51 // Isotropic elasticity is assumed and should be enforced
52 const Real lambda = _elasticity_tensor[_qp](0, 0, 1, 1);
53 const Real mu = _elasticity_tensor[_qp](0, 1, 0, 1);
54
56
57 // Compute eigenvectors and eigenvalues of mechanical strain and projection tensor
58 RankTwoTensor eigvec;
59 std::vector<Real> eigval(LIBMESH_DIM);
60 RankFourTensor Ppos =
61 _mechanical_strain[_qp].positiveProjectionEigenDecomposition(eigval, eigvec);
63
64 // Calculate tensors of outerproduct of eigen vectors
65 std::vector<RankTwoTensor> etens(LIBMESH_DIM);
66
67 for (const auto i : make_range(Moose::dim))
68 etens[i] = RankTwoTensor::selfOuterProduct(eigvec.column(i));
69
70 // Separate out positive and negative eigen values
71 std::vector<Real> epos(LIBMESH_DIM), eneg(LIBMESH_DIM);
72 for (const auto i : make_range(Moose::dim))
73 {
74 epos[i] = (std::abs(eigval[i]) + eigval[i]) / 2.0;
75 eneg[i] = -(std::abs(eigval[i]) - eigval[i]) / 2.0;
76 }
77
78 // Seprate positive and negative sums of all eigenvalues
79 Real etr = 0.0;
80 for (const auto i : make_range(Moose::dim))
81 etr += eigval[i];
82
83 const Real etrpos = (std::abs(etr) + etr) / 2.0;
84 const Real etrneg = -(std::abs(etr) - etr) / 2.0;
85
86 // Calculate the tensile (postive) and compressive (negative) parts of stress
87 RankTwoTensor stress0pos, stress0neg;
88 for (const auto i : make_range(Moose::dim))
89 {
90 stress0pos += etens[i] * (lambda * etrpos + 2.0 * mu * epos[i]);
91 stress0neg += etens[i] * (lambda * etrneg + 2.0 * mu * eneg[i]);
92 }
93
94 // sum squares of epos and eneg
95 Real pval(0.0), nval(0.0);
96 for (const auto i : make_range(Moose::dim))
97 {
98 pval += epos[i] * epos[i];
99 nval += eneg[i] * eneg[i];
100 }
101
102 _stress[_qp] = stress0pos * _D[_qp] - _pressure[_qp] * I2 * _I[_qp] + stress0neg;
103
104 // Energy with positive principal strains
105 F_pos = lambda * etrpos * etrpos / 2.0 + mu * pval;
106 F_neg = -lambda * etrneg * etrneg / 2.0 + mu * nval;
107
108 // 2nd derivative wrt c and strain = 0.0 if we used the previous step's history varible
110 _d2Fdcdstrain[_qp] = stress0pos * _dDdc[_qp];
111
112 // Used in StressDivergencePFFracTensors off-diagonal Jacobian
113 _dstress_dc[_qp] = stress0pos * _dDdc[_qp] - _pressure[_qp] * I2 * _dIdc[_qp];
114
115 _Jacobian_mult[_qp] = (I4sym - (1 - _D[_qp]) * Ppos) * _elasticity_tensor[_qp];
116}
117
118void
120{
121 // Compute Uncracked stress
123
125
126 // Create the positive and negative projection tensors
128 std::vector<Real> eigval;
129 RankTwoTensor eigvec;
130 RankFourTensor Ppos = stress.positiveProjectionEigenDecomposition(eigval, eigvec);
131
132 // Project the positive and negative stresses
133 RankTwoTensor stress0pos = Ppos * stress;
134 RankTwoTensor stress0neg = stress - stress0pos;
135
136 // Compute the positive and negative elastic energies
137 F_pos = (stress0pos).doubleContraction(_mechanical_strain[_qp]) / 2.0;
138 F_neg = (stress0neg).doubleContraction(_mechanical_strain[_qp]) / 2.0;
139
140 _stress[_qp] = stress0pos * _D[_qp] - _pressure[_qp] * I2 * _I[_qp] + stress0neg;
141
142 // 2nd derivative wrt c and strain = 0.0 if we used the previous step's history varible
144 _d2Fdcdstrain[_qp] = stress0pos * _dDdc[_qp];
145
146 // Used in StressDivergencePFFracTensors off-diagonal Jacobian
147 _dstress_dc[_qp] = stress0pos * _dDdc[_qp] - _pressure[_qp] * I2 * _dIdc[_qp];
148
149 _Jacobian_mult[_qp] = (I4sym - (1 - _D[_qp]) * Ppos) * _elasticity_tensor[_qp];
150}
151
152void
154{
155 // Isotropic elasticity is assumed and should be enforced
156 const Real lambda = _elasticity_tensor[_qp](0, 0, 1, 1);
157 const Real mu = _elasticity_tensor[_qp](0, 1, 0, 1);
158 const Real k = lambda + 2.0 * mu / LIBMESH_DIM;
159
161 RankFourTensor I2I2 = I2.outerProduct(I2);
162
163 RankFourTensor Jacobian_pos, Jacobian_neg;
164 RankTwoTensor strain0vol, strain0dev;
165 RankTwoTensor stress0pos, stress0neg;
166 Real strain0tr, strain0tr_neg, strain0tr_pos;
167
168 strain0dev = _mechanical_strain[_qp].deviatoric();
169 strain0vol = _mechanical_strain[_qp] - strain0dev;
170 strain0tr = _mechanical_strain[_qp].trace();
171 strain0tr_neg = std::min(strain0tr, 0.0);
172 strain0tr_pos = strain0tr - strain0tr_neg;
173 stress0neg = k * strain0tr_neg * I2;
174 stress0pos = _elasticity_tensor[_qp] * _mechanical_strain[_qp] - stress0neg;
175 // Energy with positive principal strains
176 RankTwoTensor strain0dev2 = strain0dev * strain0dev;
177 F_pos = 0.5 * k * strain0tr_pos * strain0tr_pos + mu * strain0dev2.trace();
178 F_neg = 0.5 * k * strain0tr_neg * strain0tr_neg;
179
180 _stress[_qp] = stress0pos * _D[_qp] - _pressure[_qp] * I2 * _I[_qp] + stress0neg;
181
182 // 2nd derivative wrt c and strain = 0.0 if we used the previous step's history varible
184 _d2Fdcdstrain[_qp] = stress0pos * _dDdc[_qp];
185
186 // Used in StressDivergencePFFracTensors off-diagonal Jacobian
187 _dstress_dc[_qp] = stress0pos * _dDdc[_qp] - _pressure[_qp] * I2 * _dIdc[_qp];
188
189 if (strain0tr < 0)
190 Jacobian_neg = k * I2I2;
191 Jacobian_pos = _elasticity_tensor[_qp] - Jacobian_neg;
192 _Jacobian_mult[_qp] = _D[_qp] * Jacobian_pos + Jacobian_neg;
193}
194
195void
197{
198 Real F_pos, F_neg;
200
201 switch (_decomposition_type)
202 {
204 computeStrainSpectral(F_pos, F_neg);
205 break;
207 computeStrainVolDev(F_pos, F_neg);
208 break;
210 computeStressSpectral(F_pos, F_neg);
211 break;
212 default:
213 {
215 F_pos = stress.doubleContraction(_mechanical_strain[_qp]) / 2.0;
216 F_neg = 0.0;
218 _d2Fdcdstrain[_qp] = stress * _dDdc[_qp];
219
220 _stress[_qp] = _D[_qp] * stress - _pressure[_qp] * I2 * _I[_qp];
221 _dstress_dc[_qp] = stress * _dDdc[_qp] - _pressure[_qp] * I2 * _dIdc[_qp];
222 _Jacobian_mult[_qp] = _D[_qp] * _elasticity_tensor[_qp];
223 }
224 }
225
226 // // Assign history variable
227 Real hist_variable = _H_old[_qp];
229 {
230 _H[_qp] = F_pos;
231
233 hist_variable = _H[_qp];
234 }
235 else
236 {
237 if (F_pos > _H_old[_qp])
238 _H[_qp] = F_pos;
239 else
240 _H[_qp] = _H_old[_qp];
241
243 hist_variable = _H[_qp];
244
245 if (hist_variable < _barrier[_qp])
246 hist_variable = _barrier[_qp];
247 }
248
249 // Elastic free energy density
250 _E[_qp] =
251 hist_variable * _D[_qp] + F_neg - _pressure[_qp] * _mechanical_strain[_qp].trace() * _I[_qp];
252 _dEdc[_qp] =
253 hist_variable * _dDdc[_qp] - _pressure[_qp] * _mechanical_strain[_qp].trace() * _dIdc[_qp];
254 _d2Ed2c[_qp] = hist_variable * _d2Dd2c[_qp] -
255 _pressure[_qp] * _mechanical_strain[_qp].trace() * _d2Id2c[_qp];
256}
registerMooseObject("SolidMechanicsApp", ComputeLinearElasticPFFractureStress)
const double mu
void mooseError(Args &&... args)
const MaterialProperty< RankTwoTensor > & _mechanical_strain
Mechanical strain material property.
MaterialProperty< RankFourTensor > & _Jacobian_mult
derivative of stress w.r.t. strain (_dstress_dstrain)
MaterialProperty< RankTwoTensor > & _stress
Stress material property.
Phase-field fracture This class computes the stress and energy contribution for the small strain Line...
void computeStrainVolDev(Real &F_pos, Real &F_neg)
Method to split elastic energy based on strain volumetric/deviatoric decomposition.
ComputeLinearElasticPFFractureStress(const InputParameters &parameters)
enum ComputeLinearElasticPFFractureStress::Decomposition_type _decomposition_type
virtual void computeQpStress() override
Compute the stress and store it in the _stress material property for the current quadrature point.
void computeStressSpectral(Real &F_pos, Real &F_neg)
Method to split elastic energy based on stress spectral decomposition.
void computeStrainSpectral(Real &F_pos, Real &F_neg)
Method to split elastic energy based on strain spectral decomposition.
ComputePFFractureStressBase is the base class for stress in phase field fracture model.
MaterialProperty< Real > & _H
History variable that prevents crack healing, declared in this material.
MaterialProperty< Real > & _E
Material property for elastic energy.
const MaterialProperty< Real > & _dDdc
Derivative of degradation function w.r.t damage variable.
const MaterialProperty< Real > & _d2Dd2c
Second-order derivative of degradation w.r.t damage variable.
const MaterialProperty< Real > & _D
Material property for energetic degradation function.
const MaterialProperty< Real > & _H_old
Old value of history variable.
MaterialProperty< RankTwoTensor > & _d2Fdcdstrain
Second-order derivative of elastic energy w.r.t damage variable and strain.
const MaterialProperty< Real > & _pressure
Material property defining pressure, declared elsewhere.
const MaterialProperty< Real > & _dIdc
Derivative of damage indicator function w.r.t damage variable.
const MaterialProperty< RankFourTensor > & _elasticity_tensor
Elasticity tensor material property.
const MaterialProperty< Real > & _barrier
material property for fracture energy barrier
bool _use_snes_vi_solver
Use PETSc's VI (Reduced space active set solvers for variational inequalities based on Newton's metho...
const MaterialProperty< Real > & _d2Id2c
Second-order derivative of damage indicator function w.r.t damage variable.
bool _use_current_hist
Use current value of history variable.
MaterialProperty< Real > & _d2Ed2c
Second-order derivative of elastic energy w.r.t damage variable.
MaterialProperty< RankTwoTensor > & _dstress_dc
Derivative of stress w.r.t damage variable.
MaterialProperty< Real > & _dEdc
Derivative of elastic energy w.r.t damage variable.
const MaterialProperty< Real > & _I
Material property for damage indicator function.
const std::string _elasticity_tensor_name
Name of the elasticity tensor material property.
Add-on class that provides the functionality to check if guarantees for material properties are provi...
bool hasGuaranteedMaterialProperty(const MaterialPropertyName &prop, Guarantee guarantee)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
std::string getRawNames() const
static RankTwoTensorTempl< T > selfOuterProduct(const libMesh::TypeVector< T > &)
T doubleContraction(const RankTwoTensorTempl< T > &a) const
RankFourTensorTempl< T > outerProduct(const RankTwoTensorTempl< T > &b) const
RankFourTensorTempl< T > positiveProjectionEigenDecomposition(std::vector< T > &, RankTwoTensorTempl< T > &) const
libMesh::VectorValue< T > column(const unsigned int i) const
RankTwoTensorTempl< T > deviatoric() const
static constexpr std::size_t dim