https://mooseframework.inl.gov
ComputeFiniteStrainNOSPD.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 
12 #include "libmesh/utility.h"
13 
15 
18 {
19  return MooseEnum("TaylorExpansion EigenSolution", "TaylorExpansion");
20 }
21 
24 {
26  params.addClassDescription(
27  "Class for computing nodal quantities for residual and jacobian calculation "
28  "for peridynamic correspondence models under finite strain assumptions");
29 
30  params.addParam<MooseEnum>("decomposition_method",
32  "Methods to calculate the strain and rotation increments");
33 
34  return params;
35 }
36 
38  : ComputeStrainBaseNOSPD(parameters),
39  _strain_rate(declareProperty<RankTwoTensor>("strain_rate")),
40  _strain_increment(declareProperty<RankTwoTensor>("strain_increment")),
41  _rotation_increment(declareProperty<RankTwoTensor>("rotation_increment")),
42  _deformation_gradient_old(getMaterialPropertyOld<RankTwoTensor>("deformation_gradient")),
43  _mechanical_strain_old(getMaterialPropertyOld<RankTwoTensor>("mechanical_strain")),
44  _total_strain_old(getMaterialPropertyOld<RankTwoTensor>("total_strain")),
45  _eigenstrains_old(_eigenstrain_names.size()),
46  _Fhat(2),
47  _decomposition_method(getParam<MooseEnum>("decomposition_method").getEnum<DecompMethod>())
48 {
49  for (unsigned int i = 0; i < _eigenstrains_old.size(); ++i)
50  _eigenstrains_old[i] = &getMaterialPropertyOld<RankTwoTensor>(_eigenstrain_names[i]);
51 }
52 
53 void
55 {
57 
58  computeQpFhat();
59 
60  RankTwoTensor total_strain_increment;
61 
62  // Two ways to calculate these increments: TaylorExpansion(default) or EigenSolution
63  computeQpStrainRotationIncrements(total_strain_increment, _rotation_increment[_qp]);
64 
65  _strain_increment[_qp] = total_strain_increment;
66 
67  // Remove the eigenstrain increment
69 
70  if (_dt > 0)
71  _strain_rate[_qp] = _strain_increment[_qp] / _dt;
72  else
73  _strain_rate[_qp].zero();
74 
75  // Update strain in intermediate configuration
77  _total_strain[_qp] = _total_strain_old[_qp] + total_strain_increment;
78 
79  // Rotate strain to current configuration
80  _mechanical_strain[_qp] =
81  _rotation_increment[_qp] * _mechanical_strain[_qp] * _rotation_increment[_qp].transpose();
82  _total_strain[_qp] =
83  _rotation_increment[_qp] * _total_strain[_qp] * _rotation_increment[_qp].transpose();
84 
85  // zero out all strain measures for broken bond
86  if (_bond_status_var->getElementalValue(_current_elem) < 0.5)
87  {
88  _strain_rate[_qp].zero();
89  _strain_increment[_qp].zero();
90  _rotation_increment[_qp].zero();
91  _mechanical_strain[_qp].zero();
92  _total_strain[_qp].zero();
93  }
94 }
95 
96 void
98 {
99  // Incremental deformation gradient of current step w.r.t previous step:
100  // _Fhat = deformation_gradient * inv(deformation_gradient_old)
101  _Fhat[_qp] = _deformation_gradient[_qp] * _deformation_gradient_old[_qp].inverse();
102 }
103 
104 void
106  RankTwoTensor & rotation_increment)
107 {
108  switch (_decomposition_method)
109  {
111  {
112  // inverse of _Fhat
113  RankTwoTensor invFhat(_Fhat[_qp].inverse());
114 
115  // A = I - _Fhat^-1
117  A -= invFhat;
118 
119  // Cinv - I = A A^T - A - A^T;
120  RankTwoTensor Cinv_I = A * A.transpose() - A - A.transpose();
121 
122  // strain rate D from Taylor expansion, Chat = (-1/2(Chat^-1 - I) + 1/4*(Chat^-1 - I)^2 + ...
123  total_strain_increment = -Cinv_I * 0.5 + Cinv_I * Cinv_I * 0.25;
124 
125  const Real a[3] = {invFhat(1, 2) - invFhat(2, 1),
126  invFhat(2, 0) - invFhat(0, 2),
127  invFhat(0, 1) - invFhat(1, 0)};
128 
129  Real q = (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]) / 4.0;
130  Real trFhatinv_1 = invFhat.trace() - 1.0;
131  const Real p = trFhatinv_1 * trFhatinv_1 / 4.0;
132 
133  // cos theta_a
134  const Real C1_squared = p +
135  3.0 * Utility::pow<2>(p) * (1.0 - (p + q)) / Utility::pow<2>(p + q) -
136  2.0 * Utility::pow<3>(p) * (1.0 - (p + q)) / Utility::pow<3>(p + q);
137  if (C1_squared <= 0.0)
138  mooseException(
139  "Cannot take square root of a number less than or equal to zero in the calculation of "
140  "C1 for the Rashid approximation for the rotation tensor.");
141 
142  const Real C1 = std::sqrt(C1_squared);
143 
144  Real C2;
145  if (q > 0.01)
146  // (1-cos theta_a)/4q
147  C2 = (1.0 - C1) / (4.0 * q);
148  else
149  // alternate form for small q
150  C2 = 0.125 + q * 0.03125 * (Utility::pow<2>(p) - 12.0 * (p - 1.0)) / Utility::pow<2>(p) +
151  Utility::pow<2>(q) * (p - 2.0) * (Utility::pow<2>(p) - 10.0 * p + 32.0) /
152  Utility::pow<3>(p) +
153  Utility::pow<3>(q) *
154  (1104.0 - 992.0 * p + 376.0 * Utility::pow<2>(p) - 72.0 * Utility::pow<3>(p) +
155  5.0 * Utility::pow<4>(p)) /
156  (512.0 * Utility::pow<4>(p));
157 
158  const Real C3_test =
159  (p * q * (3.0 - q) + Utility::pow<3>(p) + Utility::pow<2>(q)) / Utility::pow<3>(p + q);
160 
161  if (C3_test <= 0.0)
162  mooseException(
163  "Cannot take square root of a number less than or equal to zero in the calculation of "
164  "C3_test for the Rashid approximation for the rotation tensor.");
165 
166  const Real C3 = 0.5 * std::sqrt(C3_test); // sin theta_a/(2 sqrt(q))
167 
168  // Calculate incremental rotation. Note that this value is the transpose of that from Rashid,
169  // 93, so we transpose it before storing
170  RankTwoTensor R_incr;
171  R_incr.addIa(C1);
172  for (unsigned int i = 0; i < 3; ++i)
173  for (unsigned int j = 0; j < 3; ++j)
174  R_incr(i, j) += C2 * a[i] * a[j];
175 
176  R_incr(0, 1) += C3 * a[2];
177  R_incr(0, 2) -= C3 * a[1];
178  R_incr(1, 0) -= C3 * a[2];
179  R_incr(1, 2) += C3 * a[0];
180  R_incr(2, 0) += C3 * a[1];
181  R_incr(2, 1) -= C3 * a[0];
182 
183  rotation_increment = R_incr.transpose();
184  break;
185  }
187  {
189  FactorizedRankTwoTensor Uhat = MathUtils::sqrt(Chat);
190  rotation_increment = _Fhat[_qp] * Uhat.inverse().get();
191  total_strain_increment = MathUtils::log(Uhat).get();
192  break;
193  }
194 
195  default:
196  mooseError("ComputeFiniteStrainNOSPD Error: Invalid decomposition type! Please specify : "
197  "TaylorExpansion or "
198  "EigenSolution.");
199  }
200 }
201 
202 void
204 {
205  for (unsigned int i = 0; i < _eigenstrains.size(); ++i)
206  {
207  strain -= (*_eigenstrains[i])[_qp];
208  strain += (*_eigenstrains_old[i])[_qp];
209  }
210 }
void computeQpStrainRotationIncrements(RankTwoTensor &e, RankTwoTensor &r)
Function to compute strain and rotational increments.
Material class for peridynamic correspondence model for finite strain.
virtual void computeQpStrain() override
Function to compute strain tensors.
virtual void computeQpDeformationGradient()
Function to compute deformation gradient for peridynamic correspondence model.
MaterialProperty< RankTwoTensor > & _deformation_gradient
const MaterialProperty< RankTwoTensor > & _total_strain_old
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void mooseError(Args &&... args)
MaterialProperty< RankTwoTensor > & _strain_increment
ComputeFiniteStrainNOSPD(const InputParameters &parameters)
const DecompMethod _decomposition_method
void inverse(const std::vector< std::vector< Real >> &m, std::vector< std::vector< Real >> &m_inv)
static InputParameters validParams()
void subtractEigenstrainIncrementFromStrain(RankTwoTensor &strain)
Function to compute the mechanical strain tensor by subtracting thermal strain from the total strain...
std::vector< RankTwoTensor > _Fhat
&#39;Incremental&#39; deformation gradient
static InputParameters validParams()
Base material class for correspondence material model.
void addIa(const Real &a)
const MaterialProperty< RankTwoTensor > & _mechanical_strain_old
std::vector< const MaterialProperty< RankTwoTensor > * > _eigenstrains
static RankTwoTensorTempl< Real > transposeTimes(const RankTwoTensorTempl< Real > &)
RankTwoTensorTempl< Real > transpose() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const MaterialProperty< RankTwoTensor > & _deformation_gradient_old
Material properties to fetch.
std::vector< MaterialPropertyName > _eigenstrain_names
MaterialProperty< RankTwoTensor > & _strain_rate
Material properties to store.
std::vector< const MaterialProperty< RankTwoTensor > * > _eigenstrains_old
void addClassDescription(const std::string &doc_string)
MaterialProperty< RankTwoTensor > & _rotation_increment
MaterialProperty< RankTwoTensor > & _total_strain
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static MooseEnum decompositionType()
DecompMethod
Method to decompose into rotation increment and strain increment.
FactorizedRankTwoTensorTempl< T > inverse() const
registerMooseObject("PeridynamicsApp", ComputeFiniteStrainNOSPD)
MaterialProperty< RankTwoTensor > & _mechanical_strain