www.mooseframework.org
GeometricCut2DUserObject.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
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 template <>
21 InputParameters
23 {
24  InputParameters params = validParams<GeometricCutUserObject>();
25  params.addParam<Real>("time_start_cut", 0.0, "Start time of geometric cut propagation");
26  params.addParam<Real>("time_end_cut", 0.0, "End time of geometric cut propagation");
27  params.addClassDescription("Base class for 2D XFEM Geometric Cut UserObjects");
28  return params;
29 }
30 
31 GeometricCut2DUserObject::GeometricCut2DUserObject(const InputParameters & parameters)
32  : GeometricCutUserObject(parameters), _cut_line_endpoints(), _cut_time_ranges()
33 {
34  _cut_time_ranges.push_back(
35  std::make_pair(getParam<Real>("time_start_cut"), getParam<Real>("time_end_cut")));
36 }
37 
38 bool
40  std::vector<Xfem::CutEdge> & cut_edges,
41  std::vector<Xfem::CutNode> & cut_nodes,
42  Real time) const
43 {
44  bool cut_elem = false;
45 
46  for (unsigned int cut = 0; cut < _cut_line_endpoints.size(); ++cut)
47  {
48  Real fraction = cutFraction(cut, time);
49 
50  if (fraction > 0.0)
51  {
52  unsigned int n_sides = elem->n_sides();
53 
54  for (unsigned int i = 0; i < n_sides; ++i)
55  {
56  // This returns the lowest-order type of side, which should always
57  // be an EDGE2 here because this class is for 2D only.
58  std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
59  if (curr_side->type() != EDGE2)
60  mooseError("In cutElementByGeometry element side must be EDGE2, but type is: ",
61  libMesh::Utility::enum_to_string(curr_side->type()),
62  " base element type is: ",
63  libMesh::Utility::enum_to_string(elem->type()));
64 
65  const Node * node1 = curr_side->node_ptr(0);
66  const Node * node2 = curr_side->node_ptr(1);
67  Real seg_int_frac = 0.0;
68 
70  *node1, *node2, _cut_line_endpoints[cut], fraction, seg_int_frac))
71  {
72  if (seg_int_frac > Xfem::tol && seg_int_frac < 1.0 - Xfem::tol)
73  {
74  cut_elem = true;
75  Xfem::CutEdge mycut;
76  mycut._id1 = node1->id();
77  mycut._id2 = node2->id();
78  mycut._distance = seg_int_frac;
79  mycut._host_side_id = i;
80  cut_edges.push_back(mycut);
81  }
82  else if (seg_int_frac < Xfem::tol)
83  {
84  cut_elem = true;
85  Xfem::CutNode mycut;
86  mycut._id = node1->id();
87  mycut._host_id = i;
88  cut_nodes.push_back(mycut);
89  }
90  }
91  }
92  }
93  }
94  return cut_elem;
95 }
96 
97 bool
99  std::vector<Xfem::CutFace> & /*cut_faces*/,
100  Real /*time*/) const
101 {
102  mooseError("Invalid method: must use vector of element edges for 2D mesh cutting");
103  return false;
104 }
105 
106 bool
107 GeometricCut2DUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & frag_edges,
108  std::vector<Xfem::CutEdge> & cut_edges,
109  Real time) const
110 {
111  bool cut_frag = false;
112 
113  for (unsigned int cut = 0; cut < _cut_line_endpoints.size(); ++cut)
114  {
115  Real fraction = cutFraction(cut, time);
116 
117  if (fraction > 0.0)
118  {
119  unsigned int n_sides = frag_edges.size();
120 
121  for (unsigned int i = 0; i < n_sides; ++i)
122  {
123  Real seg_int_frac = 0.0;
124 
125  if (IntersectSegmentWithCutLine(frag_edges[i][0],
126  frag_edges[i][1],
127  _cut_line_endpoints[cut],
128  fraction,
129  seg_int_frac))
130  {
131  cut_frag = true;
132  Xfem::CutEdge mycut;
133  mycut._id1 = i;
134  mycut._id2 = (i < (n_sides - 1) ? (i + 1) : 0);
135  mycut._distance = seg_int_frac;
136  mycut._host_side_id = i;
137  cut_edges.push_back(mycut);
138  }
139  }
140  }
141  }
142  return cut_frag;
143 }
144 
145 bool
146 GeometricCut2DUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_faces*/,
147  std::vector<Xfem::CutFace> & /*cut_faces*/,
148  Real /*time*/) const
149 {
150  mooseError("Invalid method: must use vector of element edges for 2D mesh cutting");
151  return false;
152 }
153 
154 bool
156  const Point & segment_point1,
157  const Point & segment_point2,
158  const std::pair<Point, Point> & cutting_line_points,
159  const Real & cutting_line_fraction,
160  Real & segment_intersection_fraction) const
161 {
162  // Use the algorithm described here to determine whether a line segment is intersected
163  // by a cutting line, and to compute the fraction along that line where the intersection
164  // occurs:
165  // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
166 
167  bool cut_segment = false;
168  Point seg_dir = segment_point2 - segment_point1;
169  Point cut_dir = cutting_line_points.second - cutting_line_points.first;
170  Point cut_start_to_seg_start = segment_point1 - cutting_line_points.first;
171 
172  Real cut_dir_cross_seg_dir = crossProduct2D(cut_dir, seg_dir);
173 
174  if (std::abs(cut_dir_cross_seg_dir) > Xfem::tol)
175  {
176  // Fraction of the distance along the cutting segment where it intersects the edge segment
177  Real cut_int_frac = crossProduct2D(cut_start_to_seg_start, seg_dir) / cut_dir_cross_seg_dir;
178 
179  if (cut_int_frac >= 0.0 && cut_int_frac <= cutting_line_fraction)
180  { // Cutting segment intersects the line of the edge segment, but the intersection point may
181  // be
182  // outside the segment
183  Real int_frac = crossProduct2D(cut_start_to_seg_start, cut_dir) / cut_dir_cross_seg_dir;
184  if (int_frac >= 0.0 &&
185  int_frac <= 1.0) // TODO: revisit end cases for intersections with corners
186  {
187  cut_segment = true;
188  segment_intersection_fraction = int_frac;
189  }
190  }
191  }
192  return cut_segment;
193 }
194 
195 Real
196 GeometricCut2DUserObject::crossProduct2D(const Point & point_a, const Point & point_b) const
197 {
198  return (point_a(0) * point_b(1) - point_b(0) * point_a(1));
199 }
200 
201 Real
202 GeometricCut2DUserObject::cutFraction(unsigned int cut_num, Real time) const
203 {
204  mooseAssert(_cut_time_ranges.size() > cut_num,
205  "cut_num is outside the bounds of _cut_time_ranges");
206 
207  Real fraction = 0.0;
208 
209  if (time >= _cut_time_ranges[cut_num].first)
210  {
211  if (time >= _cut_time_ranges[cut_num].second)
212  fraction = 1.0;
213  else
214  {
215  Real denominator = _cut_time_ranges[cut_num].second - _cut_time_ranges[cut_num].first;
216  if (MooseUtils::absoluteFuzzyEqual(denominator, 0.0))
217  mooseError("time_start_cut and time_end_cut cannot have the same value");
218  fraction = (time - _cut_time_ranges[cut_num].first) / denominator;
219  }
220  }
221  return fraction;
222 }
Xfem::CutEdge::_id1
unsigned int _id1
ID of the first node on the edge.
Definition: GeometricCutUserObject.h:29
GeometricCut2DUserObject::cutElementByGeometry
virtual bool cutElementByGeometry(const Elem *elem, std::vector< Xfem::CutEdge > &cut_edges, std::vector< Xfem::CutNode > &cut_nodes, Real time) const override
Check to see whether a specified 2D element should be cut based on geometric conditions.
Definition: GeometricCut2DUserObject.C:39
GeometricCut2DUserObject::GeometricCut2DUserObject
GeometricCut2DUserObject(const InputParameters &parameters)
Definition: GeometricCut2DUserObject.C:31
Xfem::CutEdge::_distance
Real _distance
Fractional distance along the edge (from node 1 to 2) where the cut is located.
Definition: GeometricCutUserObject.h:33
Xfem::CutNode::_host_id
unsigned int _host_id
Local ID of this node in the host element.
Definition: GeometricCutUserObject.h:60
validParams< GeometricCutUserObject >
InputParameters validParams< GeometricCutUserObject >()
Definition: GeometricCutUserObject.C:25
GeometricCut2DUserObject::cutFraction
virtual Real cutFraction(unsigned int cut_num, Real time) const
Find the fractional distance along a specified cut line for the current time that is currently active...
Definition: GeometricCut2DUserObject.C:202
GeometricCut2DUserObject::_cut_time_ranges
std::vector< std::pair< Real, Real > > _cut_time_ranges
Vector of start/end times for each cut segment.
Definition: GeometricCut2DUserObject.h:61
Xfem::CutEdge::_id2
unsigned int _id2
ID of the second node on the edge.
Definition: GeometricCutUserObject.h:31
Xfem::CutEdge::_host_side_id
unsigned int _host_side_id
Local ID of this side in the host element.
Definition: GeometricCutUserObject.h:35
GeometricCut2DUserObject.h
GeometricCutUserObject
Definition: GeometricCutUserObject.h:106
XFEMFuncs.h
GeometricCut2DUserObject::crossProduct2D
Real crossProduct2D(const Point &point_a, const Point &point_b) const
Definition: GeometricCut2DUserObject.C:196
GeometricCut2DUserObject::IntersectSegmentWithCutLine
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
Definition: GeometricCut2DUserObject.C:155
Xfem::tol
static const double tol
Definition: XFEMFuncs.h:20
GeometricCut2DUserObject::cutFragmentByGeometry
virtual bool cutFragmentByGeometry(std::vector< std::vector< Point >> &frag_edges, std::vector< Xfem::CutEdge > &cut_edges, Real time) const override
Check to see whether a fragment of a 2D element should be cut based on geometric conditions.
Definition: GeometricCut2DUserObject.C:107
Xfem::CutNode
Data structure defining a cut through a node.
Definition: GeometricCutUserObject.h:55
GeometricCut2DUserObject::_cut_line_endpoints
std::vector< std::pair< Point, Point > > _cut_line_endpoints
Definition: GeometricCut2DUserObject.h:41
Xfem::CutNode::_id
unsigned int _id
ID of the cut node.
Definition: GeometricCutUserObject.h:58
validParams< GeometricCut2DUserObject >
InputParameters validParams< GeometricCut2DUserObject >()
Definition: GeometricCut2DUserObject.C:22
Xfem::CutEdge
Data structure defining a cut on an element edge.
Definition: GeometricCutUserObject.h:26