https://mooseframework.inl.gov
Loading...
Searching...
No Matches
LevelSetCutUserObject.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
11#include "SubProblem.h"
12#include "MooseVariable.h"
13#include "libmesh/string_to_enum.h"
14
16
19{
21 params.addRequiredParam<VariableName>(
22 "level_set_var", "The name of level set variable used to represent the interface");
23 params.addClassDescription("XFEM mesh cut by level set function");
25 "negative_id", 0, "The CutSubdomainID corresponding to a non-positive signed distance");
27 "positive_id", 1, "The CutSubdomainID corresponding to a positive signed distance");
28 return params;
29}
30
32 : GeometricCutUserObject(parameters),
33 _level_set_var_number(_subproblem
34 .getVariable(_tid,
35 parameters.get<VariableName>("level_set_var"),
36 Moose::VarKindType::VAR_ANY,
37 Moose::VarFieldType::VAR_FIELD_STANDARD)
38 .number()),
39 _system(_subproblem.getSystem(getParam<VariableName>("level_set_var"))),
40 _solution(*_system.current_local_solution.get()),
41 _negative_id(getParam<CutSubdomainID>("negative_id")),
42 _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}
48
49bool
51 std::vector<Xfem::CutEdge> & cut_edges,
52 std::vector<Xfem::CutNode> & /*cut_nodes*/) const
53{
54 bool cut_elem = false;
55
56 unsigned int n_sides = elem->n_sides();
57
58 for (unsigned int i = 0; i < n_sides; ++i)
59 {
60 std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
61
62 if (curr_side->type() != EDGE2)
63 mooseError("In LevelSetCutUserObject element side must be EDGE2, but type is: ",
64 libMesh::Utility::enum_to_string(curr_side->type()),
65 " base element type is: ",
67
68 const Node * node1 = curr_side->node_ptr(0);
69 const Node * node2 = curr_side->node_ptr(1);
70
71 dof_id_type ls_dof_id_1 = node1->dof_number(_system.number(), _level_set_var_number, 0);
72 dof_id_type ls_dof_id_2 = node2->dof_number(_system.number(), _level_set_var_number, 0);
73
74 Number ls_node_1 = _solution(ls_dof_id_1);
75 Number ls_node_2 = _solution(ls_dof_id_2);
76
77 if (ls_node_1 * ls_node_2 < 0)
78 {
79 cut_elem = true;
80 Xfem::CutEdge mycut;
81 mycut._id1 = node1->id();
82 mycut._id2 = node2->id();
83 Real seg_int_frac = std::abs(ls_node_1) / std::abs(ls_node_1 - ls_node_2);
84 mycut._distance = seg_int_frac;
85 mycut._host_side_id = i;
86 cut_edges.push_back(mycut);
87 }
88 }
89
90 return cut_elem;
91}
92
93bool
95 std::vector<Xfem::CutFace> & cut_faces) const
96{
97 bool cut_elem = false;
98
99 for (unsigned int i = 0; i < elem->n_sides(); ++i)
100 {
101 std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
102 if (curr_side->dim() != 2)
103 mooseError("In LevelSetCutUserObject dimension of side must be 2, but it is ",
104 curr_side->dim());
105 unsigned int n_edges = curr_side->n_sides();
106
107 std::vector<unsigned int> cut_edges;
108 std::vector<Real> cut_pos;
109
110 for (unsigned int j = 0; j < n_edges; j++)
111 {
112 // This returns the lowest-order type of side.
113 std::unique_ptr<const Elem> curr_edge = curr_side->side_ptr(j);
114 if (curr_edge->type() != EDGE2)
115 mooseError("In LevelSetCutUserObject face edge must be EDGE2, but type is: ",
116 libMesh::Utility::enum_to_string(curr_edge->type()),
117 " base element type is: ",
119
120 const Node * node1 = curr_edge->node_ptr(0);
121 const Node * node2 = curr_edge->node_ptr(1);
122
123 dof_id_type ls_dof_id_1 = node1->dof_number(_system.number(), _level_set_var_number, 0);
124 dof_id_type ls_dof_id_2 = node2->dof_number(_system.number(), _level_set_var_number, 0);
125
126 Number ls_node_1 = _solution(ls_dof_id_1);
127 Number ls_node_2 = _solution(ls_dof_id_2);
128
129 if (ls_node_1 * ls_node_2 < 0)
130 {
131 Real seg_int_frac = std::abs(ls_node_1) / std::abs(ls_node_1 - ls_node_2);
132 cut_edges.push_back(j);
133 cut_pos.push_back(seg_int_frac);
134 }
135 }
136
137 if (cut_edges.size() == 2)
138 {
139 cut_elem = true;
140 Xfem::CutFace mycut;
141 mycut._face_id = i;
142 mycut._face_edge.push_back(cut_edges[0]);
143 mycut._face_edge.push_back(cut_edges[1]);
144 mycut._position.push_back(cut_pos[0]);
145 mycut._position.push_back(cut_pos[1]);
146 cut_faces.push_back(mycut);
147 }
148 }
149 return cut_elem;
150}
151
152bool
153LevelSetCutUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_edges*/,
154 std::vector<Xfem::CutEdge> & /*cut_edges*/) const
155{
156 return false;
157}
158
159bool
160LevelSetCutUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_faces*/,
161 std::vector<Xfem::CutFace> & /*cut_faces*/) const
162{
163 mooseError("cutFragmentByGeometry not yet implemented for 3d level set cutting");
164 return false;
165}
166
167const std::vector<Point>
168LevelSetCutUserObject::getCrackFrontPoints(unsigned int /*num_crack_front_points*/) const
169{
170 mooseError("getCrackFrontPoints() is not implemented for this object.");
171}
172
173const std::vector<RealVectorValue>
174LevelSetCutUserObject::getCrackPlaneNormals(unsigned int /*num_crack_front_points*/) const
175{
176 mooseError("getCrackPlaneNormals() is not implemented for this object.");
177}
178
181{
182 dof_id_type ls_dof_id = node->dof_number(_system.number(), _level_set_var_number, 0);
183 return _solution(ls_dof_id) > 0.0 ? _positive_id : _negative_id;
184}
registerMooseObject("XFEMApp", LevelSetCutUserObject)
unsigned int CutSubdomainID
static InputParameters validParams()
Factory constructor, takes parameters so that all derived classes can be built using the same constru...
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
const System & _system
System reference.
virtual bool cutFragmentByGeometry(std::vector< std::vector< Point > > &frag_edges, std::vector< Xfem::CutEdge > &cut_edges) const override
static InputParameters validParams()
const CutSubdomainID _negative_id
The ID for the negative side of the cut.
const unsigned int _level_set_var_number
The variable number of the level set variable we using to define the cuts.
virtual const std::vector< RealVectorValue > getCrackPlaneNormals(unsigned int num_crack_front_points) const override
get a set of normal vectors along a crack front from a XFEM GeometricCutUserObject
LevelSetCutUserObject(const InputParameters &parameters)
const NumericVector< Number > & _solution
The subproblem solution vector.
virtual bool cutElementByGeometry(const Elem *elem, std::vector< Xfem::CutEdge > &cut_edges, std::vector< Xfem::CutNode > &cut_nodes) const override
const CutSubdomainID _positive_id
The ID for the positive side of the cut.
virtual CutSubdomainID getCutSubdomainID(const Node *node) const override
If the levelset value is positive, return 1, otherwise return 0.
virtual const std::vector< Point > getCrackFrontPoints(unsigned int num_crack_front_points) const override
get a set of points along a crack front from a XFEM GeometricCutUserObject
void mooseError(Args &&... args) const
std::string enum_to_string(const T e)
Data structure defining a cut on an element edge.
unsigned int _id1
ID of the first node on the edge.
Real _distance
Fractional distance along the edge (from node 1 to 2) where the cut is located.
unsigned int _id2
ID of the second node on the edge.
unsigned int _host_side_id
Local ID of this side in the host element.
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.