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 "LevelSetCutUserObject.h" 11 : #include "SubProblem.h" 12 : #include "MooseVariable.h" 13 : #include "libmesh/string_to_enum.h" 14 : 15 : registerMooseObject("XFEMApp", LevelSetCutUserObject); 16 : 17 : InputParameters 18 270 : LevelSetCutUserObject::validParams() 19 : { 20 270 : InputParameters params = GeometricCutUserObject::validParams(); 21 540 : params.addRequiredParam<VariableName>( 22 : "level_set_var", "The name of level set variable used to represent the interface"); 23 270 : params.addClassDescription("XFEM mesh cut by level set function"); 24 540 : params.addParam<CutSubdomainID>( 25 540 : "negative_id", 0, "The CutSubdomainID corresponding to a non-positive signed distance"); 26 540 : params.addParam<CutSubdomainID>( 27 540 : "positive_id", 1, "The CutSubdomainID corresponding to a positive signed distance"); 28 270 : return params; 29 0 : } 30 : 31 135 : LevelSetCutUserObject::LevelSetCutUserObject(const InputParameters & parameters) 32 : : GeometricCutUserObject(parameters), 33 270 : _level_set_var_number(_subproblem 34 135 : .getVariable(_tid, 35 135 : parameters.get<VariableName>("level_set_var"), 36 : Moose::VarKindType::VAR_ANY, 37 : Moose::VarFieldType::VAR_FIELD_STANDARD) 38 : .number()), 39 270 : _system(_subproblem.getSystem(getParam<VariableName>("level_set_var"))), 40 135 : _solution(*_system.current_local_solution.get()), 41 270 : _negative_id(getParam<CutSubdomainID>("negative_id")), 42 405 : _positive_id(getParam<CutSubdomainID>("positive_id")) 43 : { 44 : mooseAssert(_negative_id != _positive_id, 45 : "LevelSetCutUserObject expects different CutSubdomainIDs for the " 46 : "negative_id and the positive_id."); 47 135 : } 48 : 49 : bool 50 11132 : LevelSetCutUserObject::cutElementByGeometry(const Elem * elem, 51 : std::vector<Xfem::CutEdge> & cut_edges, 52 : std::vector<Xfem::CutNode> & /*cut_nodes*/) const 53 : { 54 : bool cut_elem = false; 55 : 56 11132 : unsigned int n_sides = elem->n_sides(); 57 : 58 55660 : for (unsigned int i = 0; i < n_sides; ++i) 59 : { 60 44528 : std::unique_ptr<const Elem> curr_side = elem->side_ptr(i); 61 : 62 44528 : if (curr_side->type() != EDGE2) 63 0 : mooseError("In LevelSetCutUserObject element side must be EDGE2, but type is: ", 64 0 : libMesh::Utility::enum_to_string(curr_side->type()), 65 : " base element type is: ", 66 0 : libMesh::Utility::enum_to_string(elem->type())); 67 : 68 : const Node * node1 = curr_side->node_ptr(0); 69 : const Node * node2 = curr_side->node_ptr(1); 70 : 71 44528 : dof_id_type ls_dof_id_1 = node1->dof_number(_system.number(), _level_set_var_number, 0); 72 44528 : dof_id_type ls_dof_id_2 = node2->dof_number(_system.number(), _level_set_var_number, 0); 73 : 74 44528 : Number ls_node_1 = _solution(ls_dof_id_1); 75 44528 : Number ls_node_2 = _solution(ls_dof_id_2); 76 : 77 44528 : if (ls_node_1 * ls_node_2 < 0) 78 : { 79 : cut_elem = true; 80 : Xfem::CutEdge mycut; 81 2922 : mycut._id1 = node1->id(); 82 2922 : mycut._id2 = node2->id(); 83 2922 : Real seg_int_frac = std::abs(ls_node_1) / std::abs(ls_node_1 - ls_node_2); 84 2922 : mycut._distance = seg_int_frac; 85 2922 : mycut._host_side_id = i; 86 2922 : cut_edges.push_back(mycut); 87 : } 88 44528 : } 89 : 90 11132 : return cut_elem; 91 : } 92 : 93 : bool 94 750 : LevelSetCutUserObject::cutElementByGeometry(const Elem * elem, 95 : std::vector<Xfem::CutFace> & cut_faces) const 96 : { 97 : bool cut_elem = false; 98 : 99 5250 : for (unsigned int i = 0; i < elem->n_sides(); ++i) 100 : { 101 4500 : std::unique_ptr<const Elem> curr_side = elem->side_ptr(i); 102 4500 : if (curr_side->dim() != 2) 103 0 : mooseError("In LevelSetCutUserObject dimension of side must be 2, but it is ", 104 0 : curr_side->dim()); 105 4500 : unsigned int n_edges = curr_side->n_sides(); 106 : 107 : std::vector<unsigned int> cut_edges; 108 : std::vector<Real> cut_pos; 109 : 110 22500 : for (unsigned int j = 0; j < n_edges; j++) 111 : { 112 : // This returns the lowest-order type of side. 113 18000 : std::unique_ptr<const Elem> curr_edge = curr_side->side_ptr(j); 114 18000 : if (curr_edge->type() != EDGE2) 115 0 : mooseError("In LevelSetCutUserObject face edge must be EDGE2, but type is: ", 116 0 : libMesh::Utility::enum_to_string(curr_edge->type()), 117 : " base element type is: ", 118 0 : libMesh::Utility::enum_to_string(elem->type())); 119 : 120 : const Node * node1 = curr_edge->node_ptr(0); 121 : const Node * node2 = curr_edge->node_ptr(1); 122 : 123 18000 : dof_id_type ls_dof_id_1 = node1->dof_number(_system.number(), _level_set_var_number, 0); 124 18000 : dof_id_type ls_dof_id_2 = node2->dof_number(_system.number(), _level_set_var_number, 0); 125 : 126 18000 : Number ls_node_1 = _solution(ls_dof_id_1); 127 18000 : Number ls_node_2 = _solution(ls_dof_id_2); 128 : 129 18000 : if (ls_node_1 * ls_node_2 < 0) 130 : { 131 378 : Real seg_int_frac = std::abs(ls_node_1) / std::abs(ls_node_1 - ls_node_2); 132 378 : cut_edges.push_back(j); 133 378 : cut_pos.push_back(seg_int_frac); 134 : } 135 18000 : } 136 : 137 4500 : if (cut_edges.size() == 2) 138 : { 139 : cut_elem = true; 140 : Xfem::CutFace mycut; 141 189 : mycut._face_id = i; 142 189 : mycut._face_edge.push_back(cut_edges[0]); 143 189 : mycut._face_edge.push_back(cut_edges[1]); 144 189 : mycut._position.push_back(cut_pos[0]); 145 189 : mycut._position.push_back(cut_pos[1]); 146 189 : cut_faces.push_back(mycut); 147 : } 148 4500 : } 149 750 : return cut_elem; 150 : } 151 : 152 : bool 153 598 : LevelSetCutUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_edges*/, 154 : std::vector<Xfem::CutEdge> & /*cut_edges*/) const 155 : { 156 598 : return false; 157 : } 158 : 159 : bool 160 0 : LevelSetCutUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_faces*/, 161 : std::vector<Xfem::CutFace> & /*cut_faces*/) const 162 : { 163 0 : mooseError("cutFragmentByGeometry not yet implemented for 3d level set cutting"); 164 : return false; 165 : } 166 : 167 : const std::vector<Point> 168 0 : LevelSetCutUserObject::getCrackFrontPoints(unsigned int /*num_crack_front_points*/) const 169 : { 170 0 : mooseError("getCrackFrontPoints() is not implemented for this object."); 171 : } 172 : 173 : const std::vector<RealVectorValue> 174 0 : LevelSetCutUserObject::getCrackPlaneNormals(unsigned int /*num_crack_front_points*/) const 175 : { 176 0 : mooseError("getCrackPlaneNormals() is not implemented for this object."); 177 : } 178 : 179 : CutSubdomainID 180 9157 : LevelSetCutUserObject::getCutSubdomainID(const Node * node) const 181 : { 182 9157 : dof_id_type ls_dof_id = node->dof_number(_system.number(), _level_set_var_number, 0); 183 9157 : return _solution(ls_dof_id) > 0.0 ? _positive_id : _negative_id; 184 : }