https://mooseframework.inl.gov
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 
10 #include "LevelSetCutUserObject.h"
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");
24  params.addParam<CutSubdomainID>(
25  "negative_id", 0, "The CutSubdomainID corresponding to a non-positive signed distance");
26  params.addParam<CutSubdomainID>(
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"),
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 
49 bool
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: ",
66  libMesh::Utility::enum_to_string(elem->type()));
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 
93 bool
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: ",
118  libMesh::Utility::enum_to_string(elem->type()));
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 
152 bool
153 LevelSetCutUserObject::cutFragmentByGeometry(std::vector<std::vector<Point>> & /*frag_edges*/,
154  std::vector<Xfem::CutEdge> & /*cut_edges*/) const
155 {
156  return false;
157 }
158 
159 bool
160 LevelSetCutUserObject::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 
167 const std::vector<Point>
168 LevelSetCutUserObject::getCrackFrontPoints(unsigned int /*num_crack_front_points*/) const
169 {
170  mooseError("getCrackFrontPoints() is not implemented for this object.");
171 }
172 
173 const std::vector<RealVectorValue>
174 LevelSetCutUserObject::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 }
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
VarFieldType
const unsigned int _level_set_var_number
The variable number of the level set variable we using to define the cuts.
static InputParameters validParams()
Factory constructor, takes parameters so that all derived classes can be built using the same constru...
registerMooseObject("XFEMApp", LevelSetCutUserObject)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const NumericVector< Number > & _solution
The subproblem solution vector.
const System & _system
System reference.
virtual bool cutElementByGeometry(const Elem *elem, std::vector< Xfem::CutEdge > &cut_edges, std::vector< Xfem::CutNode > &cut_nodes) const override
std::vector< Real > _position
Fractional distance along the cut edges where the cut is located.
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 ...
void addRequiredParam(const std::string &name, const std::string &doc_string)
Data structure defining a cut through a face.
unsigned int CutSubdomainID
Definition: XFEMAppTypes.h:18
const CutSubdomainID _negative_id
The ID for the negative side of the cut.
Data structure defining a cut on an element edge.
static InputParameters validParams()
virtual CutSubdomainID getCutSubdomainID(const Node *node) const override
If the levelset value is positive, return 1, otherwise return 0.
unsigned int _id1
ID of the first node on the edge.
virtual bool cutFragmentByGeometry(std::vector< std::vector< Point >> &frag_edges, std::vector< Xfem::CutEdge > &cut_edges) const override
VarKindType
std::string enum_to_string(const T e)
Real _distance
Fractional distance along the edge (from node 1 to 2) where the cut is located.
VAR_ANY
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
EDGE2
unsigned int _id2
ID of the second node on the edge.
void mooseError(Args &&... args) const
unsigned int _host_side_id
Local ID of this side in the host element.
void addClassDescription(const std::string &doc_string)
LevelSetCutUserObject(const InputParameters &parameters)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
VAR_FIELD_STANDARD
const CutSubdomainID _positive_id
The ID for the positive side of the cut.
Real Number
const Elem & get(const ElemType type_in)
std::vector< unsigned int > _face_edge
IDs of all cut faces.
unsigned int _face_id
ID of the cut face.
uint8_t dof_id_type