LCOV - code coverage report
Current view: top level - src/userobjects - MeshCut2DFractureUserObject.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31405 (292dce) with base fef103 Lines: 71 83 85.5 %
Date: 2025-09-04 07:58:55 Functions: 4 4 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 "MeshCut2DFractureUserObject.h"
      11             : 
      12             : #include "XFEMFuncs.h"
      13             : #include "MooseError.h"
      14             : #include "MooseMesh.h"
      15             : #include "libmesh/edge_edge2.h"
      16             : #include "libmesh/serial_mesh.h"
      17             : #include "libmesh/mesh_tools.h"
      18             : #include "algorithm"
      19             : 
      20             : #include "CrackFrontDefinition.h"
      21             : 
      22             : registerMooseObject("XFEMApp", MeshCut2DFractureUserObject);
      23             : 
      24             : InputParameters
      25          67 : MeshCut2DFractureUserObject::validParams()
      26             : {
      27          67 :   InputParameters params = MeshCut2DUserObjectBase::validParams();
      28          67 :   params.addClassDescription("XFEM mesh cutter for 2D models that defines cuts with a"
      29             :                              "mesh and uses fracture integrals to determine growth");
      30         134 :   params.addRequiredParam<Real>("growth_increment",
      31             :                                 "Length to grow crack if k>k_critical or stress>stress_threshold");
      32         134 :   params.addParam<Real>("k_critical", "Critical fracture toughness.");
      33         134 :   params.addParam<Real>("stress_threshold", "Stress threshold for growing crack");
      34         134 :   params.addParam<VectorPostprocessorName>(
      35             :       "ki_vectorpostprocessor", "II_KI_1", "The name of the vectorpostprocessor that contains KI");
      36         134 :   params.addParam<VectorPostprocessorName>("kii_vectorpostprocessor",
      37             :                                            "II_KII_1",
      38             :                                            "The name of the vectorpostprocessor that contains KII");
      39         134 :   params.addParam<VectorPostprocessorName>(
      40             :       "stress_vectorpostprocessor",
      41             :       "The name of the vectorpostprocessor that contains crack front stress");
      42         134 :   params.addParam<std::string>("stress_vector_name",
      43             :                                "crack_tip_stress",
      44             :                                "The name of the stress vector in the stress_vectorpostprocessor");
      45         134 :   params.addParam<VectorPostprocessorName>(
      46             :       "k_critical_vectorpostprocessor",
      47             :       "The name of the vectorpostprocessor that contains critical fracture toughness at crack tip");
      48         134 :   params.addParam<std::string>(
      49             :       "k_critical_vector_name",
      50             :       "The name of the k_critical vector in the k_critical_vectorpostprocessor");
      51          67 :   return params;
      52           0 : }
      53             : 
      54          34 : MeshCut2DFractureUserObject::MeshCut2DFractureUserObject(const InputParameters & parameters)
      55             :   : MeshCut2DUserObjectBase(parameters),
      56          34 :     _growth_increment(getParam<Real>("growth_increment")),
      57          84 :     _use_k(isParamValid("k_critical") || isParamValid("k_critical_vectorpostprocessor")),
      58          68 :     _use_stress(isParamValid("stress_threshold")),
      59         120 :     _k_critical(isParamValid("k_critical") ? getParam<Real>("k_critical")
      60             :                                            : std::numeric_limits<Real>::max()),
      61          42 :     _stress_threshold(_use_stress ? getParam<Real>("stress_threshold")
      62             :                                   : std::numeric_limits<Real>::max()),
      63          64 :     _ki_vpp(_use_k ? &getVectorPostprocessorValue(
      64             :                          "ki_vectorpostprocessor",
      65          64 :                          getParam<VectorPostprocessorName>("ki_vectorpostprocessor"))
      66             :                    : nullptr),
      67          64 :     _kii_vpp(_use_k ? &getVectorPostprocessorValue(
      68             :                           "kii_vectorpostprocessor",
      69          64 :                           getParam<VectorPostprocessorName>("kii_vectorpostprocessor"))
      70             :                     : nullptr),
      71          68 :     _stress_vpp(_use_stress
      72          42 :                     ? &getVectorPostprocessorValue("stress_vectorpostprocessor",
      73          42 :                                                    getParam<std::string>("stress_vector_name"))
      74             :                     : nullptr),
      75          34 :     _k_critical_vpp(
      76          34 :         isParamValid("k_critical_vectorpostprocessor")
      77          39 :             ? &getVectorPostprocessorValue("k_critical_vectorpostprocessor",
      78          44 :                                            getParam<std::string>("k_critical_vector_name"))
      79          34 :             : nullptr)
      80             : {
      81          34 :   if (!_use_k && !_use_stress)
      82           0 :     paramError("k_critical",
      83             :                "Must set crack extension criterion with k_critical, k_critical_vectorpostprocessor "
      84             :                "or stress_threshold.");
      85             : 
      86         120 :   if (isParamValid("k_critical") && isParamValid("k_critical_vectorpostprocessor"))
      87           1 :     paramError("k_critical",
      88             :                "Fracture toughness cannot be specified by both k_critical and "
      89             :                "k_critical_vectorpostprocessor.");
      90          33 : }
      91             : 
      92             : void
      93         300 : MeshCut2DFractureUserObject::initialize()
      94             : {
      95         300 :   _is_mesh_modified = false;
      96         300 :   findActiveBoundaryGrowth();
      97         300 :   growFront();
      98         300 :   addNucleatedCracksToMesh();
      99             :   // update _crack_front_definition with nucleated nodes
     100         300 :   _crack_front_definition->updateNumberOfCrackFrontPoints(
     101             :       _original_and_current_front_node_ids.size());
     102         300 :   _crack_front_definition->isCutterModified(_is_mesh_modified);
     103         300 : }
     104             : 
     105             : void
     106         300 : MeshCut2DFractureUserObject::findActiveBoundaryGrowth()
     107             : {
     108             :   // The k*_vpp & stress_vpp are empty (but not a nullptr) on the very first time step because this
     109             :   // UO is called before the InteractionIntegral or crackFrontStress vpp
     110         300 :   if ((!_ki_vpp || _ki_vpp->size() == 0) && (!_stress_vpp || _stress_vpp->size() == 0))
     111             :     return;
     112             : 
     113         217 :   if (_use_k && ((_ki_vpp->size() != _kii_vpp->size()) ||
     114             :                  (_ki_vpp->size() != _original_and_current_front_node_ids.size())))
     115           0 :     mooseError("ki_vectorpostprocessor and kii_vectorpostprocessor should have the same number of "
     116             :                "crack tips as CrackFrontDefinition.",
     117             :                "\n  ki size = ",
     118           0 :                _ki_vpp->size(),
     119             :                "\n  kii size = ",
     120           0 :                _kii_vpp->size(),
     121             :                "\n  cracktips in MeshCut2DFractureUserObject = ",
     122           0 :                _original_and_current_front_node_ids.size());
     123             : 
     124         217 :   if (_use_stress && ((_stress_vpp->size() != _original_and_current_front_node_ids.size())))
     125           0 :     mooseError("stress_vectorpostprocessor should have the same number of crack front points as "
     126             :                "CrackFrontDefinition.  If it is empty, check that CrackFrontNonlocalStress "
     127             :                "vectorpostprocess has execute_on = TIMESTEP_BEGIN",
     128             :                "\n  stress_vectorpostprocessor size = ",
     129           0 :                _stress_vpp->size(),
     130             :                "\n  cracktips in MeshCut2DFractureUserObject = ",
     131           0 :                _original_and_current_front_node_ids.size());
     132             : 
     133         217 :   if (_k_critical_vpp && ((_k_critical_vpp->size() != _original_and_current_front_node_ids.size())))
     134           0 :     mooseError("k_critical_vectorpostprocessor must have the same number of crack front points as "
     135             :                "CrackFrontDefinition.",
     136             :                "\n  k_critical_vectorpostprocessor size = ",
     137           0 :                _k_critical_vpp->size(),
     138             :                "\n  cracktips in MeshCut2DFractureUserObject = ",
     139           0 :                _original_and_current_front_node_ids.size());
     140             : 
     141         217 :   _active_front_node_growth_vectors.clear();
     142         983 :   for (unsigned int i = 0; i < _original_and_current_front_node_ids.size(); ++i)
     143             :   {
     144         766 :     if (_use_k)
     145             :     {
     146         710 :       Real k_crit = _k_critical;
     147         710 :       if (_k_critical_vpp)
     148         112 :         k_crit = std::min(_k_critical_vpp->at(i), _k_critical);
     149         710 :       Real k_squared = _ki_vpp->at(i) * _ki_vpp->at(i) + _kii_vpp->at(i) * _kii_vpp->at(i);
     150         710 :       if (k_squared > (k_crit * k_crit) && _ki_vpp->at(i) > 0)
     151             :       {
     152             :         // growth direction in crack front coord (cfc) system based on the  max hoop stress
     153             :         // criterion
     154         196 :         Real ki = _ki_vpp->at(i);
     155         196 :         Real kii = _kii_vpp->at(i);
     156         196 :         Real sqrt_k = std::sqrt(ki * ki + kii * kii);
     157         196 :         Real theta = 2 * std::atan((ki - sqrt_k) / (4 * kii));
     158             :         RealVectorValue dir_cfc;
     159         196 :         dir_cfc(0) = std::cos(theta);
     160         196 :         dir_cfc(1) = std::sin(theta);
     161             :         dir_cfc(2) = 0;
     162             : 
     163             :         // growth direction in global coord system based on the max hoop stress criterion
     164             :         RealVectorValue dir_global =
     165         196 :             _crack_front_definition->rotateFromCrackFrontCoordsToGlobal(dir_cfc, i);
     166         196 :         Point dir_global_pt(dir_global(0), dir_global(1), dir_global(2));
     167         196 :         Point nodal_offset = dir_global_pt * _growth_increment;
     168             :         _active_front_node_growth_vectors.push_back(
     169         196 :             std::make_pair(_original_and_current_front_node_ids[i].second, nodal_offset));
     170             :       }
     171             :     }
     172          56 :     else if (_use_stress && _stress_vpp->at(i) > _stress_threshold)
     173             :     {
     174             :       // just extending the crack in the same direction it was going
     175             :       RealVectorValue dir_cfc(1.0, 0.0, 0.0);
     176             :       RealVectorValue dir_global =
     177          24 :           _crack_front_definition->rotateFromCrackFrontCoordsToGlobal(dir_cfc, i);
     178          24 :       Point dir_global_pt(dir_global(0), dir_global(1), dir_global(2));
     179          24 :       Point nodal_offset = dir_global_pt * _growth_increment;
     180             :       _active_front_node_growth_vectors.push_back(
     181          24 :           std::make_pair(_original_and_current_front_node_ids[i].second, nodal_offset));
     182             :     }
     183             :   }
     184             : }

Generated by: LCOV version 1.14