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

Generated by: LCOV version 1.14