118 _ndisp(coupledComponents(
"displacements")),
121 _stress(getGenericMaterialPropertyByName<
RankTwoTensor, is_ad>(
"stress")),
122 _strain(getGenericMaterialPropertyByName<
RankTwoTensor, is_ad>(
"elastic_strain")),
123 _fe_vars(getCoupledMooseVars()),
124 _fe_type(_fe_vars[0]->feType()),
125 _disp(coupledValues(
"displacements")),
127 _has_temp(isCoupled(
"temperature")),
128 _grad_temp(_has_temp ? coupledGradient(
"temperature") : _grad_zero),
129 _functionally_graded_youngs_modulus_crack_dir_gradient(
130 isParamSetByUser(
"functionally_graded_youngs_modulus_crack_dir_gradient")
131 ? &getMaterialProperty<Real>(
"functionally_graded_youngs_modulus_crack_dir_gradient")
133 _functionally_graded_youngs_modulus(
134 isParamSetByUser(
"functionally_graded_youngs_modulus")
135 ? &getMaterialProperty<Real>(
"functionally_graded_youngs_modulus")
137 _K_factor(getParam<Real>(
"K_factor")),
138 _has_symmetry_plane(isParamValid(
"symmetry_plane")),
139 _poissons_ratio(getParam<Real>(
"poissons_ratio")),
140 _youngs_modulus(getParam<Real>(
"youngs_modulus")),
141 _fgm_crack(isParamSetByUser(
"functionally_graded_youngs_modulus_crack_dir_gradient") &&
142 isParamSetByUser(
"functionally_graded_youngs_modulus")),
143 _ring_index(getParam<unsigned
int>(
"ring_index")),
144 _total_deigenstrain_dT(
146 ? &getGenericMaterialProperty<
RankTwoTensor, is_ad>(
"total_deigenstrain_dT")
148 _has_additional_eigenstrain(false),
149 _additional_eigenstrain_gradient_00(isCoupled(
"additional_eigenstrain_00")
150 ? &coupledGradient(
"additional_eigenstrain_00")
152 _additional_eigenstrain_gradient_01(isCoupled(
"additional_eigenstrain_01")
153 ? &coupledGradient(
"additional_eigenstrain_01")
155 _additional_eigenstrain_gradient_11(isCoupled(
"additional_eigenstrain_11")
156 ? &coupledGradient(
"additional_eigenstrain_11")
158 _additional_eigenstrain_gradient_22(isCoupled(
"additional_eigenstrain_22")
159 ? &coupledGradient(
"additional_eigenstrain_22")
161 _additional_eigenstrain_gradient_02(isCoupled(
"additional_eigenstrain_02")
162 ? &coupledGradient(
"additional_eigenstrain_02")
164 _additional_eigenstrain_gradient_12(isCoupled(
"additional_eigenstrain_12")
165 ? &coupledGradient(
"additional_eigenstrain_12")
167 _q_function_type(getParam<
MooseEnum>(
"q_function_type").template getEnum<
QMethod>()),
170 _x(declareVector(
"x")),
171 _y(declareVector(
"y")),
172 _z(declareVector(
"z")),
173 _position(declareVector(
"id")),
174 _interaction_integral(declareVector(
"II_" +
Moose::stringify(getParam<
MooseEnum>(
"sif_mode")) +
175 "_" +
Moose::stringify(_ring_index))),
176 _eigenstrain_gradient(nullptr),
180 mooseError(
"InteractionIntegral Error: To include thermal strain term in interaction integral, "
181 "must both couple temperature in DomainIntegral block and compute "
182 "total_deigenstrain_dT using ThermalFractureIntegral material model.");
188 paramError(
"functionally_graded_youngs_modulus_crack_dir_gradient",
189 "You have selected to compute the interaction integral for a crack in FGM. That "
190 "selection requires the user to provide a spatially varying elasticity modulus "
192 "defines the transition of material properties (i.e. "
193 "'functionally_graded_youngs_modulus') and its "
194 "spatial derivative in the crack direction (i.e. "
195 "'functionally_graded_youngs_modulus_crack_dir_gradient').");
204 "InteractionIntegral Error: number of variables supplied in 'displacements' must "
205 "match the mesh dimension.");
208 for (std::size_t i = 0; i <
_ndisp; ++i)
212 for (std::size_t i =
_ndisp; i < 3; ++i)
218 &getGenericMaterialProperty<RankThreeTensor, is_ad>(
"eigenstrain_gradient");
221 "eigenstrain_gradient cannot be specified for materials that provide the "
222 "total_deigenstrain_dT material property");
225 _body_force = &getMaterialProperty<RealVectorValue>(
"body_force");
234 paramError(
"additional_eigenstrain_gradient_12",
235 "If additional eigenstrains are provided for the computation of the interaction "
236 "integral in three dimensions, make sure the six components are provided.");
239 mooseInfo(
"A generic eigenstrain provided by the user will be considered in the interaction "
240 "integral (via domain integral action).");
278 const RealVectorValue & grad_of_scalar_q)
282 if (scalar_q < TOLERANCE * TOLERANCE * TOLERANCE)
286 RealVectorValue crack_direction(1.0, 0.0, 0.0);
289 _crack_front_definition->calculateRThetaToCrackFront(
290 _q_point[_qp], crack_front_point_index, _r, _theta);
297 if (_sif_mode == SifMethod::KI || _sif_mode == SifMethod::KII || _sif_mode == SifMethod::KIII)
298 computeAuxFields(aux_stress, aux_du, aux_strain, aux_disp);
299 else if (_sif_mode == SifMethod::T)
300 computeTFields(aux_stress, aux_du);
303 (*_grad_disp[0])[_qp], (*_grad_disp[1])[_qp], (*_grad_disp[2])[_qp]);
306 RealVectorValue grad_q_cf =
307 _crack_front_definition->rotateToCrackFrontCoords(grad_of_scalar_q, crack_front_point_index);
309 _crack_front_definition->rotateToCrackFrontCoords(grad_disp, crack_front_point_index);
310 RankTwoTensor stress_cf = _crack_front_definition->rotateToCrackFrontCoords(
312 RankTwoTensor strain_cf = _crack_front_definition->rotateToCrackFrontCoords(
314 RealVectorValue grad_temp_cf =
315 _crack_front_definition->rotateToCrackFrontCoords(_grad_temp[_qp], crack_front_point_index);
318 strain_cf(2, 2) = 0.0;
321 dq(0, 0) = crack_direction(0) * grad_q_cf(0);
322 dq(0, 1) = crack_direction(0) * grad_q_cf(1);
323 dq(0, 2) = crack_direction(0) * grad_q_cf(2);
333 Real term2 = grad_disp_cf(0, 0) * tmp2(0, 0) + grad_disp_cf(1, 0) * tmp2(0, 1) +
334 grad_disp_cf(2, 0) * tmp2(0, 2);
346 term4 = scalar_q * sigma_alpha * grad_temp_cf(0);
350 if (_eigenstrain_gradient)
356 const RealVectorValue & crack_dir =
357 _crack_front_definition->getCrackDirection(crack_front_point_index);
368 if (_has_additional_eigenstrain)
380 const RealVectorValue & crack_dir =
381 _crack_front_definition->getCrackDirection(crack_front_point_index);
383 const auto eigenstrain_gradient_x =
385 const auto eigenstrain_gradient_xy =
387 const auto eigenstrain_gradient_y =
391 if (_additional_eigenstrain_gradient_22)
392 eigenstrain_gradient_z = I_z.
mixedProductJkI((*_additional_eigenstrain_gradient_22)[_qp]);
403 if (_mesh.dimension() == 3)
407 I_xz(0, 2) = I_xz(2, 0) = 1.0;
408 eigenstrain_gradient_xz = I_xz.
mixedProductJkI((*_additional_eigenstrain_gradient_02)[_qp]);
410 I_yz(1, 2) = I_yz(2, 1) = 1.0;
411 eigenstrain_gradient_yz = I_yz.
mixedProductJkI((*_additional_eigenstrain_gradient_12)[_qp]);
429 const RealVectorValue & crack_dir =
430 _crack_front_definition->getCrackDirection(crack_front_point_index);
435 if (_fgm_crack && scalar_q != 0)
445 cijklj *= (*_functionally_graded_youngs_modulus_crack_dir_gradient)[_qp];
446 cijklj_epsilonkl_aux = cijklj * aux_strain;
448 const Real term6_a = grad_disp_cf(0, 0) * cijklj_epsilonkl_aux(0, 0) +
449 grad_disp_cf(1, 0) * cijklj_epsilonkl_aux(0, 1) +
450 grad_disp_cf(2, 0) * cijklj_epsilonkl_aux(0, 2);
454 cijkl1_epsilonkl = -cijklj * strain_cf;
457 term6 = (term6_a + term6_b) * scalar_q;
466 const Real u_r = (*_disp[0])[_qp];
467 const Real radius_qp = _q_point[_qp](0);
470 (u_r / radius_qp * aux_stress(2, 2) + aux_disp(0, 0) / radius_qp * stress_cf(2, 2) -
475 const Real term7b1 = aux_stress(0, 0) * grad_disp_cf(0, 0) +
476 aux_stress(0, 1) * grad_disp_cf(1, 0) +
477 aux_stress(0, 2) * grad_disp_cf(2, 0);
479 const Real term7b = 1.0 / radius_qp *
480 (term7b1 - aux_stress(2, 2) * grad_disp_cf(0, 0) +
481 stress_cf(2, 2) * (aux_du(0, 0) - aux_disp(0, 0) / radius_qp));
483 term7 = (term7a + term7b) * scalar_q;
486 Real q_avg_seg = 1.0;
487 if (!_crack_front_definition->treatAs2D())
490 (_crack_front_definition->getCrackFrontForwardSegmentLength(crack_front_point_index) +
491 _crack_front_definition->getCrackFrontBackwardSegmentLength(crack_front_point_index)) /
495 Real eq = term1 + term2 + term3 + term4 + term4a + term4b + term5 + term6 + term7;
499 const Real radius_qp = _q_point[_qp](0);
502 std::size_t num_crack_front_points = _crack_front_definition->getNumCrackFrontPoints();
503 if (num_crack_front_points != 1)
504 mooseError(
"Crack front has more than one point, but this is a 2D-RZ problem. Please revise "
507 const Point * crack_front_point = _crack_front_definition->getCrackFrontPoint(0);
508 eq = eq / (*crack_front_point)(0);
511 return eq / q_avg_seg;
519 const std::size_t
dim = _current_elem->dim();
520 std::unique_ptr<FEBase> fe(FEBase::build(
dim, _fe_type));
521 fe->attach_quadrature_rule(
const_cast<QBase *
>(_qrule));
522 _phi_curr_elem = &fe->get_phi();
523 _dphi_curr_elem = &fe->get_dphi();
524 fe->reinit(_current_elem);
527 std::size_t ring_base = (_q_function_type == QMethod::Topology) ? 0 : 1;
529 for (
auto icfp = beginIndex(_interaction_integral); icfp < _interaction_integral.size(); icfp++)
531 _q_curr_elem.clear();
532 for (std::size_t i = 0; i < _current_elem->n_nodes(); ++i)
534 const Node * this_node = _current_elem->node_ptr(i);
537 if (_q_function_type == QMethod::Geometry)
538 q_this_node = _crack_front_definition->DomainIntegralQFunction(
539 icfp, _ring_index - ring_base, this_node);
541 q_this_node = _crack_front_definition->DomainIntegralTopologicalQFunction(
542 icfp, _ring_index - ring_base, this_node);
544 _q_curr_elem.push_back(q_this_node);
547 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
550 RealVectorValue grad_of_scalar_q(0.0, 0.0, 0.0);
552 for (std::size_t i = 0; i < _current_elem->n_nodes(); ++i)
554 scalar_q += (*_phi_curr_elem)[i][_qp] * _q_curr_elem[i];
556 for (std::size_t j = 0; j < _current_elem->dim(); ++j)
557 grad_of_scalar_q(j) += (*_dphi_curr_elem)[i][_qp](j) * _q_curr_elem[i];
561 _interaction_integral[icfp] +=
562 _JxW[_qp] * _coord[_qp] * computeQpIntegral(icfp, scalar_q, grad_of_scalar_q);
564 _interaction_integral[icfp] +=
565 _JxW[_qp] * computeQpIntegral(icfp, scalar_q, grad_of_scalar_q);
616 RealVectorValue k(0.0);
617 if (_sif_mode == SifMethod::KI)
619 else if (_sif_mode == SifMethod::KII)
621 else if (_sif_mode == SifMethod::KIII)
625 Real t2 = _theta / 2.0;
626 Real tt2 = 3.0 * _theta / 2.0;
627 Real st = std::sin(t);
628 Real ct = std::cos(t);
629 Real st2 = std::sin(t2);
630 Real ct2 = std::cos(t2);
631 Real stt2 = std::sin(tt2);
632 Real ctt2 = std::cos(tt2);
633 Real ct2sq = Utility::pow<2>(ct2);
634 Real st2sq = Utility::pow<2>(st2);
635 Real ct2cu = Utility::pow<3>(ct2);
642 1.0 / sqrt2PiR * (k(0) * ct2 * (1.0 - st2 * stt2) - k(1) * st2 * (2.0 + ct2 * ctt2));
643 aux_stress(1, 1) = 1.0 / sqrt2PiR * (k(0) * ct2 * (1.0 + st2 * stt2) + k(1) * st2 * ct2 * ctt2);
644 aux_stress(0, 1) = 1.0 / sqrt2PiR * (k(0) * ct2 * st2 * ctt2 + k(1) * ct2 * (1.0 - st2 * stt2));
645 aux_stress(0, 2) = -1.0 / sqrt2PiR * k(2) * st2;
646 aux_stress(1, 2) = 1.0 / sqrt2PiR * k(2) * ct2;
650 aux_stress(2, 2) = _poissons_ratio * (aux_stress(0, 0) + aux_stress(1, 1));
652 aux_stress(1, 0) = aux_stress(0, 1);
653 aux_stress(2, 0) = aux_stress(0, 2);
654 aux_stress(2, 1) = aux_stress(1, 2);
662 (*_functionally_graded_youngs_modulus)[_qp], _poissons_ratio);
663 aux_strain = spatial_elasticity_tensor.
invSymm() * aux_stress;
668 grad_disp(0, 0) = k(0) / (4.0 * _shear_modulus * sqrt2PiR) *
669 (ct * ct2 * _kappa + ct * ct2 - 2.0 * ct * ct2cu + st * st2 * _kappa +
670 st * st2 - 6.0 * st * st2 * ct2sq) +
671 k(1) / (4.0 * _shear_modulus * sqrt2PiR) *
672 (ct * st2 * _kappa + ct * st2 + 2.0 * ct * st2 * ct2sq - st * ct2 * _kappa +
673 3.0 * st * ct2 - 6.0 * st * ct2cu);
675 grad_disp(0, 1) = k(0) / (4.0 * _shear_modulus * sqrt2PiR) *
676 (ct * st2 * _kappa + ct * st2 - 2.0 * ct * st2 * ct2sq - st * ct2 * _kappa -
677 5.0 * st * ct2 + 6.0 * st * ct2cu) +
678 k(1) / (4.0 * _shear_modulus * sqrt2PiR) *
679 (-ct * ct2 * _kappa + 3.0 * ct * ct2 - 2.0 * ct * ct2cu -
680 st * st2 * _kappa + 3.0 * st * st2 - 6.0 * st * st2 * ct2sq);
682 grad_disp(0, 2) = k(2) / (_shear_modulus * sqrt2PiR) * (st2 * ct - ct2 * st);
688 const Real prefactor_rz = std::sqrt(_r / 2.0 /
libMesh::pi) / 2.0 / _shear_modulus;
689 aux_disp(0, 0) = prefactor_rz * ((k(0) * ct2 * (_kappa - 1.0 + 2.0 * st2sq)) +
690 (k(1) * st2 * (_kappa + 1.0 + 2.0 * ct2sq)));
691 aux_disp(0, 1) = prefactor_rz * ((k(0) * st2 * (_kappa + 1.0 - 2.0 * ct2sq)) -
692 (k(1) * ct2 * (_kappa - 1.0 - 2.0 * st2sq)));
693 aux_disp(0, 2) = prefactor_rz * k(2) * 4.0 * st2;