www.mooseframework.org
ComputeLinearElasticPFFractureStress.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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),
32  GuaranteeConsumer(this),
33  _decomposition_type(getParam<MooseEnum>("decomposition_type").getEnum<Decomposition_type>())
34 {
35 }
36 
37 void
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 
48 void
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
109  if (_use_current_hist)
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 
118 void
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
143  if (_use_current_hist)
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 
152 void
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
183  if (_use_current_hist)
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 
195 void
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;
217  if (_use_current_hist)
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];
223  }
224  }
225 
226  // // Assign history variable
227  Real hist_variable = _H_old[_qp];
229  {
230  _H[_qp] = F_pos;
231 
232  if (_use_current_hist)
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 
242  if (_use_current_hist)
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] -
256 }
RankFourTensorTempl< Real > outerProduct(const RankTwoTensorTempl< Real > &b) const
MaterialProperty< Real > & _H
History variable that prevents crack healing, declared in this material.
MaterialProperty< RankFourTensor > & _Jacobian_mult
derivative of stress w.r.t. strain (_dstress_dstrain)
const MaterialProperty< Real > & _d2Dd2c
Second-order derivative of degradation w.r.t damage variable.
const MaterialProperty< RankFourTensor > & _elasticity_tensor
Elasticity tensor material property.
MaterialProperty< Real > & _E
Material property for elastic energy.
RankFourTensorTempl< Real > positiveProjectionEigenDecomposition(std::vector< Real > &, RankTwoTensorTempl< Real > &) const
MaterialProperty< Real > & _d2Ed2c
Second-order derivative of elastic energy w.r.t damage variable.
virtual void computeQpStress() override
Compute the stress and store it in the _stress material property for the current quadrature point...
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const MaterialProperty< RankTwoTensor > & _mechanical_strain
Mechanical strain material property.
ComputePFFractureStressBase is the base class for stress in phase field fracture model.
MaterialProperty< RankTwoTensor > & _dstress_dc
Derivative of stress w.r.t damage variable.
const MaterialProperty< Real > & _d2Id2c
Second-order derivative of damage indicator function w.r.t damage variable.
VectorValue< Real > column(const unsigned int i) const
MaterialProperty< RankTwoTensor > & _d2Fdcdstrain
Second-order derivative of elastic energy w.r.t damage variable and strain.
static constexpr std::size_t dim
void computeStrainSpectral(Real &F_pos, Real &F_neg)
Method to split elastic energy based on strain spectral decomposition.
std::string getRawNames() const
const MaterialProperty< Real > & _barrier
material property for fracture energy barrier
static InputParameters validParams()
void computeStressSpectral(Real &F_pos, Real &F_neg)
Method to split elastic energy based on stress spectral decomposition.
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
static RankTwoTensorTempl< Real > selfOuterProduct(const libMesh::TypeVector< Real > &)
enum ComputeLinearElasticPFFractureStress::Decomposition_type _decomposition_type
const MaterialProperty< Real > & _dDdc
Derivative of degradation function w.r.t damage variable.
MaterialProperty< Real > & _dEdc
Derivative of elastic energy w.r.t damage variable.
Phase-field fracture This class computes the stress and energy contribution for the small strain Line...
static const std::string mu
Definition: NS.h:122
ComputeLinearElasticPFFractureStress(const InputParameters &parameters)
bool _use_current_hist
Use current value of history variable.
Real doubleContraction(const RankTwoTensorTempl< Real > &a) const
const MaterialProperty< Real > & _H_old
Old value of history variable.
const std::string _elasticity_tensor_name
Name of the elasticity tensor material property.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
const MaterialProperty< Real > & _I
Material property for damage indicator function.
MaterialProperty< RankTwoTensor > & _stress
Stress material property.
const MaterialProperty< Real > & _pressure
Material property defining pressure, declared elsewhere.
bool hasGuaranteedMaterialProperty(const MaterialPropertyName &prop, Guarantee guarantee)
const MaterialProperty< Real > & _D
Material property for energetic degradation function.
void computeStrainVolDev(Real &F_pos, Real &F_neg)
Method to split elastic energy based on strain volumetric/deviatoric decomposition.
Add-on class that provides the functionality to check if guarantees for material properties are provi...
static const std::string k
Definition: NS.h:124
const MaterialProperty< Real > & _dIdc
Derivative of damage indicator function w.r.t damage variable.
registerMooseObject("SolidMechanicsApp", ComputeLinearElasticPFFractureStress)
bool _use_snes_vi_solver
Use PETSc&#39;s VI (Reduced space active set solvers for variational inequalities based on Newton&#39;s metho...