www.mooseframework.org
InteractionIntegral.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 // This post processor returns the Interaction Integral
11 //
12 #include "InteractionIntegral.h"
13 #include "MooseMesh.h"
14 #include "RankTwoTensor.h"
15 #include "libmesh/string_to_enum.h"
16 #include "libmesh/quadrature.h"
17 #include "DerivativeMaterialInterface.h"
18 #include "libmesh/utility.h"
19 
20 MooseEnum
22 {
23  return MooseEnum("Geometry Topology", "Geometry");
24 }
25 
26 MooseEnum
28 {
29  return MooseEnum("KI KII KIII T", "KI");
30 }
31 
32 registerMooseObject("TensorMechanicsApp", InteractionIntegral);
33 
35 
36 InputParameters
38 {
39  InputParameters params = ElementIntegralPostprocessor::validParams();
40  params.addClassDescription("Computes the interaction integral for fracture");
41  params.addRequiredCoupledVar(
42  "displacements",
43  "The displacements appropriate for the simulation geometry and coordinate system");
44  params.addCoupledVar("temperature",
45  "The temperature (optional). Must be provided to correctly compute "
46  "stress intensity factors in models with thermal strain gradients.");
47  params.addRequiredParam<UserObjectName>("crack_front_definition",
48  "The CrackFrontDefinition user object name");
49  params.addParam<unsigned int>(
50  "crack_front_point_index",
51  "The index of the point on the crack front corresponding to this q function");
52  params.addParam<Real>(
53  "K_factor", "Conversion factor between interaction integral and stress intensity factor K");
54  params.addParam<unsigned int>("symmetry_plane",
55  "Account for a symmetry plane passing through "
56  "the plane of the crack, normal to the specified "
57  "axis (0=x, 1=y, 2=z)");
58  params.addParam<Real>("poissons_ratio", "Poisson's ratio for the material.");
59  params.addParam<Real>("youngs_modulus", "Young's modulus of the material.");
60  params.set<bool>("use_displaced_mesh") = false;
61  params.addParam<unsigned int>("ring_first",
62  "The first ring of elements for volume integral domain");
63  params.addParam<unsigned int>("ring_index", "Ring ID");
64  params.addParam<MooseEnum>("q_function_type",
66  "The method used to define the integration domain. Options are: " +
67  InteractionIntegral::qFunctionType().getRawNames());
68  params.addRequiredParam<MooseEnum>("sif_mode",
70  "Stress intensity factor to calculate. Choices are: " +
71  InteractionIntegral::sifModeType().getRawNames());
72 
73  return params;
74 }
75 
76 InteractionIntegral::InteractionIntegral(const InputParameters & parameters)
77  : ElementIntegralPostprocessor(parameters),
78  _ndisp(coupledComponents("displacements")),
79  _crack_front_definition(&getUserObject<CrackFrontDefinition>("crack_front_definition")),
80  _has_crack_front_point_index(isParamValid("crack_front_point_index")),
81  _crack_front_point_index(
82  _has_crack_front_point_index ? getParam<unsigned int>("crack_front_point_index") : 0),
83  _treat_as_2d(false),
84  _stress(hasMaterialProperty<RankTwoTensor>("stress")
85  ? &getMaterialPropertyByName<RankTwoTensor>("stress")
86  : nullptr),
87  _strain(hasMaterialProperty<RankTwoTensor>("elastic_strain")
88  ? &getMaterialPropertyByName<RankTwoTensor>("elastic_strain")
89  : nullptr),
90  _grad_disp(3),
91  _has_temp(isCoupled("temperature")),
92  _grad_temp(_has_temp ? coupledGradient("temperature") : _grad_zero),
93  _K_factor(getParam<Real>("K_factor")),
94  _has_symmetry_plane(isParamValid("symmetry_plane")),
95  _poissons_ratio(getParam<Real>("poissons_ratio")),
96  _youngs_modulus(getParam<Real>("youngs_modulus")),
97  _ring_index(getParam<unsigned int>("ring_index")),
98  _total_deigenstrain_dT(hasMaterialProperty<RankTwoTensor>("total_deigenstrain_dT")
99  ? &getMaterialProperty<RankTwoTensor>("total_deigenstrain_dT")
100  : nullptr),
101  _q_function_type(getParam<MooseEnum>("q_function_type").getEnum<QMethod>()),
102  _sif_mode(getParam<MooseEnum>("sif_mode").getEnum<SifMethod>())
103 {
104  if (!hasMaterialProperty<RankTwoTensor>("stress"))
105  mooseError("InteractionIntegral Error: RankTwoTensor material property 'stress' not found. "
106  "This may be because solid mechanics system is being used to calculate a SymmTensor "
107  "'stress' material property. To use interaction integral calculation with solid "
108  "mechanics application, please set 'solid_mechanics = true' in the DomainIntegral "
109  "block.");
110 
111  if (!hasMaterialProperty<RankTwoTensor>("elastic_strain"))
112  mooseError("InteractionIntegral Error: RankTwoTensor material property 'elastic_strain' not "
113  "found. This may be because solid mechanics system is being used to calculate a "
114  "SymmTensor 'elastic_strain' material property. To use interaction integral "
115  "calculation with solid mechanics application, please set 'solid_mechanics = true' "
116  "in the DomainIntegral block.");
117 
119  mooseError("InteractionIntegral Error: To include thermal strain term in interaction integral, "
120  "must both couple temperature in DomainIntegral block and compute "
121  "total_deigenstrain_dT using ThermalFractureIntegral material model.");
122 
123  // plane strain
124  _kappa = 3.0 - 4.0 * _poissons_ratio;
125  _shear_modulus = _youngs_modulus / (2.0 * (1.0 + _poissons_ratio));
126 
127  // Checking for consistency between mesh size and length of the provided displacements vector
128  if (_ndisp != _mesh.dimension())
129  mooseError("InteractionIntegral Error: number of variables supplied in 'displacements' must "
130  "match the mesh dimension.");
131 
132  // fetch gradients of coupled variables
133  for (unsigned int i = 0; i < _ndisp; ++i)
134  _grad_disp[i] = &coupledGradient("displacements", i);
135 
136  // set unused dimensions to zero
137  for (unsigned i = _ndisp; i < 3; ++i)
138  _grad_disp[i] = &_grad_zero;
139 }
140 
141 void
143 {
145 }
146 
147 Real
149 {
150  gatherSum(_integral_value);
151 
155 
156  return _K_factor * _integral_value;
157 }
158 
159 Real
161 {
162  Real scalar_q = 0.0;
163  RealVectorValue grad_q(0.0, 0.0, 0.0);
164 
165  const std::vector<std::vector<Real>> & phi_curr_elem = *_phi_curr_elem;
166  const std::vector<std::vector<RealGradient>> & dphi_curr_elem = *_dphi_curr_elem;
167 
168  for (unsigned int i = 0; i < _current_elem->n_nodes(); ++i)
169  {
170  scalar_q += phi_curr_elem[i][_qp] * _q_curr_elem[i];
171 
172  for (unsigned int j = 0; j < _current_elem->dim(); ++j)
173  grad_q(j) += dphi_curr_elem[i][_qp](j) * _q_curr_elem[i];
174  }
175 
176  // In the crack front coordinate system, the crack direction is (1,0,0)
177  RealVectorValue crack_direction(0.0);
178  crack_direction(0) = 1.0;
179 
180  // Calculate (r,theta) position of qp relative to crack front
181  Point p(_q_point[_qp]);
183 
184  RankTwoTensor aux_stress;
185  RankTwoTensor aux_du;
186 
188  computeAuxFields(aux_stress, aux_du);
189  else if (_sif_mode == SifMethod::T)
190  computeTFields(aux_stress, aux_du);
191 
192  RankTwoTensor grad_disp((*_grad_disp[0])[_qp], (*_grad_disp[1])[_qp], (*_grad_disp[2])[_qp]);
193 
194  // Rotate stress, strain, displacement and temperature to crack front coordinate system
195  RealVectorValue grad_q_cf =
197  RankTwoTensor grad_disp_cf =
199  RankTwoTensor stress_cf =
201  RankTwoTensor strain_cf =
203  RealVectorValue grad_temp_cf =
205 
206  RankTwoTensor dq;
207  dq(0, 0) = crack_direction(0) * grad_q_cf(0);
208  dq(0, 1) = crack_direction(0) * grad_q_cf(1);
209  dq(0, 2) = crack_direction(0) * grad_q_cf(2);
210 
211  // Calculate interaction integral terms
212 
213  // Term1 = stress * x1-derivative of aux disp * dq
214  RankTwoTensor tmp1 = dq * stress_cf;
215  Real term1 = aux_du.doubleContraction(tmp1);
216 
217  // Term2 = aux stress * x1-derivative of disp * dq
218  RankTwoTensor tmp2 = dq * aux_stress;
219  Real term2 = grad_disp_cf(0, 0) * tmp2(0, 0) + grad_disp_cf(1, 0) * tmp2(0, 1) +
220  grad_disp_cf(2, 0) * tmp2(0, 2);
221 
222  // Term3 = aux stress * strain * dq_x (= stress * aux strain * dq_x)
223  Real term3 = dq(0, 0) * aux_stress.doubleContraction(strain_cf);
224 
225  // Term4 (thermal strain term) = q * aux_stress * alpha * dtheta_x
226  // - the term including the derivative of alpha is not implemented
227  Real term4 = 0.0;
228  if (_has_temp)
229  {
230  Real sigma_alpha = aux_stress.doubleContraction((*_total_deigenstrain_dT)[_qp]);
231  term4 = scalar_q * sigma_alpha * grad_temp_cf(0);
232  }
233 
234  Real q_avg_seg = 1.0;
236  {
237  q_avg_seg =
240  2.0;
241  }
242 
243  Real eq = term1 + term2 - term3 + term4;
244 
246  eq *= 2.0;
247 
248  return eq / q_avg_seg;
249 }
250 
251 Real
253 {
254  Real sum = 0.0;
255 
256  // calculate phi and dphi for this element
257  FEType fe_type(Utility::string_to_enum<Order>("first"),
258  Utility::string_to_enum<FEFamily>("lagrange"));
259  const unsigned int dim = _current_elem->dim();
260  std::unique_ptr<FEBase> fe(FEBase::build(dim, fe_type));
261  fe->attach_quadrature_rule(const_cast<QBase *>(_qrule));
262  _phi_curr_elem = &fe->get_phi();
263  _dphi_curr_elem = &fe->get_dphi();
264  fe->reinit(_current_elem);
265 
266  // calculate q for all nodes in this element
267  _q_curr_elem.clear();
268  unsigned int ring_base = (_q_function_type == QMethod::Topology) ? 0 : 1;
269 
270  for (unsigned int i = 0; i < _current_elem->n_nodes(); ++i)
271  {
272  const Node * this_node = _current_elem->node_ptr(i);
273  Real q_this_node;
274 
277  _crack_front_point_index, _ring_index - ring_base, this_node);
280  _crack_front_point_index, _ring_index - ring_base, this_node);
281 
282  _q_curr_elem.push_back(q_this_node);
283  }
284 
285  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
286  sum += _JxW[_qp] * _coord[_qp] * computeQpIntegral();
287  return sum;
288 }
289 
290 void
292 {
293  RealVectorValue k(0.0);
294  if (_sif_mode == SifMethod::KI)
295  k(0) = 1.0;
296  else if (_sif_mode == SifMethod::KII)
297  k(1) = 1.0;
298  else if (_sif_mode == SifMethod::KIII)
299  k(2) = 1.0;
300 
301  Real t = _theta;
302  Real t2 = _theta / 2.0;
303  Real tt2 = 3.0 * _theta / 2.0;
304  Real st = std::sin(t);
305  Real ct = std::cos(t);
306  Real st2 = std::sin(t2);
307  Real ct2 = std::cos(t2);
308  Real stt2 = std::sin(tt2);
309  Real ctt2 = std::cos(tt2);
310  Real ct2sq = Utility::pow<2>(ct2);
311  Real ct2cu = Utility::pow<3>(ct2);
312  Real sqrt2PiR = std::sqrt(2.0 * libMesh::pi * _r);
313 
314  // Calculate auxiliary stress tensor
315  aux_stress.zero();
316 
317  aux_stress(0, 0) =
318  1.0 / sqrt2PiR * (k(0) * ct2 * (1.0 - st2 * stt2) - k(1) * st2 * (2.0 + ct2 * ctt2));
319  aux_stress(1, 1) = 1.0 / sqrt2PiR * (k(0) * ct2 * (1.0 + st2 * stt2) + k(1) * st2 * ct2 * ctt2);
320  aux_stress(0, 1) = 1.0 / sqrt2PiR * (k(0) * ct2 * st2 * ctt2 + k(1) * ct2 * (1.0 - st2 * stt2));
321  aux_stress(0, 2) = -1.0 / sqrt2PiR * k(2) * st2;
322  aux_stress(1, 2) = 1.0 / sqrt2PiR * k(2) * ct2;
323  // plane stress
324  // Real s33 = 0;
325  // plane strain
326  aux_stress(2, 2) = _poissons_ratio * (aux_stress(0, 0) + aux_stress(1, 1));
327 
328  aux_stress(1, 0) = aux_stress(0, 1);
329  aux_stress(2, 0) = aux_stress(0, 2);
330  aux_stress(2, 1) = aux_stress(1, 2);
331 
332  // Calculate x1 derivative of auxiliary displacements
333  grad_disp.zero();
334 
335  grad_disp(0, 0) = k(0) / (4.0 * _shear_modulus * sqrt2PiR) *
336  (ct * ct2 * _kappa + ct * ct2 - 2.0 * ct * ct2cu + st * st2 * _kappa +
337  st * st2 - 6.0 * st * st2 * ct2sq) +
338  k(1) / (4.0 * _shear_modulus * sqrt2PiR) *
339  (ct * st2 * _kappa + ct * st2 + 2.0 * ct * st2 * ct2sq - st * ct2 * _kappa +
340  3.0 * st * ct2 - 6.0 * st * ct2cu);
341 
342  grad_disp(0, 1) = k(0) / (4.0 * _shear_modulus * sqrt2PiR) *
343  (ct * st2 * _kappa + ct * st2 - 2.0 * ct * st2 * ct2sq - st * ct2 * _kappa -
344  5.0 * st * ct2 + 6.0 * st * ct2cu) +
345  k(1) / (4.0 * _shear_modulus * sqrt2PiR) *
346  (-ct * ct2 * _kappa + 3.0 * ct * ct2 - 2.0 * ct * ct2cu -
347  st * st2 * _kappa + 3.0 * st * st2 - 6.0 * st * st2 * ct2sq);
348 
349  grad_disp(0, 2) = k(2) / (_shear_modulus * sqrt2PiR) * (st2 * ct - ct2 * st);
350 }
351 
352 void
354 {
355 
356  Real t = _theta;
357  Real st = std::sin(t);
358  Real ct = std::cos(t);
359  Real stsq = Utility::pow<2>(st);
360  Real ctsq = Utility::pow<2>(ct);
361  Real ctcu = Utility::pow<3>(ct);
362  Real oneOverPiR = 1.0 / (libMesh::pi * _r);
363 
364  aux_stress.zero();
365  aux_stress(0, 0) = -oneOverPiR * ctcu;
366  aux_stress(0, 1) = -oneOverPiR * st * ctsq;
367  aux_stress(1, 0) = -oneOverPiR * st * ctsq;
368  aux_stress(1, 1) = -oneOverPiR * ct * stsq;
369  aux_stress(2, 2) = -oneOverPiR * _poissons_ratio * (ctcu + ct * stsq);
370 
371  grad_disp.zero();
372  grad_disp(0, 0) = oneOverPiR / (4.0 * _youngs_modulus) *
373  (ct * (4.0 * Utility::pow<2>(_poissons_ratio) - 3.0 + _poissons_ratio) -
374  std::cos(3.0 * t) * (1.0 + _poissons_ratio));
375  grad_disp(0, 1) = -oneOverPiR / (4.0 * _youngs_modulus) *
376  (st * (4.0 * Utility::pow<2>(_poissons_ratio) - 3.0 + _poissons_ratio) +
377  std::sin(3.0 * t) * (1.0 + _poissons_ratio));
378 }
InteractionIntegral::sifModeType
static MooseEnum sifModeType()
Definition: InteractionIntegral.C:27
registerMooseObject
registerMooseObject("TensorMechanicsApp", InteractionIntegral)
InteractionIntegral::_crack_front_point_index
const unsigned int _crack_front_point_index
Definition: InteractionIntegral.h:49
InteractionIntegral::_ndisp
unsigned int _ndisp
Definition: InteractionIntegral.h:46
InteractionIntegral::_has_temp
const bool _has_temp
Definition: InteractionIntegral.h:54
InteractionIntegral::SifMethod::KIII
InteractionIntegral::SifMethod::KI
InteractionIntegral::_total_deigenstrain_dT
const MaterialProperty< RankTwoTensor > * _total_deigenstrain_dT
Definition: InteractionIntegral.h:61
InteractionIntegral::validParams
static InputParameters validParams()
Definition: InteractionIntegral.C:37
CrackFrontDefinition::DomainIntegralQFunction
Real DomainIntegralQFunction(unsigned int crack_front_point_index, unsigned int ring_index, const Node *const current_node) const
Definition: CrackFrontDefinition.C:1675
CrackFrontDefinition
Works on top of NodalNormalsPreprocessor.
Definition: CrackFrontDefinition.h:36
CrackFrontDefinition::getCrackFrontTangentialStrain
Real getCrackFrontTangentialStrain(const unsigned int node_index) const
Definition: CrackFrontDefinition.C:1448
InteractionIntegral::qFunctionType
static MooseEnum qFunctionType()
Definition: InteractionIntegral.C:21
InteractionIntegral::_strain
const MaterialProperty< RankTwoTensor > * _strain
Definition: InteractionIntegral.h:52
InteractionIntegral::_poissons_ratio
Real _poissons_ratio
Definition: InteractionIntegral.h:58
InteractionIntegral::SifMethod::KII
InteractionIntegral::_treat_as_2d
bool _treat_as_2d
Definition: InteractionIntegral.h:50
InteractionIntegral::QMethod
QMethod
Definition: InteractionIntegral.h:71
InteractionIntegral::_q_function_type
const QMethod _q_function_type
Definition: InteractionIntegral.h:77
InteractionIntegral::getValue
virtual Real getValue()
Definition: InteractionIntegral.C:148
CrackFrontDefinition::DomainIntegralTopologicalQFunction
Real DomainIntegralTopologicalQFunction(unsigned int crack_front_point_index, unsigned int ring_index, const Node *const current_node) const
Definition: CrackFrontDefinition.C:1729
InteractionIntegral::computeQpIntegral
virtual Real computeQpIntegral()
Definition: InteractionIntegral.C:160
InteractionIntegral
This postprocessor computes the Interaction Integral.
Definition: InteractionIntegral.h:28
InteractionIntegral::SifMethod
SifMethod
Definition: InteractionIntegral.h:79
InteractionIntegral::_K_factor
Real _K_factor
Definition: InteractionIntegral.h:56
InteractionIntegral::computeAuxFields
void computeAuxFields(RankTwoTensor &aux_stress, RankTwoTensor &grad_disp)
Definition: InteractionIntegral.C:291
InteractionIntegral::_phi_curr_elem
const std::vector< std::vector< Real > > * _phi_curr_elem
Definition: InteractionIntegral.h:63
CrackFrontDefinition::calculateRThetaToCrackFront
void calculateRThetaToCrackFront(const Point qp, const unsigned int point_index, Real &r, Real &theta) const
calculate r and theta in the crack front polar coordinates
Definition: CrackFrontDefinition.C:1150
InteractionIntegral::QMethod::Geometry
validParams
InputParameters validParams()
InteractionIntegral::computeIntegral
virtual Real computeIntegral()
Definition: InteractionIntegral.C:252
InteractionIntegral.h
defineLegacyParams
defineLegacyParams(InteractionIntegral)
InteractionIntegral::_has_symmetry_plane
bool _has_symmetry_plane
Definition: InteractionIntegral.h:57
CrackFrontDefinition::rotateToCrackFrontCoords
RealVectorValue rotateToCrackFrontCoords(const RealVectorValue vector, const unsigned int point_index) const
Definition: CrackFrontDefinition.C:1126
InteractionIntegral::_grad_disp
std::vector< const VariableGradient * > _grad_disp
Definition: InteractionIntegral.h:53
InteractionIntegral::initialSetup
virtual void initialSetup()
Definition: InteractionIntegral.C:142
CrackFrontDefinition::treatAs2D
bool treatAs2D() const
Definition: CrackFrontDefinition.h:59
InteractionIntegral::_youngs_modulus
Real _youngs_modulus
Definition: InteractionIntegral.h:59
InteractionIntegral::_r
Real _r
Definition: InteractionIntegral.h:67
InteractionIntegral::_shear_modulus
Real _shear_modulus
Definition: InteractionIntegral.h:66
InteractionIntegral::InteractionIntegral
InteractionIntegral(const InputParameters &parameters)
Definition: InteractionIntegral.C:76
InteractionIntegral::computeTFields
void computeTFields(RankTwoTensor &aux_stress, RankTwoTensor &grad_disp)
Definition: InteractionIntegral.C:353
InteractionIntegral::_crack_front_definition
const CrackFrontDefinition *const _crack_front_definition
Definition: InteractionIntegral.h:47
InteractionIntegral::_grad_temp
const VariableGradient & _grad_temp
Definition: InteractionIntegral.h:55
InteractionIntegral::QMethod::Topology
RankTwoTensorTempl< Real >
CrackFrontDefinition::getCrackFrontBackwardSegmentLength
Real getCrackFrontBackwardSegmentLength(const unsigned int point_index) const
Definition: CrackFrontDefinition.C:1084
InteractionIntegral::_stress
const MaterialProperty< RankTwoTensor > * _stress
Definition: InteractionIntegral.h:51
InteractionIntegral::_ring_index
unsigned int _ring_index
Definition: InteractionIntegral.h:60
InteractionIntegral::_q_curr_elem
std::vector< Real > _q_curr_elem
Definition: InteractionIntegral.h:62
InteractionIntegral::_dphi_curr_elem
const std::vector< std::vector< RealGradient > > * _dphi_curr_elem
Definition: InteractionIntegral.h:64
InteractionIntegral::SifMethod::T
CrackFrontDefinition::getCrackFrontForwardSegmentLength
Real getCrackFrontForwardSegmentLength(const unsigned int point_index) const
Definition: CrackFrontDefinition.C:1078
InteractionIntegral::_kappa
Real _kappa
Definition: InteractionIntegral.h:65
InteractionIntegral::_theta
Real _theta
Definition: InteractionIntegral.h:68
InteractionIntegral::_sif_mode
const SifMethod _sif_mode
Definition: InteractionIntegral.h:87