https://mooseframework.inl.gov
Loading...
Searching...
No Matches
InterfaceMeshCut3DUserObject.C
Go to the documentation of this file.
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
12#include "libmesh/enum_point_locator_type.h"
13
15
18{
20 params.addClassDescription("A userobject to cut a 3D mesh using a 2D cutter mesh.");
21 return params;
22}
23
26{
27 for (const auto & elem : _cutter_mesh->element_ptr_range())
28 if (elem->type() != TRI3)
29 mooseError("InterfaceMeshCut3DUserObject currently only supports TRI3 elements in the "
30 "cutting mesh.");
31}
32
33void
35{
36 _pseudo_normal.clear();
37
38 for (const auto & elem : _cutter_mesh->element_ptr_range())
39 {
40 std::vector<Point> vertices{elem->node_ref(0), elem->node_ref(1), elem->node_ref(2)};
41 std::array<Point, 7> normal;
42 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
43 normal[0] = 2.0 * libMesh::pi * elem_plane.unit_normal(vertices[0]);
44
45 for (unsigned int i = 0; i < elem->n_nodes(); i++)
46 {
47 Point normal_at_node(0.0);
48 const Node & node = elem->node_ref(i);
49
50 for (const auto & node_neigh_elem_id : _node_to_elem_map[node.id()])
51 {
52 const Elem & node_neigh_elem = _cutter_mesh->elem_ref(node_neigh_elem_id);
53 std::vector<Point> vertices{
54 node_neigh_elem.node_ref(0), node_neigh_elem.node_ref(1), node_neigh_elem.node_ref(2)};
55 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
56 unsigned int j = node_neigh_elem.local_node(node.id());
57 Point normal_at_node_j = elem_plane.unit_normal(vertices[0]);
58 unsigned int m = j + 1 < 3 ? j + 1 : j + 1 - 3;
59 unsigned int n = j + 2 < 3 ? j + 2 : j + 2 - 3;
60 Point line_1 = node_neigh_elem.node_ref(j) - node_neigh_elem.node_ref(m);
61 Point line_2 = node_neigh_elem.node_ref(j) - node_neigh_elem.node_ref(n);
62 Real dot = line_1 * line_2;
63 Real lenSq1 = line_1 * line_1;
64 Real lenSq2 = line_2 * line_2;
65 Real angle = std::acos(dot / std::sqrt(lenSq1 * lenSq2));
66 normal_at_node += normal_at_node_j * angle;
67 }
68 normal[1 + i] = normal_at_node;
69 }
70
71 for (unsigned int i = 0; i < elem->n_sides(); i++)
72 {
73 std::vector<Point> vertices{elem->node_ref(0), elem->node_ref(1), elem->node_ref(2)};
74
75 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
76 Point normal_at_edge = libMesh::pi * elem_plane.unit_normal(vertices[0]);
77
78 const Elem * neighbor = elem->neighbor_ptr(i);
79
80 if (neighbor != nullptr)
81 {
82 std::vector<Point> vertices{
83 neighbor->node_ref(0), neighbor->node_ref(1), neighbor->node_ref(2)};
84
85 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
86 normal_at_edge += libMesh::pi * elem_plane.unit_normal(vertices[0]);
87 }
88 normal[4 + i] = normal_at_edge;
89 }
90 _pseudo_normal.insert(std::make_pair(elem->id(), normal));
91 }
92}
93
94Point
95InterfaceMeshCut3DUserObject::nodeNormal(const unsigned int & node_id)
96{
97 Point normal(0.0);
98
99 for (const auto & node_neigh_elem_id : _node_to_elem_map[node_id])
100 {
101 const auto & elem = _cutter_mesh->elem_ref(node_neigh_elem_id);
102 Plane elem_plane(elem.node_ref(0), elem.node_ref(1), elem.node_ref(2));
103 normal += elem_plane.unit_normal(elem.node_ref(0));
104 }
105
106 unsigned int num = _node_to_elem_map[node_id].size();
107 return normal / num;
108}
109
110bool
112 std::vector<Xfem::CutEdge> & /*cut_edges*/,
113 std::vector<Xfem::CutNode> & /*cut_nodes*/) const
114{
115 mooseError("invalid method for 3D mesh cutting");
116 return false;
117}
118
119bool
121 std::vector<Xfem::CutFace> & cut_faces) const
122{
123 mooseAssert(elem->dim() == 3, "Dimension of element to be cut must be 3");
124
125 bool elem_cut = false;
126
127 for (unsigned int i = 0; i < elem->n_sides(); ++i)
128 {
129 // This returns the lowest-order type of side.
130 std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
131
132 mooseAssert(curr_side->dim() == 2, "Side dimension must be 2");
133
134 unsigned int n_edges = curr_side->n_sides();
135
136 std::vector<unsigned int> cut_edges;
137 std::vector<Real> cut_pos;
138
139 for (unsigned int j = 0; j < n_edges; j++)
140 {
141 // This returns the lowest-order type of side.
142 std::unique_ptr<const Elem> curr_edge = curr_side->side_ptr(j);
143 if (curr_edge->type() != EDGE2)
144 mooseError("In cutElementByGeometry face edge must be EDGE2, but type is: ",
145 libMesh::Utility::enum_to_string(curr_edge->type()),
146 " base element type is: ",
148 const Node * node1 = curr_edge->node_ptr(0);
149 const Node * node2 = curr_edge->node_ptr(1);
150
151 for (const auto & cut_elem : _cutter_mesh->element_ptr_range())
152 {
153 std::vector<Point> vertices;
154
155 for (auto & node : cut_elem->node_ref_range())
156 {
157 Point & this_point = node;
158 vertices.push_back(this_point);
159 }
160
161 Point intersection;
162 if (Xfem::intersectWithEdge(*node1, *node2, vertices, intersection) &&
163 std::find(cut_edges.begin(), cut_edges.end(), j) == cut_edges.end())
164 {
165 cut_edges.push_back(j);
166 cut_pos.push_back(Xfem::getRelativePosition(*node1, *node2, intersection));
167 }
168 }
169 }
170
171 // if two edges of an element are cut, it is considered as an element being cut
172 if (cut_edges.size() == 2)
173 {
174 elem_cut = true;
175 Xfem::CutFace mycut;
176 mycut._face_id = i;
177 mycut._face_edge.push_back(cut_edges[0]);
178 mycut._face_edge.push_back(cut_edges[1]);
179 mycut._position.push_back(cut_pos[0]);
180 mycut._position.push_back(cut_pos[1]);
181 cut_faces.push_back(mycut);
182 }
183 }
184
185 return elem_cut;
186}
187
188bool
190 std::vector<std::vector<Point>> & /*frag_edges*/,
191 std::vector<Xfem::CutEdge> & /*cut_edges*/) const
192{
193 mooseError("invalid method for 3D mesh cutting");
194 return false;
195}
196
197bool
199 std::vector<std::vector<Point>> & /*frag_faces*/,
200 std::vector<Xfem::CutFace> & /*cut_faces*/) const
201{
202 mooseError("cutFragmentByGeometry not yet implemented for 3D mesh cutting");
203 return false;
204}
205
206Real
208{
209 std::vector<Real> distance;
210 Real min_dist = std::numeric_limits<Real>::max();
211 for (const auto & cut_elem : _cutter_mesh->element_ptr_range())
212 {
213 std::vector<Point> vertices{
214 cut_elem->node_ref(0), cut_elem->node_ref(1), cut_elem->node_ref(2)};
215 unsigned int region;
216 Point xp;
217 Real dist = Xfem::pointTriangleDistance(
218 p, cut_elem->node_ref(0), cut_elem->node_ref(1), cut_elem->node_ref(2), xp, region);
219
220 distance.push_back(std::abs(dist));
221
222 if (dist < std::abs(min_dist))
223 {
224 min_dist = dist;
225 Point normal = (_pseudo_normal.find(cut_elem->id())->second)[region];
226 if (normal * (p - xp) < 0.0)
227 min_dist *= -1.0;
228 }
229 }
230 std::sort(distance.begin(), distance.end());
231 Real sum_dist = 0.0;
232 for (std::vector<Real>::iterator it = distance.begin(); it != distance.begin() + 1; ++it)
233 sum_dist += *it;
234
235 if (min_dist < 0.0)
236 return -sum_dist / 1.0;
237 else
238 return sum_dist / 1.0;
239}
const Real p
registerMooseObject("XFEMApp", InterfaceMeshCut3DUserObject)
void addClassDescription(const std::string &doc_string)
virtual void calculateNormals() override
calculate the element normal values for all of the elements.
std::unordered_map< unsigned int, std::array< Point, 7 > > _pseudo_normal
Map of information defining cutting elements, stored in this order for each element: pseudo normal,...
virtual bool cutElementByGeometry(const Elem *elem, std::vector< Xfem::CutEdge > &cut_edges, std::vector< Xfem::CutNode > &cut_nodes) const override
virtual Real calculateSignedDistance(Point p) const override
Calculate the signed distance for a given point relative to the surface.
InterfaceMeshCut3DUserObject(const InputParameters &parameters)
virtual bool cutFragmentByGeometry(std::vector< std::vector< Point > > &frag_edges, std::vector< Xfem::CutEdge > &cut_edges) const override
virtual Point nodeNormal(const unsigned int &node_id) override
return the normal at a node in the cutting mesh
std::unordered_map< dof_id_type, std::vector< dof_id_type > > _node_to_elem_map
node to element map of cut mesh
std::shared_ptr< MeshBase > _cutter_mesh
The cutter mesh.
void mooseError(Args &&... args) const
Real getRelativePosition(const Point &p1, const Point &p2, const Point &p)
Get the relative position of p from p1 respect to the total length of the line segment.
Definition XFEMFuncs.C:991
bool intersectWithEdge(const Point &p1, const Point &p2, const std::vector< Point > &vertices, Point &pint)
check if a line intersects with an element defined by vertices calculate the distance from a point to...
Definition XFEMFuncs.C:948
Real pointTriangleDistance(const Point &x0, const Point &x1, const Point &x2, const Point &x3, Point &xp, unsigned int &region)
Calculate the signed distance from a point to a triangle.
Definition XFEMFuncs.C:836
std::string enum_to_string(const T e)
const Real pi
Data structure defining a cut through a face.
unsigned int _face_id
ID of the cut face.
std::vector< Real > _position
Fractional distance along the cut edges where the cut is located.
std::vector< unsigned int > _face_edge
IDs of all cut faces.
Real distance(const Point &p)