LCOV - code coverage report
Current view: top level - src/auxkernels - DomainIntegralQFunction.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: f45d79 Lines: 58 61 95.1 %
Date: 2025-07-25 05:00:39 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      10             : #include "DomainIntegralQFunction.h"
      11             : 
      12             : registerMooseObject("SolidMechanicsApp", DomainIntegralQFunction);
      13             : 
      14             : InputParameters
      15        1406 : DomainIntegralQFunction::validParams()
      16             : {
      17        1406 :   InputParameters params = AuxKernel::validParams();
      18        1406 :   params.addClassDescription("Computes the q-function for a segment along the crack front, used in "
      19             :                              "the calculation of the J-integral");
      20        2812 :   params.addRequiredParam<Real>("j_integral_radius_inner", "Radius for J-Integral calculation");
      21        2812 :   params.addRequiredParam<Real>("j_integral_radius_outer", "Radius for J-Integral calculation");
      22        2812 :   params.addRequiredParam<UserObjectName>("crack_front_definition",
      23             :                                           "The CrackFrontDefinition user object name");
      24        2812 :   params.addParam<unsigned int>(
      25             :       "crack_front_point_index",
      26             :       "The index of the point on the crack front corresponding to this q function");
      27        1406 :   params.set<bool>("use_displaced_mesh") = false;
      28        1406 :   return params;
      29           0 : }
      30             : 
      31        1248 : DomainIntegralQFunction::DomainIntegralQFunction(const InputParameters & parameters)
      32             :   : AuxKernel(parameters),
      33        1248 :     _j_integral_radius_inner(getParam<Real>("j_integral_radius_inner")),
      34        2496 :     _j_integral_radius_outer(getParam<Real>("j_integral_radius_outer")),
      35        1248 :     _crack_front_definition(&getUserObject<CrackFrontDefinition>("crack_front_definition")),
      36        2496 :     _has_crack_front_point_index(isParamValid("crack_front_point_index")),
      37        1248 :     _crack_front_point_index(
      38        2082 :         _has_crack_front_point_index ? getParam<unsigned int>("crack_front_point_index") : 0),
      39        1248 :     _treat_as_2d(false),
      40        1248 :     _is_point_on_intersecting_boundary(false)
      41             : {
      42        1248 : }
      43             : 
      44             : void
      45        1248 : DomainIntegralQFunction::initialSetup()
      46             : {
      47        1248 :   _treat_as_2d = _crack_front_definition->treatAs2D();
      48             :   bool using_mesh_cutter = _crack_front_definition->usingMeshCutter();
      49        1248 :   if (_treat_as_2d && using_mesh_cutter == false)
      50             :   {
      51         414 :     if (_has_crack_front_point_index)
      52             :     {
      53           0 :       mooseWarning(
      54             :           "crack_front_point_index ignored because CrackFrontDefinition is set to treat as 2D");
      55             :     }
      56             :   }
      57             :   else
      58             :   {
      59         834 :     if (!_has_crack_front_point_index)
      60             :     {
      61           0 :       mooseError("crack_front_point_index must be specified in DomainIntegralQFunction");
      62             :     }
      63             :   }
      64        1248 :   _is_point_on_intersecting_boundary =
      65        1248 :       _crack_front_definition->isPointWithIndexOnIntersectingBoundary(_crack_front_point_index);
      66        1248 : }
      67             : 
      68             : Real
      69      853224 : DomainIntegralQFunction::computeValue()
      70             : {
      71             :   Real dist_to_crack_front;
      72             :   Real dist_along_tangent;
      73      853224 :   projectToFrontAtPoint(dist_to_crack_front, dist_along_tangent);
      74             : 
      75             :   Real q = 1.0;
      76      853224 :   if (dist_to_crack_front > _j_integral_radius_inner &&
      77      838568 :       dist_to_crack_front < _j_integral_radius_outer)
      78        4224 :     q = (_j_integral_radius_outer - dist_to_crack_front) /
      79        4224 :         (_j_integral_radius_outer - _j_integral_radius_inner);
      80      849000 :   else if (dist_to_crack_front >= _j_integral_radius_outer)
      81             :     q = 0.0;
      82             : 
      83      853224 :   if (q > 0.0)
      84             :   {
      85       18864 :     Real tangent_multiplier = 1.0;
      86       18864 :     if (!_treat_as_2d)
      87             :     {
      88             :       const Real forward_segment_length =
      89       10280 :           _crack_front_definition->getCrackFrontForwardSegmentLength(_crack_front_point_index);
      90             :       const Real backward_segment_length =
      91       10280 :           _crack_front_definition->getCrackFrontBackwardSegmentLength(_crack_front_point_index);
      92             : 
      93       10280 :       if (dist_along_tangent >= 0.0)
      94             :       {
      95        6656 :         if (forward_segment_length > 0.0)
      96        6224 :           tangent_multiplier = 1.0 - dist_along_tangent / forward_segment_length;
      97             :       }
      98             :       else
      99             :       {
     100        3624 :         if (backward_segment_length > 0.0)
     101        3568 :           tangent_multiplier = 1.0 + dist_along_tangent / backward_segment_length;
     102             :       }
     103             :     }
     104             : 
     105       18864 :     tangent_multiplier = std::max(tangent_multiplier, 0.0);
     106       18864 :     tangent_multiplier = std::min(tangent_multiplier, 1.0);
     107             : 
     108             :     // Set to zero if a node is on a designated free surface and its crack front node is not.
     109       18864 :     if (_crack_front_definition->isNodeOnIntersectingBoundary(_current_node) &&
     110        1896 :         !_is_point_on_intersecting_boundary)
     111        1416 :       tangent_multiplier = 0.0;
     112             : 
     113       18864 :     q *= tangent_multiplier;
     114             :   }
     115             : 
     116      853224 :   return q;
     117             : }
     118             : 
     119             : void
     120      853224 : DomainIntegralQFunction::projectToFrontAtPoint(Real & dist_to_front, Real & dist_along_tangent)
     121             : {
     122             :   const Point * crack_front_point =
     123      853224 :       _crack_front_definition->getCrackFrontPoint(_crack_front_point_index);
     124             : 
     125      853224 :   Point p = *_current_node;
     126             :   const RealVectorValue & crack_front_tangent =
     127      853224 :       _crack_front_definition->getCrackFrontTangent(_crack_front_point_index);
     128             : 
     129             :   RealVectorValue crack_node_to_current_node = p - *crack_front_point;
     130      853224 :   dist_along_tangent = crack_node_to_current_node * crack_front_tangent;
     131             :   RealVectorValue projection_point = *crack_front_point + dist_along_tangent * crack_front_tangent;
     132             :   RealVectorValue axis_to_current_node = p - projection_point;
     133      853224 :   dist_to_front = axis_to_current_node.norm();
     134      853224 : }

Generated by: LCOV version 1.14