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"
23 return MooseEnum(
"Geometry Topology",
"Geometry");
29 return MooseEnum(
"KI KII KIII T",
"KI");
40 params.addClassDescription(
"Computes the interaction integral for fracture");
41 params.addRequiredCoupledVar(
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: " +
68 params.addRequiredParam<MooseEnum>(
"sif_mode",
70 "Stress intensity factor to calculate. Choices are: " +
77 : ElementIntegralPostprocessor(parameters),
78 _ndisp(coupledComponents(
"displacements")),
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),
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")
101 _q_function_type(getParam<MooseEnum>(
"q_function_type").getEnum<
QMethod>()),
102 _sif_mode(getParam<MooseEnum>(
"sif_mode").getEnum<
SifMethod>())
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 "
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.");
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.");
128 if (
_ndisp != _mesh.dimension())
129 mooseError(
"InteractionIntegral Error: number of variables supplied in 'displacements' must "
130 "match the mesh dimension.");
133 for (
unsigned int i = 0; i <
_ndisp; ++i)
134 _grad_disp[i] = &coupledGradient(
"displacements", i);
137 for (
unsigned i =
_ndisp; i < 3; ++i)
150 gatherSum(_integral_value);
163 RealVectorValue grad_q(0.0, 0.0, 0.0);
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;
168 for (
unsigned int i = 0; i < _current_elem->n_nodes(); ++i)
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];
177 RealVectorValue crack_direction(0.0);
178 crack_direction(0) = 1.0;
181 Point p(_q_point[_qp]);
195 RealVectorValue grad_q_cf =
203 RealVectorValue grad_temp_cf =
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);
215 Real term1 = aux_du.doubleContraction(tmp1);
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);
223 Real term3 = dq(0, 0) * aux_stress.doubleContraction(strain_cf);
231 term4 = scalar_q * sigma_alpha * grad_temp_cf(0);
234 Real q_avg_seg = 1.0;
243 Real eq = term1 + term2 - term3 + term4;
248 return eq / q_avg_seg;
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));
264 fe->reinit(_current_elem);
270 for (
unsigned int i = 0; i < _current_elem->n_nodes(); ++i)
272 const Node * this_node = _current_elem->node_ptr(i);
285 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
293 RealVectorValue k(0.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);
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;
326 aux_stress(2, 2) =
_poissons_ratio * (aux_stress(0, 0) + aux_stress(1, 1));
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);
336 (ct * ct2 *
_kappa + ct * ct2 - 2.0 * ct * ct2cu + st * st2 *
_kappa +
337 st * st2 - 6.0 * st * st2 * ct2sq) +
339 (ct * st2 *
_kappa + ct * st2 + 2.0 * ct * st2 * ct2sq - st * ct2 *
_kappa +
340 3.0 * st * ct2 - 6.0 * st * ct2cu);
343 (ct * st2 *
_kappa + ct * st2 - 2.0 * ct * st2 * ct2sq - st * ct2 *
_kappa -
344 5.0 * st * ct2 + 6.0 * st * ct2cu) +
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);
349 grad_disp(0, 2) = k(2) / (
_shear_modulus * sqrt2PiR) * (st2 * ct - ct2 * st);
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);
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;