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 "GeometricCut2DUserObject.h" 11 : 12 : // MOOSE includes 13 : #include "MooseError.h" 14 : 15 : #include "libmesh/string_to_enum.h" 16 : 17 : // XFEM includes 18 : #include "XFEMFuncs.h" 19 : 20 : InputParameters 21 416 : GeometricCut2DUserObject::validParams() 22 : { 23 416 : InputParameters params = GeometricCutUserObject::validParams(); 24 832 : params.addParam<Real>("time_start_cut", 0.0, "Start time of geometric cut propagation"); 25 832 : params.addParam<Real>("time_end_cut", 0.0, "End time of geometric cut propagation"); 26 416 : params.addClassDescription("Base class for 2D XFEM Geometric Cut UserObjects"); 27 416 : return params; 28 0 : } 29 : 30 208 : GeometricCut2DUserObject::GeometricCut2DUserObject(const InputParameters & parameters) 31 208 : : GeometricCutUserObject(parameters), _cut_line_endpoints(), _cut_time_ranges() 32 : { 33 208 : _cut_time_ranges.push_back( 34 832 : std::make_pair(getParam<Real>("time_start_cut"), getParam<Real>("time_end_cut"))); 35 208 : } 36 : 37 : bool 38 46000 : GeometricCut2DUserObject::cutElementByGeometry(const Elem * elem, 39 : std::vector<Xfem::CutEdge> & cut_edges, 40 : std::vector<Xfem::CutNode> & cut_nodes) const 41 : { 42 : bool cut_elem = false; 43 : 44 105644 : for (unsigned int cut = 0; cut < _cut_line_endpoints.size(); ++cut) 45 : { 46 59644 : Real fraction = cutFraction(cut); 47 : 48 59644 : if (fraction > 0.0) 49 : { 50 47630 : unsigned int n_sides = elem->n_sides(); 51 : 52 221080 : for (unsigned int i = 0; i < n_sides; ++i) 53 : { 54 : // This returns the lowest-order type of side, which should always 55 : // be an EDGE2 here because this class is for 2D only. 56 173450 : std::unique_ptr<const Elem> curr_side = elem->side_ptr(i); 57 173450 : if (curr_side->type() != EDGE2) 58 0 : mooseError("In cutElementByGeometry element side must be EDGE2, but type is: ", 59 0 : libMesh::Utility::enum_to_string(curr_side->type()), 60 : " base element type is: ", 61 0 : libMesh::Utility::enum_to_string(elem->type())); 62 : 63 : const Node * node1 = curr_side->node_ptr(0); 64 : const Node * node2 = curr_side->node_ptr(1); 65 173450 : Real seg_int_frac = 0.0; 66 : 67 173450 : if (Xfem::intersectSegmentWithCutLine( 68 : *node1, *node2, _cut_line_endpoints[cut], fraction, seg_int_frac)) 69 : { 70 14045 : if (seg_int_frac > Xfem::tol && seg_int_frac < 1.0 - Xfem::tol) 71 : { 72 : cut_elem = true; 73 : Xfem::CutEdge mycut; 74 13508 : mycut._id1 = node1->id(); 75 13508 : mycut._id2 = node2->id(); 76 13508 : mycut._distance = seg_int_frac; 77 13508 : mycut._host_side_id = i; 78 13508 : cut_edges.push_back(mycut); 79 13508 : } 80 537 : else if (seg_int_frac < Xfem::tol) 81 : { 82 : cut_elem = true; 83 : Xfem::CutNode mycut; 84 270 : mycut._id = node1->id(); 85 270 : mycut._host_id = i; 86 270 : cut_nodes.push_back(mycut); 87 : } 88 : } 89 173450 : } 90 : } 91 : } 92 46000 : return cut_elem; 93 : } 94 : 95 : bool 96 0 : GeometricCut2DUserObject::cutElementByGeometry(const Elem * /*elem*/, 97 : std::vector<Xfem::CutFace> & /*cut_faces*/) const 98 : { 99 0 : mooseError("Invalid method: must use vector of element edges for 2D mesh cutting"); 100 : return false; 101 : } 102 : 103 : bool 104 7537 : GeometricCut2DUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & frag_edges, 105 : std::vector<Xfem::CutEdge> & cut_edges) const 106 : { 107 : bool cut_frag = false; 108 : 109 17582 : for (unsigned int cut = 0; cut < _cut_line_endpoints.size(); ++cut) 110 : { 111 10045 : Real fraction = cutFraction(cut); 112 : 113 10045 : if (fraction > 0.0) 114 : { 115 9343 : unsigned int n_sides = frag_edges.size(); 116 : 117 44720 : for (unsigned int i = 0; i < n_sides; ++i) 118 : { 119 35377 : Real seg_int_frac = 0.0; 120 : 121 35377 : if (Xfem::intersectSegmentWithCutLine(frag_edges[i][0], 122 35377 : frag_edges[i][1], 123 : _cut_line_endpoints[cut], 124 : fraction, 125 : seg_int_frac)) 126 : { 127 : cut_frag = true; 128 : Xfem::CutEdge mycut; 129 9894 : mycut._id1 = i; 130 9894 : mycut._id2 = (i < (n_sides - 1) ? (i + 1) : 0); 131 9894 : mycut._distance = seg_int_frac; 132 9894 : mycut._host_side_id = i; 133 9894 : cut_edges.push_back(mycut); 134 : } 135 : } 136 : } 137 : } 138 7537 : return cut_frag; 139 : } 140 : 141 : bool 142 0 : GeometricCut2DUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_faces*/, 143 : std::vector<Xfem::CutFace> & /*cut_faces*/) const 144 : { 145 0 : mooseError("Invalid method: must use vector of element edges for 2D mesh cutting"); 146 : return false; 147 : } 148 : 149 : Real 150 69689 : GeometricCut2DUserObject::cutFraction(unsigned int cut_num) const 151 : { 152 : mooseAssert(_cut_time_ranges.size() > cut_num, 153 : "cut_num is outside the bounds of _cut_time_ranges"); 154 : 155 : Real fraction = 0.0; 156 : 157 69689 : if (_t >= _cut_time_ranges[cut_num].first) 158 : { 159 66842 : if (_t >= _cut_time_ranges[cut_num].second) 160 : fraction = 1.0; 161 : else 162 : { 163 13271 : Real denominator = _cut_time_ranges[cut_num].second - _cut_time_ranges[cut_num].first; 164 13271 : if (MooseUtils::absoluteFuzzyEqual(denominator, 0.0)) 165 0 : mooseError("time_start_cut and time_end_cut cannot have the same value"); 166 13271 : fraction = (_t - _cut_time_ranges[cut_num].first) / denominator; 167 : } 168 : } 169 69689 : return fraction; 170 : }