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