www.mooseframework.org
GeometricCut2DUserObject.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
3 /* */
4 /* All contents are licensed under LGPL V2.1 */
5 /* See LICENSE for full restrictions */
6 /****************************************************************/
7 
9 
10 // MOOSE includes
11 #include "MooseError.h"
12 
13 #include "libmesh/string_to_enum.h"
14 
15 // XFEM includes
16 #include "XFEMFuncs.h"
17 
18 template <>
19 InputParameters
21 {
22  // Get input parameters from parent class
23  InputParameters params = validParams<GeometricCutUserObject>();
24 
25  // Class description
26  params.addClassDescription("Base class for 2D XFEM Geometric Cut UserObjects");
27  // Return the parameters
28  return params;
29 }
30 
31 GeometricCut2DUserObject::GeometricCut2DUserObject(const InputParameters & parameters)
32  : GeometricCutUserObject(parameters), _cut_line_endpoints()
33 {
34 }
35 
36 bool
38 {
39  bool is_cut_active = false;
40 
41  for (unsigned int cut = 0; cut < _cut_line_endpoints.size(); ++cut)
42  if (cutFraction(cut, time) > 0)
43  is_cut_active = true;
44 
45  return is_cut_active;
46 }
47 
48 bool
50  std::vector<CutEdge> & cut_edges,
51  std::vector<CutNode> & cut_nodes,
52  Real time) const
53 {
54  bool cut_elem = false;
55 
56  for (unsigned int cut = 0; cut < _cut_line_endpoints.size(); ++cut)
57  {
58  Real fraction = cutFraction(cut, time);
59 
60  if (fraction > 0.0)
61  {
62  unsigned int n_sides = elem->n_sides();
63 
64  for (unsigned int i = 0; i < n_sides; ++i)
65  {
66  // This returns the lowest-order type of side, which should always
67  // be an EDGE2 here because this class is for 2D only.
68  std::unique_ptr<Elem> curr_side = elem->side(i);
69  if (curr_side->type() != EDGE2)
70  mooseError("In cutElementByGeometry element side must be EDGE2, but type is: ",
71  libMesh::Utility::enum_to_string(curr_side->type()),
72  " base element type is: ",
73  libMesh::Utility::enum_to_string(elem->type()));
74 
75  const Node * node1 = curr_side->get_node(0);
76  const Node * node2 = curr_side->get_node(1);
77  Real seg_int_frac = 0.0;
78 
80  *node1, *node2, _cut_line_endpoints[cut], fraction, seg_int_frac))
81  {
82  if (seg_int_frac > Xfem::tol && seg_int_frac < 1.0 - Xfem::tol)
83  {
84  cut_elem = true;
85  CutEdge mycut;
86  mycut.id1 = node1->id();
87  mycut.id2 = node2->id();
88  mycut.distance = seg_int_frac;
89  mycut.host_side_id = i;
90  cut_edges.push_back(mycut);
91  }
92  else if (seg_int_frac < Xfem::tol)
93  {
94  cut_elem = true;
95  CutNode mycut;
96  mycut.id = node1->id();
97  mycut.host_id = i;
98  cut_nodes.push_back(mycut);
99  }
100  }
101  }
102  }
103  }
104  return cut_elem;
105 }
106 
107 bool
109  std::vector<CutFace> & /*cut_faces*/,
110  Real /*time*/) const
111 {
112  mooseError("Invalid method: must use vector of element edges for 2D mesh cutting");
113  return false;
114 }
115 
116 bool
117 GeometricCut2DUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & frag_edges,
118  std::vector<CutEdge> & cut_edges,
119  Real time) const
120 {
121  bool cut_frag = false;
122 
123  for (unsigned int cut = 0; cut < _cut_line_endpoints.size(); ++cut)
124  {
125  Real fraction = cutFraction(cut, time);
126 
127  if (fraction > 0.0)
128  {
129  unsigned int n_sides = frag_edges.size();
130 
131  for (unsigned int i = 0; i < n_sides; ++i)
132  {
133  Real seg_int_frac = 0.0;
134 
135  if (IntersectSegmentWithCutLine(frag_edges[i][0],
136  frag_edges[i][1],
137  _cut_line_endpoints[cut],
138  fraction,
139  seg_int_frac))
140  {
141  cut_frag = true;
142  CutEdge mycut;
143  mycut.id1 = i;
144  mycut.id2 = (i < (n_sides - 1) ? (i + 1) : 0);
145  mycut.distance = seg_int_frac;
146  mycut.host_side_id = i;
147  cut_edges.push_back(mycut);
148  }
149  }
150  }
151  }
152  return cut_frag;
153 }
154 
155 bool
156 GeometricCut2DUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_faces*/,
157  std::vector<CutFace> & /*cut_faces*/,
158  Real /*time*/) const
159 {
160  mooseError("Invalid method: must use vector of element edges for 2D mesh cutting");
161  return false;
162 }
163 
164 bool
166  const Point & segment_point1,
167  const Point & segment_point2,
168  const std::pair<Point, Point> & cutting_line_points,
169  const Real & cutting_line_fraction,
170  Real & segment_intersection_fraction) const
171 {
172  // Use the algorithm described here to determine whether a line segment is intersected
173  // by a cutting line, and to compute the fraction along that line where the intersection
174  // occurs:
175  // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
176 
177  bool cut_segment = false;
178  Point seg_dir = segment_point2 - segment_point1;
179  Point cut_dir = cutting_line_points.second - cutting_line_points.first;
180  Point cut_start_to_seg_start = segment_point1 - cutting_line_points.first;
181 
182  Real cut_dir_cross_seg_dir = crossProduct2D(cut_dir, seg_dir);
183 
184  if (std::abs(cut_dir_cross_seg_dir) > Xfem::tol)
185  {
186  // Fraction of the distance along the cutting segment where it intersects the edge segment
187  Real cut_int_frac = crossProduct2D(cut_start_to_seg_start, seg_dir) / cut_dir_cross_seg_dir;
188 
189  if (cut_int_frac >= 0.0 && cut_int_frac <= cutting_line_fraction)
190  { // Cutting segment intersects the line of the edge segment, but the intersection point may
191  // be
192  // outside the segment
193  Real int_frac = crossProduct2D(cut_start_to_seg_start, cut_dir) / cut_dir_cross_seg_dir;
194  if (int_frac >= 0.0 &&
195  int_frac <= 1.0) // TODO: revisit end cases for intersections with corners
196  {
197  cut_segment = true;
198  segment_intersection_fraction = int_frac;
199  }
200  }
201  }
202  return cut_segment;
203 }
204 
205 Real
206 GeometricCut2DUserObject::crossProduct2D(const Point & point_a, const Point & point_b) const
207 {
208  return (point_a(0) * point_b(1) - point_b(0) * point_a(1));
209 }
std::vector< std::pair< Point, Point > > _cut_line_endpoints
Real cutFraction(unsigned int cut_num, Real time) const
unsigned int id2
bool IntersectSegmentWithCutLine(const Point &segment_point1, const Point &segment_point2, const std::pair< Point, Point > &cutting_line_points, const Real &cutting_line_fraction, Real &segment_intersection_fraction) const
unsigned int id1
Real crossProduct2D(const Point &point_a, const Point &point_b) const
virtual bool active(Real time) const override
InputParameters validParams< GeometricCutUserObject >()
GeometricCut2DUserObject(const InputParameters &parameters)
static const double tol
Definition: XFEMFuncs.h:26
virtual bool cutFragmentByGeometry(std::vector< std::vector< Point >> &frag_edges, std::vector< CutEdge > &cut_edges, Real time) const override
unsigned int id
unsigned int host_side_id
InputParameters validParams< GeometricCut2DUserObject >()
virtual bool cutElementByGeometry(const Elem *elem, std::vector< CutEdge > &cut_edges, std::vector< CutNode > &cut_nodes, Real time) const override
unsigned int host_id