https://mooseframework.inl.gov
SideSetsFromBoundingBoxGenerator.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 "Conversion.h"
12 #include "MooseTypes.h"
13 #include "MooseMeshUtils.h"
14 #include "CastUniquePointer.h"
15 #include "MooseUtils.h"
16 
17 #include "libmesh/distributed_mesh.h"
18 #include "libmesh/elem.h"
19 
20 #include <typeinfo>
21 
23 
26 {
28 
29  params.addClassDescription("Defines new sidesets using currently-defined sideset IDs inside or "
30  "outside of a bounding box.");
31 
32  MooseEnum location("INSIDE OUTSIDE", "INSIDE");
33 
35  "bottom_left", "The bottom left point (in x,y,z with spaces in-between).");
37  "top_right", "The bottom left point (in x,y,z with spaces in-between).");
39  "block_id",
40  "Subdomain id to set for inside/outside the bounding box",
41  "The parameter 'block_id' is not used.");
42  params.addRequiredParam<BoundaryName>(
43  "boundary_new", "Boundary on specified block within the bounding box to assign");
44  params.addParam<bool>("boundary_id_overlap",
45  false,
46  "Set to true if boundaries need to overlap on sideset to be detected.");
47  params.addParam<MooseEnum>(
48  "location", location, "Control of where the subdomain id is to be set");
49 
50  // TODO: Implement each of these in the generate() routine using utilities in SidesetGeneratorBase
51  params.suppressParameter<bool>("fixed_normal");
52  params.suppressParameter<std::vector<BoundaryName>>("new_boundary");
53 
54  return params;
55 }
56 
58  const InputParameters & parameters)
59  : SideSetsGeneratorBase(parameters),
60  _location(parameters.get<MooseEnum>("location")),
61  _bounding_box(MooseUtils::buildBoundingBox(parameters.get<RealVectorValue>("bottom_left"),
62  parameters.get<RealVectorValue>("top_right"))),
63  _boundary_id_overlap(parameters.get<bool>("boundary_id_overlap"))
64 {
66  {
67  const std::vector<std::string> incompatible_params = {"normal",
68  "replace",
69  "include_only_external_sides",
70  "included_subdomains",
71  "included_neighbors"};
72  for (const auto & param_name : incompatible_params)
73  if (isParamSetByUser(param_name))
74  paramError(param_name, "Parameter should not be used with boundary_id_overlap = true.");
75  }
76 
77  _boundary_names.push_back(parameters.get<BoundaryName>("boundary_new"));
78 }
79 
80 std::unique_ptr<MeshBase>
82 {
83  std::unique_ptr<MeshBase> mesh = std::move(_input);
84  if (!mesh->is_replicated())
85  mooseError("SideSetsFromBoundingBoxGenerator is not implemented for distributed meshes");
86 
87  // construct the FE object so we can compute normals of faces
88  setup(*mesh);
89 
90  // Get a reference to our BoundaryInfo object for later use
91  BoundaryInfo & boundary_info = mesh->get_boundary_info();
92  boundary_info.build_node_list_from_side_list();
93 
94  bool found_element = false;
95  bool found_side_sets = false;
96  const bool inside = (_location == "INSIDE");
97 
98  // Attempt to get the new boundary id from the name
99  auto boundary_id_new = MooseMeshUtils::getBoundaryID(_boundary_names[0], *mesh);
100 
101  // If the new boundary id is not valid, make it instead
102  if (boundary_id_new == Moose::INVALID_BOUNDARY_ID)
103  {
104  boundary_id_new = MooseMeshUtils::getNextFreeBoundaryID(*mesh);
105 
106  // Write the name alias of the boundary id to the mesh boundary info
107  boundary_info.sideset_name(boundary_id_new) = _boundary_names[0];
108  boundary_info.nodeset_name(boundary_id_new) = _boundary_names[0];
109  }
110 
112  {
113  // Request to compute normal vectors
114  const std::vector<Point> & face_normals = _fe_face->get_normals();
115 
116  // Loop over the elements
117  for (const auto & elem : mesh->active_element_ptr_range())
118  {
119  // boolean if element centroid is in bounding box
120  bool contains = _bounding_box.contains_point(elem->vertex_average());
121 
122  // check if active elements are found either in or out of the bounding box, apropos "inside"
123  if (contains == inside)
124  {
125  found_element = true;
126  // loop over sides of elements within bounding box
127  for (const auto & side : make_range(elem->n_sides()))
128  {
129  _fe_face->reinit(elem, side);
130  // We'll just use the normal of the first qp
131  const Point face_normal = face_normals[0];
132 
133  if (elemSideSatisfiesRequirements(elem, side, *mesh, _normal, face_normal))
134  {
135  // assign new boundary value to boundary which meets meshmodifier criteria
136  if (_replace)
137  boundary_info.remove_side(elem, side);
138  boundary_info.add_side(elem, side, boundary_id_new);
139  found_side_sets = true;
140  }
141  }
142  }
143  }
144  if (!found_element && inside)
145  mooseError("No elements found within the bounding box");
146 
147  if (!found_element && !inside)
148  mooseError("No elements found outside the bounding box");
149 
150  if (!found_side_sets)
151  mooseError("No side sets found on active elements within the bounding box");
152  }
153 
154  else if (_boundary_id_overlap)
155  {
156  if (_included_boundary_ids.size() < 2)
157  mooseError("boundary_id_old out of bounds: ",
158  _included_boundary_ids.size(),
159  " Must be 2 boundary inputs or more.");
160 
161  bool found_node = false;
162 
163  // Loop over the elements and assign node set id to nodes within the bounding box
164  for (auto node = mesh->active_nodes_begin(); node != mesh->active_nodes_end(); ++node)
165  {
166  // check if nodes are inside of bounding box
167  if (_bounding_box.contains_point(**node) == inside)
168  {
169  // read out boundary ids for nodes
170  std::vector<boundary_id_type> node_boundary_ids;
171  boundary_info.boundary_ids(*node, node_boundary_ids);
172 
173  // sort boundary ids on node and sort boundary ids provided in input file
174  std::sort(node_boundary_ids.begin(), node_boundary_ids.end());
175  std::sort(_included_boundary_ids.begin(), _included_boundary_ids.end());
176 
177  // check if input boundary ids are all contained in the node
178  // if true, write new boundary id on respective node
179  if (std::includes(node_boundary_ids.begin(),
180  node_boundary_ids.end(),
181  _included_boundary_ids.begin(),
182  _included_boundary_ids.end()))
183  {
184  boundary_info.add_node(*node, boundary_id_new);
185  found_node = true;
186  }
187  }
188  }
189 
190  if (!found_node)
191  mooseError("No nodes found within the bounding box");
192  }
193 
194  mesh->set_isnt_prepared();
195  return dynamic_pointer_cast<MeshBase>(mesh);
196 }
bool elemSideSatisfiesRequirements(const Elem *const elem, const unsigned int side, const MeshBase &mesh, const Point &normal, const Point &face_normal)
Determines whether the given element&#39;s side satisfies the following parameters: include_only_external...
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
std::unique_ptr< MeshBase > & _input
the mesh to add the sidesets to
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition: MooseBase.h:439
SideSetsFromBoundingBoxGenerator(const InputParameters &parameters)
const BoundaryID INVALID_BOUNDARY_ID
Definition: MooseTypes.C:22
Point _normal
if specified, then faces are only added if their normal is close to this
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
T * get(const std::unique_ptr< T > &u)
The MooseUtils::get() specializations are used to support making forwards-compatible code changes fro...
Definition: MooseUtils.h:1135
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
MeshBase & mesh
const bool _replace
Whether or not to remove the old sidesets (all of them, if any) when adding sidesets.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
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.
MeshGenerator for defining sidesets inside or outside of a bounding box.
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...
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...
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
Gets the boundary ID associated with the given BoundaryName.
BoundingBox _bounding_box
Bounding box for testing element centroids against.
registerMooseObject("MooseApp", SideSetsFromBoundingBoxGenerator)
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
bool contains(std::string_view superstring, std::string_view substring)
static InputParameters validParams()
MooseEnum _location
ID location (inside of outside of box)
std::vector< boundary_id_type > _included_boundary_ids
A list of boundary ids that the side has to be part of, extracted from the included_boundaries parame...
const bool _boundary_id_overlap
Flag to determine if the provided boundaries need to overlap.
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:271
libMesh::BoundingBox buildBoundingBox(const Point &p1, const Point &p2)
Construct a valid bounding box from 2 arbitrary points.
Definition: MooseUtils.C:1142
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...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
BoundaryID getNextFreeBoundaryID(MeshBase &input_mesh)
Checks input mesh and returns the largest boundary ID in the mesh plus one, which is a boundary ID in...
std::unique_ptr< libMesh::FEBase > _fe_face
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition: MooseBase.h:205
void setup(MeshBase &mesh)
This method is used to construct the FE object so we can compute normals of faces.