https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ComputeFiniteStrain.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
10#include "ComputeFiniteStrain.h"
11#include "Assembly.h"
12
13#include "libmesh/quadrature.h"
14#include "libmesh/utility.h"
15
18{
19 return MooseEnum(getDecompMethodOptions(), "TaylorExpansion");
20}
21
23
26{
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
46void
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
114 }
115}
116
117void
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)
132 _strain_rate[_qp] = _strain_increment[_qp] / _dt;
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] *
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 {
154 _mechanical_strain[_qp] =
156 _total_strain[_qp] =
157 _rotation_increment[_qp] * _total_strain[_qp] * _rotation_increment[_qp].transpose();
158 }
159
160 if (_global_strain)
161 _total_strain[_qp] += (*_global_strain)[_qp];
162}
163
164void
166 RankTwoTensor & rotation_increment)
167{
168 switch (_decomposition_method)
169 {
170 case DecompMethod::TaylorExpansion:
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
249 case DecompMethod::EigenSolution:
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
258 case DecompMethod::HughesWinget:
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}
registerMooseObject("SolidMechanicsApp", ComputeFiniteStrain)
const Real p
void mooseError(Args &&... args)
ComputeFiniteStrain defines a strain increment and rotation increment, for finite strains.
static InputParameters validParams()
const bool _use_hw
Flag if using HughesWinget method.
static MooseEnum decompositionType()
ComputeFiniteStrain(const InputParameters &parameters)
const DecompMethod _decomposition_method
Method for determining rotation and strain increments.
virtual void computeQpStrain()
void computeProperties() override
std::vector< RankTwoTensor > _Fhat
Incremental deformation gradient.
virtual void computeQpIncrements(RankTwoTensor &e, RankTwoTensor &r)
ComputeIncrementalStrainBase is the base class for strain tensors using incremental formulations.
MaterialProperty< RankTwoTensor > & _strain_rate
std::vector< const VariableGradient * > _grad_disp_old
const MaterialProperty< RankTwoTensor > & _mechanical_strain_old
void subtractEigenstrainIncrementFromStrain(RankTwoTensor &strain)
MaterialProperty< RankTwoTensor > & _rotation_increment
MaterialProperty< RankTwoTensor > & _strain_increment
MaterialProperty< RankTwoTensor > & _deformation_gradient
const MaterialProperty< RankTwoTensor > & _total_strain_old
std::vector< const VariableGradient * > _grad_disp
Gradient of displacements.
MaterialProperty< RankTwoTensor > & _mechanical_strain
const Real & _current_elem_volume
const MaterialProperty< RankTwoTensor > *const _global_strain
MaterialProperty< RankTwoTensor > & _total_strain
const bool _volumetric_locking_correction
FactorizedRankTwoTensorTempl< T > inverse() const
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)
static RankTwoTensorTempl initializeFromRows(const libMesh::TypeVector< T > &row0, const libMesh::TypeVector< T > &row1, const libMesh::TypeVector< T > &row2)
void addIa(const T &a)
RankTwoTensorTempl< T > inverse() const
RankTwoTensorTempl< T > transpose() const
static RankTwoTensorTempl< T > transposeTimes(const RankTwoTensorTempl< T > &)