www.mooseframework.org
SideSetsFromPointsGenerator.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 #include "Parser.h"
12 #include "InputParameters.h"
13 #include "MooseMeshUtils.h"
14 #include "CastUniquePointer.h"
15 
16 #include "libmesh/mesh.h"
17 #include "libmesh/mesh_generation.h"
18 #include "libmesh/mesh_serializer.h"
19 #include "libmesh/string_to_enum.h"
20 #include "libmesh/quadrature_gauss.h"
21 #include "libmesh/point_locator_base.h"
22 #include "libmesh/enum_point_locator_type.h"
23 #include "libmesh/distributed_mesh.h"
24 #include "libmesh/elem.h"
25 #include "libmesh/fe_base.h"
26 #include "libmesh/mesh_tools.h"
27 
28 #include <typeinfo>
29 
31 
34 {
36 
37  params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
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<BoundaryName>>("new_boundary",
41  "The name of the boundary to create");
42  params.addRequiredParam<std::vector<Point>>(
43  "points", "A list of points from which to start painting sidesets");
44 
45  return params;
46 }
47 
49  : SideSetsGeneratorBase(parameters),
50  _input(getMesh("input")),
51  _boundary_names(getParam<std::vector<BoundaryName>>("new_boundary")),
52  _points(getParam<std::vector<Point>>("points"))
53 {
54  if (_points.size() != _boundary_names.size())
55  mooseError("point list and boundary list are not the same length");
56 }
57 
58 std::unique_ptr<MeshBase>
60 {
61  std::unique_ptr<MeshBase> mesh = std::move(_input);
62 
63  // Our flood fill doesn't do any communication, so it requires a
64  // serialized mesh
65  MeshSerializer serial(*mesh);
66 
67  // Get the BoundaryIDs from the mesh
68  std::vector<BoundaryID> boundary_ids =
70 
71  setup(*mesh);
72 
73  _visited.clear();
74 
75  std::unique_ptr<PointLocatorBase> pl = PointLocatorBase::build(TREE, *mesh);
76 
77  for (unsigned int i = 0; i < boundary_ids.size(); ++i)
78  {
79  std::set<const Elem *> candidate_elements;
80  (*pl)(_points[i], candidate_elements);
81 
82  const Elem * elem_to_flood = nullptr;
83  Point normal_to_flood;
84 
85  for (const Elem * elem : candidate_elements)
86  for (unsigned int side = 0; side < elem->n_sides(); ++side)
87  {
88  if (elem->neighbor_ptr(side))
89  continue;
90 
91  // See if this point is on this side
92  std::unique_ptr<const Elem> elem_side = elem->side_ptr(side);
93 
94  if (elem_side->contains_point(_points[i]))
95  {
96  // This is a good side to paint our sideset with.
97  // Get the normal.
98  const std::vector<Point> & normals = _fe_face->get_normals();
99  _fe_face->reinit(elem, side);
100 
101  // If we *already* found a good but different side to paint
102  // our sideset with, we've got an ambiguity here.
103  if (elem_to_flood && (std::abs(1.0 - normal_to_flood * normals[0]) > _variance ||
104  elem_to_flood->which_neighbor_am_i(elem) == libMesh::invalid_uint))
105  mooseError("Two ambiguous potential sideset sources found for boundary `",
106  _boundary_names[i],
107  "' at ",
108  _points[i],
109  ":\nElement ",
110  elem_to_flood->id(),
111  " normal ",
112  normal_to_flood,
113  " and\n",
114  ":\nElement ",
115  elem->id(),
116  " normal ",
117  normals[0]);
118 
119  elem_to_flood = elem;
120  normal_to_flood = normals[0];
121  // Don't just flood here; keep looking for possible ambiguity
122  }
123  }
124 
125  flood(elem_to_flood, normal_to_flood, boundary_ids[i], *mesh);
126  }
127 
128 #ifdef DEBUG
129  MeshTools::libmesh_assert_valid_boundary_ids(*mesh);
130 #endif
131 
132  finalize();
133 
134  for (unsigned int i = 0; i < boundary_ids.size(); ++i)
135  mesh->get_boundary_info().sideset_name(boundary_ids[i]) = _boundary_names[i];
136 
137  mesh->set_isnt_prepared();
138  return dynamic_pointer_cast<MeshBase>(mesh);
139 }
TREE
const unsigned int invalid_uint
std::unique_ptr< MeshBase > & _input
the mesh to add the sidesets to
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static InputParameters validParams()
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
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
A mesh generator to generate new sidesets from all faces connected to points with the same normal as ...
SideSetsFromPointsGenerator(const InputParameters &parameters)
std::unique_ptr< FEBase > _fe_face
void flood(const Elem *elem, Point normal, boundary_id_type side_id, MeshBase &mesh)
This method implements a recursive flood routine to paint a sideset of mesh to neighboring faces give...
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()
std::vector< BoundaryName > _boundary_names
holds the boundary names for the sidesets
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
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
void setup(MeshBase &mesh)
This method is used to construct the FE object so we can compute normals of faces.