www.mooseframework.org
ComputeFiniteStrain.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 
10 #include "ComputeFiniteStrain.h"
11 #include "Assembly.h"
12 
13 #include "libmesh/quadrature.h"
14 #include "libmesh/utility.h"
15 
18 {
19  return MooseEnum("TaylorExpansion EigenSolution HughesWinget", "TaylorExpansion");
20 }
21 
22 registerMooseObject("SolidMechanicsApp", ComputeFiniteStrain);
23 
26 {
28  params.addClassDescription(
29  "Compute a strain increment and rotation increment for finite strains.");
30  params.addParam<MooseEnum>("decomposition_method",
32  "Methods to calculate the strain and rotation increments");
33  return params;
34 }
35 
37  : ComputeIncrementalStrainBase(parameters),
38  _Fhat(_fe_problem.getMaxQps()),
39  _decomposition_method(getParam<MooseEnum>("decomposition_method").getEnum<DecompMethod>()),
40  _use_hw(_decomposition_method == DecompMethod::HughesWinget),
41  _def_grad_mid(_use_hw ? &declareProperty<RankTwoTensor>(_base_name + "def_grad_mid") : nullptr),
42  _f_bar(_use_hw ? &declareProperty<RankTwoTensor>(_base_name + "f_bar") : nullptr)
43 {
44 }
45 
46 void
48 {
49  RankTwoTensor ave_Fhat;
50  Real ave_dfgrd_det = 0.0;
51  for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
52  {
53  // Deformation gradient
55  (*_grad_disp[0])[_qp], (*_grad_disp[1])[_qp], (*_grad_disp[2])[_qp]);
56 
57  // Old Deformation gradient
59  (*_grad_disp_old[0])[_qp], (*_grad_disp_old[1])[_qp], (*_grad_disp_old[2])[_qp]);
60 
61  // Gauss point deformation gradient
63  _deformation_gradient[_qp].addIa(1.0);
64 
65  // deformation gradient midpoint (for Hughes-Winget kinematics)
66  if (_use_hw)
67  {
68  (*_def_grad_mid)[_qp].setToIdentity();
69  (*_def_grad_mid)[_qp] += 0.5 * (A + Fbar);
70  }
71 
72  // A = gradU - gradUold
73  A -= Fbar;
74 
75  //_f_bar = dDu/Dx_o (for Hughes-Winget kinematics)
76  if (_use_hw)
77  (*_f_bar)[_qp] = A;
78 
79  // Fbar = ( I + gradUold)
80  Fbar.addIa(1.0);
81 
82  // Incremental deformation gradient _Fhat = I + A Fbar^-1
83  _Fhat[_qp] = A * Fbar.inverse();
84  _Fhat[_qp].addIa(1.0);
85 
87  {
88  // Calculate average _Fhat for volumetric locking correction
89  ave_Fhat += _Fhat[_qp] * _JxW[_qp] * _coord[_qp];
90 
91  // Average deformation gradient
92  ave_dfgrd_det += _deformation_gradient[_qp].det() * _JxW[_qp] * _coord[_qp];
93  }
94  }
95 
97  {
98  // needed for volumetric locking correction
99  ave_Fhat /= _current_elem_volume;
100  // average deformation gradient
101  ave_dfgrd_det /= _current_elem_volume;
102  }
103 
104  for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
105  {
107  {
108  // Finalize volumetric locking correction
109  _Fhat[_qp] *= std::cbrt(ave_Fhat.det() / _Fhat[_qp].det());
110  _deformation_gradient[_qp] *= std::cbrt(ave_dfgrd_det / _deformation_gradient[_qp].det());
111  }
112 
113  computeQpStrain();
114  }
115 }
116 
117 void
119 {
120  RankTwoTensor total_strain_increment;
121 
122  // three ways to calculate these increments: TaylorExpansion(default), EigenSolution, or
123  // HughesWinget
124  computeQpIncrements(total_strain_increment, _rotation_increment[_qp]);
125 
126  _strain_increment[_qp] = total_strain_increment;
127 
128  // Remove the eigenstrain increment
130 
131  if (_dt > 0)
133  else
134  _strain_rate[_qp].zero();
135 
136  // if HughesWinget, rotate old strains here
137  RankTwoTensor mechanical_strain_old = _mechanical_strain_old[_qp];
138  RankTwoTensor total_strain_old = _total_strain_old[_qp];
139  if (_use_hw)
140  {
141  mechanical_strain_old = _rotation_increment[_qp] * _mechanical_strain_old[_qp] *
142  _rotation_increment[_qp].transpose();
143  total_strain_old =
145  }
146 
147  // Update strain in intermediate configuration
148  _mechanical_strain[_qp] = mechanical_strain_old + _strain_increment[_qp];
149  _total_strain[_qp] = total_strain_old + total_strain_increment;
150 
151  // Rotate strain to current configuration, unless HughesWinget
152  if (!_use_hw)
153  {
156  _total_strain[_qp] =
158  }
159 
160  if (_global_strain)
161  _total_strain[_qp] += (*_global_strain)[_qp];
162 }
163 
164 void
166  RankTwoTensor & rotation_increment)
167 {
168  switch (_decomposition_method)
169  {
171  {
172  // inverse of _Fhat
173  const RankTwoTensor invFhat = _Fhat[_qp].inverse();
174 
175  // A = I - _Fhat^-1
177  A -= invFhat;
178 
179  // Cinv - I = A A^T - A - A^T;
180  RankTwoTensor Cinv_I = A * A.transpose() - A - A.transpose();
181 
182  // strain rate D from Taylor expansion, Chat = (-1/2(Chat^-1 - I) + 1/4*(Chat^-1 - I)^2 + ...
183  total_strain_increment = -Cinv_I * 0.5 + Cinv_I * Cinv_I * 0.25;
184 
185  const Real a[3] = {invFhat(1, 2) - invFhat(2, 1),
186  invFhat(2, 0) - invFhat(0, 2),
187  invFhat(0, 1) - invFhat(1, 0)};
188 
189  Real q = (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]) / 4.0;
190  Real trFhatinv_1 = invFhat.trace() - 1.0;
191  const Real p = trFhatinv_1 * trFhatinv_1 / 4.0;
192 
193  // cos theta_a
194  const Real C1_squared = p +
195  3.0 * Utility::pow<2>(p) * (1.0 - (p + q)) / Utility::pow<2>(p + q) -
196  2.0 * Utility::pow<3>(p) * (1.0 - (p + q)) / Utility::pow<3>(p + q);
197  if (C1_squared <= 0.0)
198  mooseException(
199  "Cannot take square root of a number less than or equal to zero in the calculation of "
200  "C1 for the Rashid approximation for the rotation tensor. This zero or negative number "
201  "may occur when elements become heavily distorted.");
202 
203  const Real C1 = std::sqrt(C1_squared);
204 
205  Real C2;
206  if (q > 0.01)
207  // (1-cos theta_a)/4q
208  C2 = (1.0 - C1) / (4.0 * q);
209  else
210  // alternate form for small q
211  C2 = 0.125 + q * 0.03125 * (Utility::pow<2>(p) - 12.0 * (p - 1.0)) / Utility::pow<2>(p) +
212  Utility::pow<2>(q) * (p - 2.0) * (Utility::pow<2>(p) - 10.0 * p + 32.0) /
213  Utility::pow<3>(p) +
214  Utility::pow<3>(q) *
215  (1104.0 - 992.0 * p + 376.0 * Utility::pow<2>(p) - 72.0 * Utility::pow<3>(p) +
216  5.0 * Utility::pow<4>(p)) /
217  (512.0 * Utility::pow<4>(p));
218 
219  const Real C3_test =
220  (p * q * (3.0 - q) + Utility::pow<3>(p) + Utility::pow<2>(q)) / Utility::pow<3>(p + q);
221 
222  if (C3_test <= 0.0)
223  mooseException(
224  "Cannot take square root of a number less than or equal to zero in the calculation of "
225  "C3_test for the Rashid approximation for the rotation tensor. This zero or negative "
226  "number may occur when elements become heavily distorted.");
227 
228  const Real C3 = 0.5 * std::sqrt(C3_test); // sin theta_a/(2 sqrt(q))
229 
230  // Calculate incremental rotation. Note that this value is the transpose of that from Rashid,
231  // 93, so we transpose it before storing
232  RankTwoTensor R_incr;
233  R_incr.addIa(C1);
234  for (unsigned int i = 0; i < 3; ++i)
235  for (unsigned int j = 0; j < 3; ++j)
236  R_incr(i, j) += C2 * a[i] * a[j];
237 
238  R_incr(0, 1) += C3 * a[2];
239  R_incr(0, 2) -= C3 * a[1];
240  R_incr(1, 0) -= C3 * a[2];
241  R_incr(1, 2) += C3 * a[0];
242  R_incr(2, 0) += C3 * a[1];
243  R_incr(2, 1) -= C3 * a[0];
244 
245  rotation_increment = R_incr.transpose();
246  break;
247  }
248 
250  {
252  FactorizedRankTwoTensor Uhat = MathUtils::sqrt(Chat);
253  rotation_increment = _Fhat[_qp] * Uhat.inverse().get();
254  total_strain_increment = MathUtils::log(Uhat).get();
255  break;
256  }
257 
259  {
260  const RankTwoTensor G = (*_f_bar)[_qp] * (*_def_grad_mid)[_qp].inverse();
261 
262  total_strain_increment = 0.5 * (G + G.transpose());
263  const RankTwoTensor W = 0.5 * (G - G.transpose());
264 
267 
268  Q_1 -= 0.5 * W;
269  Q_2 += 0.5 * W;
270 
271  rotation_increment = Q_1.inverse() * Q_2;
272 
273  break;
274  }
275 
276  default:
277  mooseError("ComputeFiniteStrain Error: Pass valid decomposition type: TaylorExpansion, "
278  "EigenSolution, or HughesWinget.");
279  }
280 }
static InputParameters validParams()
ComputeFiniteStrain(const InputParameters &parameters)
RankTwoTensorTempl< Real > inverse() const
const Real & _current_elem_volume
const MaterialProperty< RankTwoTensor > & _total_strain_old
MaterialProperty< RankTwoTensor > & _deformation_gradient
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const DecompMethod _decomposition_method
Method for determining rotation and strain increments.
const MooseArray< Real > & _JxW
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
void computeProperties() override
virtual void computeQpStrain()
static const std::string G
Definition: NS.h:151
MaterialProperty< RankTwoTensor > & _strain_increment
static RankTwoTensorTempl initializeFromRows(const libMesh::TypeVector< Real > &row0, const libMesh::TypeVector< Real > &row1, const libMesh::TypeVector< Real > &row2)
const bool _use_hw
Flag if using HughesWinget method.
MaterialProperty< RankTwoTensor > & _mechanical_strain
void addIa(const Real &a)
virtual void computeQpIncrements(RankTwoTensor &e, RankTwoTensor &r)
static MooseEnum decompositionType()
MaterialProperty< RankTwoTensor > & _strain_rate
void subtractEigenstrainIncrementFromStrain(RankTwoTensor &strain)
static RankTwoTensorTempl< Real > transposeTimes(const RankTwoTensorTempl< Real > &)
RankTwoTensorTempl< Real > transpose() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
ComputeFiniteStrain defines a strain increment and rotation increment, for finite strains...
registerMooseObject("SolidMechanicsApp", ComputeFiniteStrain)
const MaterialProperty< RankTwoTensor > & _mechanical_strain_old
std::vector< const VariableGradient * > _grad_disp_old
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
ComputeIncrementalStrainBase is the base class for strain tensors using incremental formulations...
const bool _volumetric_locking_correction
MaterialProperty< RankTwoTensor > & _rotation_increment
const MooseArray< Real > & _coord
const MaterialProperty< RankTwoTensor > *const _global_strain
MaterialProperty< RankTwoTensor > & _total_strain
std::vector< RankTwoTensor > _Fhat
Incremental deformation gradient.
FactorizedRankTwoTensorTempl< T > inverse() const
std::vector< const VariableGradient * > _grad_disp
Gradient of displacements.