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