12 #include "libmesh/quadrature.h"
13 #include "libmesh/utility.h"
19 template <ComputeStage compute_stage>
23 return MooseEnum(
"TaylorExpansion EigenSolution",
"TaylorExpansion");
26 template <ComputeStage compute_stage>
31 params.addClassDescription(
32 "Compute a strain increment and rotation increment for finite strains.");
33 params.addParam<MooseEnum>(
"decomposition_method",
35 "Methods to calculate the strain and rotation increments");
39 template <ComputeStage compute_stage>
42 _Fhat(_fe_problem.getMaxQps()),
43 _decomposition_method(
44 getParam<MooseEnum>(
"decomposition_method").template getEnum<
DecompMethod>())
48 template <ComputeStage compute_stage>
52 ADRankTwoTensor ave_Fhat;
53 for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
56 ADRankTwoTensor A((*_grad_disp[0])[_qp], (*_grad_disp[1])[_qp], (*_grad_disp[2])[_qp]);
60 (*_grad_disp_old[0])[_qp], (*_grad_disp_old[1])[_qp], (*_grad_disp_old[2])[_qp]);
69 _Fhat[_qp] = A * Fbar.inverse();
70 _Fhat[_qp].addIa(1.0);
73 if (_volumetric_locking_correction)
74 ave_Fhat += _Fhat[_qp] * _JxW[_qp] * _coord[_qp];
77 if (_volumetric_locking_correction)
78 ave_Fhat /= _current_elem_volume;
80 for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
83 if (_volumetric_locking_correction)
85 _Fhat[_qp] *=
std::pow(ave_Fhat.det() / _Fhat[_qp].det(), 1.0 / 3.0);
90 copyDualNumbersToValues();
93 template <ComputeStage compute_stage>
97 ADRankTwoTensor total_strain_increment;
100 computeQpIncrements(total_strain_increment, _rotation_increment[_qp]);
102 _strain_increment[_qp] = total_strain_increment;
105 subtractEigenstrainIncrementFromStrain(_strain_increment[_qp]);
108 _strain_rate[_qp] = _strain_increment[_qp] / _dt;
110 _strain_rate[_qp].zero();
113 _mechanical_strain[_qp] = _mechanical_strain_old[_qp] + _strain_increment[_qp];
114 _total_strain[_qp] = _total_strain_old[_qp] + total_strain_increment;
117 _mechanical_strain[_qp] =
118 _rotation_increment[_qp] * _mechanical_strain[_qp] * _rotation_increment[_qp].transpose();
120 _rotation_increment[_qp] * _total_strain[_qp] * _rotation_increment[_qp].transpose();
123 _total_strain[_qp] += (*_global_strain)[_qp];
126 template <ComputeStage compute_stage>
129 ADRankTwoTensor & rotation_increment)
131 switch (_decomposition_method)
133 case DecompMethod::TaylorExpansion:
136 const ADRankTwoTensor invFhat = _Fhat[_qp].inverse();
139 ADRankTwoTensor A(RankTwoTensorType<compute_stage>::type::initIdentity);
143 ADRankTwoTensor Cinv_I = A * A.transpose() - A - A.transpose();
146 total_strain_increment = -Cinv_I * 0.5 + Cinv_I * Cinv_I * 0.25;
148 const ADReal a[3] = {invFhat(1, 2) - invFhat(2, 1),
149 invFhat(2, 0) - invFhat(0, 2),
150 invFhat(0, 1) - invFhat(1, 0)};
152 const auto q = (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]) / 4.0;
153 const auto trFhatinv_1 = invFhat.trace() - 1.0;
154 const auto p = trFhatinv_1 * trFhatinv_1 / 4.0;
157 const ADReal C1_squared =
158 p + 3.0 * Utility::pow<2>(p) * (1.0 - (p + q)) / Utility::pow<2>(p + q) -
159 2.0 * Utility::pow<3>(p) * (1.0 - (p + q)) / Utility::pow<3>(p + q);
160 mooseAssert(C1_squared >= 0.0,
161 "Cannot take square root of a negative number. This may happen when elements "
162 "become heavily distorted.");
163 const ADReal C1 = std::sqrt(C1_squared);
168 C2 = (1.0 - C1) / (4.0 * q);
171 C2 = 0.125 + q * 0.03125 * (Utility::pow<2>(p) - 12.0 * (p - 1.0)) / Utility::pow<2>(p) +
172 Utility::pow<2>(q) * (p - 2.0) * (Utility::pow<2>(p) - 10.0 * p + 32.0) /
175 (1104.0 - 992.0 * p + 376.0 * Utility::pow<2>(p) - 72.0 * Utility::pow<3>(p) +
176 5.0 * Utility::pow<4>(p)) /
177 (512.0 * Utility::pow<4>(p));
179 const ADReal C3_test =
180 (p * q * (3.0 - q) + Utility::pow<3>(p) + Utility::pow<2>(q)) / Utility::pow<3>(p + q);
181 mooseAssert(C3_test >= 0.0,
182 "Cannot take square root of a negative number. This may happen when elements "
183 "become heavily distorted.");
184 const ADReal C3 = 0.5 * std::sqrt(C3_test);
188 ADRankTwoTensor R_incr;
190 for (
unsigned int i = 0; i < 3; ++i)
191 for (
unsigned int j = 0; j < 3; ++j)
192 R_incr(i, j) += C2 * a[i] * a[j];
194 R_incr(0, 1) += C3 * a[2];
195 R_incr(0, 2) -= C3 * a[1];
196 R_incr(1, 0) -= C3 * a[2];
197 R_incr(1, 2) += C3 * a[0];
198 R_incr(2, 0) += C3 * a[1];
199 R_incr(2, 1) -= C3 * a[0];
201 rotation_increment = R_incr.transpose();
205 case DecompMethod::EigenSolution:
207 std::vector<ADReal> e_value(3);
208 ADRankTwoTensor e_vector, N1, N2, N3;
210 const auto Chat = _Fhat[_qp].transpose() * _Fhat[_qp];
211 Chat.symmetricEigenvaluesEigenvectors(e_value, e_vector);
213 const auto lambda1 = std::sqrt(e_value[0]);
214 const auto lambda2 = std::sqrt(e_value[1]);
215 const auto lambda3 = std::sqrt(e_value[2]);
217 N1.vectorOuterProduct(e_vector.column(0), e_vector.column(0));
218 N2.vectorOuterProduct(e_vector.column(1), e_vector.column(1));
219 N3.vectorOuterProduct(e_vector.column(2), e_vector.column(2));
221 const auto Uhat = N1 * lambda1 + N2 * lambda2 + N3 * lambda3;
222 const ADRankTwoTensor invUhat(Uhat.inverse());
224 rotation_increment = _Fhat[_qp] * invUhat;
226 total_strain_increment =
227 N1 * std::log(lambda1) + N2 * std::log(lambda2) + N3 * std::log(lambda3);
232 mooseError(
"ADComputeFiniteStrain Error: Pass valid decomposition type: TaylorExpansion or "