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