LCOV - code coverage report
Current view: top level - src/userobjects - MeshCut2DFractureUserObject.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31613 (c7d555) with base 7323e9 Lines: 71 83 85.5 %
Date: 2025-11-06 14:19:40 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          75 : MeshCut2DFractureUserObject::validParams()
      26             : {
      27          75 :   InputParameters params = MeshCut2DUserObjectBase::validParams();
      28          75 :   params.addClassDescription("XFEM mesh cutter for 2D models that defines cuts with a"
      29             :                              "mesh and uses fracture integrals to determine growth");
      30         150 :   params.addRequiredParam<Real>("growth_increment",
      31             :                                 "Length to grow crack if k>k_critical or stress>stress_threshold");
      32         150 :   params.addParam<Real>("k_critical", "Critical fracture toughness.");
      33         150 :   params.addParam<Real>("stress_threshold", "Stress threshold for growing crack");
      34         150 :   params.addParam<VectorPostprocessorName>(
      35             :       "ki_vectorpostprocessor", "II_KI_1", "The name of the vectorpostprocessor that contains KI");
      36         150 :   params.addParam<VectorPostprocessorName>("kii_vectorpostprocessor",
      37             :                                            "II_KII_1",
      38             :                                            "The name of the vectorpostprocessor that contains KII");
      39         150 :   params.addParam<VectorPostprocessorName>(
      40             :       "stress_vectorpostprocessor",
      41             :       "The name of the vectorpostprocessor that contains crack front stress");
      42         150 :   params.addParam<std::string>("stress_vector_name",
      43             :                                "crack_tip_stress",
      44             :                                "The name of the stress vector in the stress_vectorpostprocessor");
      45         150 :   params.addParam<VectorPostprocessorName>(
      46             :       "k_critical_vectorpostprocessor",
      47             :       "The name of the vectorpostprocessor that contains critical fracture toughness at crack tip");
      48         150 :   params.addParam<std::string>(
      49             :       "k_critical_vector_name",
      50             :       "The name of the k_critical vector in the k_critical_vectorpostprocessor");
      51          75 :   return params;
      52           0 : }
      53             : 
      54          38 : MeshCut2DFractureUserObject::MeshCut2DFractureUserObject(const InputParameters & parameters)
      55             :   : MeshCut2DUserObjectBase(parameters),
      56          38 :     _growth_increment(getParam<Real>("growth_increment")),
      57          92 :     _use_k(isParamValid("k_critical") || isParamValid("k_critical_vectorpostprocessor")),
      58          76 :     _use_stress(isParamValid("stress_threshold")),
      59         136 :     _k_critical(isParamValid("k_critical") ? getParam<Real>("k_critical")
      60             :                                            : std::numeric_limits<Real>::max()),
      61          46 :     _stress_threshold(_use_stress ? getParam<Real>("stress_threshold")
      62             :                                   : std::numeric_limits<Real>::max()),
      63          72 :     _ki_vpp(_use_k ? &getVectorPostprocessorValue(
      64             :                          "ki_vectorpostprocessor",
      65          72 :                          getParam<VectorPostprocessorName>("ki_vectorpostprocessor"))
      66             :                    : nullptr),
      67          72 :     _kii_vpp(_use_k ? &getVectorPostprocessorValue(
      68             :                           "kii_vectorpostprocessor",
      69          72 :                           getParam<VectorPostprocessorName>("kii_vectorpostprocessor"))
      70             :                     : nullptr),
      71          76 :     _stress_vpp(_use_stress
      72          46 :                     ? &getVectorPostprocessorValue("stress_vectorpostprocessor",
      73          46 :                                                    getParam<std::string>("stress_vector_name"))
      74             :                     : nullptr),
      75          38 :     _k_critical_vpp(
      76          38 :         isParamValid("k_critical_vectorpostprocessor")
      77          43 :             ? &getVectorPostprocessorValue("k_critical_vectorpostprocessor",
      78          48 :                                            getParam<std::string>("k_critical_vector_name"))
      79          38 :             : nullptr)
      80             : {
      81          38 :   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         136 :   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          37 : }
      91             : 
      92             : void
      93         322 : MeshCut2DFractureUserObject::initialize()
      94             : {
      95         322 :   _is_mesh_modified = false;
      96         322 :   findActiveBoundaryGrowth();
      97         322 :   growFront();
      98         322 :   addNucleatedCracksToMesh();
      99             :   // update _crack_front_definition with nucleated nodes
     100         322 :   _crack_front_definition->updateNumberOfCrackFrontPoints(
     101             :       _original_and_current_front_node_ids.size());
     102         322 :   _crack_front_definition->isCutterModified(_is_mesh_modified);
     103         322 : }
     104             : 
     105             : void
     106         322 : 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         322 :   if ((!_ki_vpp || _ki_vpp->size() == 0) && (!_stress_vpp || _stress_vpp->size() == 0))
     111             :     return;
     112             : 
     113         263 :   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         263 :   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.",
     127             :                "\n  stress_vectorpostprocessor size = ",
     128           0 :                _stress_vpp->size(),
     129             :                "\n  cracktips in MeshCut2DFractureUserObject = ",
     130           0 :                _original_and_current_front_node_ids.size());
     131             : 
     132         263 :   if (_k_critical_vpp && ((_k_critical_vpp->size() != _original_and_current_front_node_ids.size())))
     133           0 :     mooseError("k_critical_vectorpostprocessor must have the same number of crack front points as "
     134             :                "CrackFrontDefinition.",
     135             :                "\n  k_critical_vectorpostprocessor size = ",
     136           0 :                _k_critical_vpp->size(),
     137             :                "\n  cracktips in MeshCut2DFractureUserObject = ",
     138           0 :                _original_and_current_front_node_ids.size());
     139             : 
     140         263 :   _active_front_node_growth_vectors.clear();
     141        1137 :   for (unsigned int i = 0; i < _original_and_current_front_node_ids.size(); ++i)
     142             :   {
     143             :     // only extend crack with kcrit or nonlocal stress, never both.
     144             :     bool was_crack_extended_kcrit = false;
     145         874 :     if (_use_k)
     146             :     {
     147         794 :       Real k_crit = _k_critical;
     148         794 :       if (_k_critical_vpp)
     149         132 :         k_crit = std::min(_k_critical_vpp->at(i), _k_critical);
     150             : 
     151         794 :       Real k_squared = _ki_vpp->at(i) * _ki_vpp->at(i) + _kii_vpp->at(i) * _kii_vpp->at(i);
     152         794 :       if (k_squared > (k_crit * k_crit) && _ki_vpp->at(i) > 0)
     153             :       {
     154             :         was_crack_extended_kcrit = true;
     155             :         // growth direction in crack front coord (cfc) system based on the  max hoop stress
     156             :         // criterion
     157         160 :         Real ki = _ki_vpp->at(i);
     158         160 :         Real kii = _kii_vpp->at(i);
     159         160 :         Real sqrt_k = std::sqrt(ki * ki + kii * kii);
     160         160 :         Real theta = 2 * std::atan((ki - sqrt_k) / (4 * kii));
     161             :         RealVectorValue dir_cfc;
     162         160 :         dir_cfc(0) = std::cos(theta);
     163         160 :         dir_cfc(1) = std::sin(theta);
     164             :         dir_cfc(2) = 0;
     165             : 
     166             :         // growth direction in global coord system based on the max hoop stress criterion
     167             :         RealVectorValue dir_global =
     168         160 :             _crack_front_definition->rotateFromCrackFrontCoordsToGlobal(dir_cfc, i);
     169         160 :         Point dir_global_pt(dir_global(0), dir_global(1), dir_global(2));
     170         160 :         Point nodal_offset = dir_global_pt * _growth_increment;
     171             :         _active_front_node_growth_vectors.push_back(
     172         160 :             std::make_pair(_original_and_current_front_node_ids[i].second, nodal_offset));
     173             :       }
     174             :     }
     175         874 :     if (_use_stress && !was_crack_extended_kcrit && _stress_vpp->at(i) > _stress_threshold)
     176             :     {
     177             :       // crack will only be extended if it was not already extended by kcrit
     178             :       // just extending the crack in the same direction it was going
     179             :       RealVectorValue dir_cfc(1.0, 0.0, 0.0);
     180             :       RealVectorValue dir_global =
     181          44 :           _crack_front_definition->rotateFromCrackFrontCoordsToGlobal(dir_cfc, i);
     182          44 :       Point dir_global_pt(dir_global(0), dir_global(1), dir_global(2));
     183          44 :       Point nodal_offset = dir_global_pt * _growth_increment;
     184             :       _active_front_node_growth_vectors.push_back(
     185          44 :           std::make_pair(_original_and_current_front_node_ids[i].second, nodal_offset));
     186             :     }
     187             :   }
     188             : }

Generated by: LCOV version 1.14