https://mooseframework.inl.gov
SideSetsFromPointsGenerator.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 "Parser.h"
12 #include "InputParameters.h"
13 #include "MeshTraversingUtils.h"
14 #include "MooseMeshUtils.h"
15 #include "CastUniquePointer.h"
16 
17 #include "libmesh/mesh.h"
18 #include "libmesh/mesh_generation.h"
19 #include "libmesh/mesh_serializer.h"
20 #include "libmesh/string_to_enum.h"
21 #include "libmesh/quadrature_gauss.h"
22 #include "libmesh/point_locator_base.h"
23 #include "libmesh/enum_point_locator_type.h"
24 #include "libmesh/distributed_mesh.h"
25 #include "libmesh/elem.h"
26 #include "libmesh/fe_base.h"
27 #include "libmesh/mesh_tools.h"
28 
29 #include <typeinfo>
30 
32 
35 {
37 
38  params.addClassDescription("Adds a new sideset starting at the specified point containing all "
39  "connected element faces with the same normal.");
40  params.addRequiredParam<std::vector<Point>>(
41  "points", "A list of points from which to start painting sidesets");
42 
43  params.suppressParameter<Point>("normal");
44  params.suppressParameter<Real>("normal_tol");
45 
46  // It doesn't make sense to allow internal sides for this side set generator.
47  params.setParameters("include_only_external_sides", true);
48  params.suppressParameter<bool>("include_only_external_sides");
49 
50  return params;
51 }
52 
54  : SideSetsGeneratorBase(parameters), _points(getParam<std::vector<Point>>("points"))
55 {
56  if (_points.size() != _boundary_names.size())
57  mooseError("point list and boundary list are not the same length");
58  _using_normal = true;
59 }
60 
61 std::unique_ptr<MeshBase>
63 {
64  std::unique_ptr<MeshBase> mesh = std::move(_input);
65 
66  // Our flood fill doesn't do any communication, so it requires a
67  // serialized mesh
69 
70  // Get the BoundaryIDs from the mesh
71  std::vector<BoundaryID> boundary_ids =
73 
74  setup(*mesh);
75 
76  _visited.clear();
77 
78  std::unique_ptr<libMesh::PointLocatorBase> pl =
80 
81  for (const auto i : index_range(boundary_ids))
82  {
83  std::set<const Elem *> candidate_elements;
84  (*pl)(_points[i], candidate_elements);
85 
86  const Elem * elem_to_flood = nullptr;
87  Point normal_to_flood;
88 
89  for (const Elem * elem : candidate_elements)
90  for (const auto side : make_range(elem->n_sides()))
91  {
92  if (elem->neighbor_ptr(side))
93  continue;
94 
95  // See if this point is on this side
96  std::unique_ptr<const Elem> elem_side = elem->side_ptr(side);
97 
98  if (elem_side->contains_point(_points[i]))
99  {
100  // This is a good side to paint our sideset with.
101  // Get the normal.
102  const std::vector<Point> & normals = _fe_face->get_normals();
103  _fe_face->reinit(elem, side);
104 
105  // If we *already* found a good but different side to paint
106  // our sideset with, we've got an ambiguity here.
107  if (elem_to_flood &&
108  (!MeshTraversingUtils::normalsWithinTol(normal_to_flood, normals[0], _normal_tol) ||
109  elem_to_flood->which_neighbor_am_i(elem) == libMesh::invalid_uint))
110  mooseError("Two ambiguous potential sideset sources found for boundary `",
111  _boundary_names[i],
112  "' at ",
113  _points[i],
114  ":\nElement ",
115  elem_to_flood->id(),
116  " normal ",
117  normal_to_flood,
118  " and\n",
119  ":\nElement ",
120  elem->id(),
121  " normal ",
122  normals[0]);
123 
124  elem_to_flood = elem;
125  normal_to_flood = normals[0];
126  // Don't just flood here; keep looking for possible ambiguity
127  }
128  }
129 
130  flood(elem_to_flood, normal_to_flood, boundary_ids[i], *mesh);
131  }
132 
133 #ifdef DEBUG
134  MeshTools::libmesh_assert_valid_boundary_ids(*mesh);
135 #endif
136 
137  finalize();
138 
139  for (const auto i : index_range(boundary_ids))
140  mesh->get_boundary_info().sideset_name(boundary_ids[i]) = _boundary_names[i];
141 
142  mesh->unset_is_prepared();
143  return dynamic_pointer_cast<MeshBase>(mesh);
144 }
std::unique_ptr< MeshBase > & _input
the mesh to add the sidesets to
const unsigned int invalid_uint
const Real _normal_tol
if normal is specified, then faces are only added if face_normal.normal_hat <= 1 - normal_tol where n...
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static InputParameters validParams()
std::vector< BoundaryName > _boundary_names
The list of new boundary names.
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
registerMooseObject("MooseApp", SideSetsFromPointsGenerator)
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
std::vector< Point > _points
holds the points used to generate sidesets
void suppressParameter(const std::string &name)
This method suppresses an inherited parameter so that it isn&#39;t required or valid in the derived class...
void flood(const Elem *elem, const Point &normal, const boundary_id_type &side_id, MeshBase &mesh)
This method implements a recursive flood routine to paint a sideset of mesh to neighboring faces give...
A mesh generator to generate new sidesets from all faces connected to points with the same normal as ...
SideSetsFromPointsGenerator(const InputParameters &parameters)
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
void finalize()
This method finalizes the object, setting names back in the boundary_info object and releasing memory...
static InputParameters validParams()
bool _using_normal
true if only faces close to "normal" will be added
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:281
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
std::map< boundary_id_type, std::set< const Elem * > > _visited
std::unique_ptr< libMesh::FEBase > _fe_face
static std::unique_ptr< PointLocatorBase > build(PointLocatorType t, const MeshBase &mesh, const PointLocatorBase *master=nullptr)
void setup(MeshBase &mesh)
This method is used to construct the FE object so we can compute normals of faces.
auto index_range(const T &sizable)
void setParameters(const std::string &name, const T &value, Ts... extra_input_parameters)
Given a series of parameters names and values, sets each name to the corresponding value...
bool normalsWithinTol(const Point &normal_1, const Point &normal_2, const Real tol)
Determines whether two normal vectors are within normal_tol of each other.