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 : }