Loading [MathJax]/extensions/tex2jax.js
https://mooseframework.inl.gov
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
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.makeParamRequired<std::vector<BoundaryName>>("included_boundaries");
43  params.addParam<std::vector<BoundaryName>>(
44  "boundaries_old",
45  "The list of boundaries on the specified block within the bounding box to be modified");
46  params.deprecateParam("boundaries_old", "included_boundaries", "4/01/2025");
47  params.addRequiredParam<BoundaryName>(
48  "boundary_new", "Boundary on specified block within the bounding box to assign");
49  params.addParam<bool>("boundary_id_overlap",
50  false,
51  "Set to true if boundaries need to overlap on sideset to be detected.");
52  params.addParam<MooseEnum>(
53  "location", location, "Control of where the subdomain id is to be set");
54 
55  // TODO: Implement each of these in the generate() routine using utilities in SidesetGeneratorBase
56  params.suppressParameter<bool>("fixed_normal");
57  params.suppressParameter<std::vector<BoundaryName>>("new_boundary");
58 
59  return params;
60 }
61 
63  const InputParameters & parameters)
64  : SideSetsGeneratorBase(parameters),
65  _location(parameters.get<MooseEnum>("location")),
66  _bounding_box(MooseUtils::buildBoundingBox(parameters.get<RealVectorValue>("bottom_left"),
67  parameters.get<RealVectorValue>("top_right"))),
68  _boundary_id_overlap(parameters.get<bool>("boundary_id_overlap"))
69 {
71  {
72  const std::vector<std::string> incompatible_params = {"normal",
73  "replace",
74  "include_only_external_sides",
75  "included_subdomains",
76  "included_neighbors"};
77  for (const auto & param_name : incompatible_params)
78  if (isParamSetByUser(param_name))
79  paramError(param_name, "Parameter should not be used with boundary_id_overlap = true.");
80  }
81 
82  _boundary_names.push_back(parameters.get<BoundaryName>("boundary_new"));
83 }
84 
85 std::unique_ptr<MeshBase>
87 {
88  std::unique_ptr<MeshBase> mesh = std::move(_input);
89  if (!mesh->is_replicated())
90  mooseError("SideSetsFromBoundingBoxGenerator is not implemented for distributed meshes");
91 
92  // construct the FE object so we can compute normals of faces
93  setup(*mesh);
94 
95  // Get a reference to our BoundaryInfo object for later use
96  BoundaryInfo & boundary_info = mesh->get_boundary_info();
97  boundary_info.build_node_list_from_side_list();
98 
99  bool found_element = false;
100  bool found_side_sets = false;
101  const bool inside = (_location == "INSIDE");
102 
103  // Attempt to get the new boundary id from the name
104  auto boundary_id_new = MooseMeshUtils::getBoundaryID(_boundary_names[0], *mesh);
105 
106  // If the new boundary id is not valid, make it instead
107  if (boundary_id_new == Moose::INVALID_BOUNDARY_ID)
108  {
109  boundary_id_new = MooseMeshUtils::getNextFreeBoundaryID(*mesh);
110 
111  // Write the name alias of the boundary id to the mesh boundary info
112  boundary_info.sideset_name(boundary_id_new) = _boundary_names[0];
113  boundary_info.nodeset_name(boundary_id_new) = _boundary_names[0];
114  }
115 
117  {
118  // Request to compute normal vectors
119  const std::vector<Point> & face_normals = _fe_face->get_normals();
120 
121  // Loop over the elements
122  for (const auto & elem : mesh->active_element_ptr_range())
123  {
124  // boolean if element centroid is in bounding box
125  bool contains = _bounding_box.contains_point(elem->vertex_average());
126 
127  // check if active elements are found either in or out of the bounding box, apropos "inside"
128  if (contains == inside)
129  {
130  found_element = true;
131  // loop over sides of elements within bounding box
132  for (const auto & side : make_range(elem->n_sides()))
133  {
134  _fe_face->reinit(elem, side);
135  // We'll just use the normal of the first qp
136  const Point face_normal = face_normals[0];
137 
138  if (elemSideSatisfiesRequirements(elem, side, *mesh, _normal, face_normal))
139  {
140  // assign new boundary value to boundary which meets meshmodifier criteria
141  if (_replace)
142  boundary_info.remove_side(elem, side);
143  boundary_info.add_side(elem, side, boundary_id_new);
144  found_side_sets = true;
145  }
146  }
147  }
148  }
149  if (!found_element && inside)
150  mooseError("No elements found within the bounding box");
151 
152  if (!found_element && !inside)
153  mooseError("No elements found outside the bounding box");
154 
155  if (!found_side_sets)
156  mooseError("No side sets found on active elements within the bounding box");
157  }
158 
159  else if (_boundary_id_overlap)
160  {
161  if (_included_boundary_ids.size() < 2)
162  mooseError("boundary_id_old out of bounds: ",
163  _included_boundary_ids.size(),
164  " Must be 2 boundary inputs or more.");
165 
166  bool found_node = false;
167 
168  // Loop over the elements and assign node set id to nodes within the bounding box
169  for (auto node = mesh->active_nodes_begin(); node != mesh->active_nodes_end(); ++node)
170  {
171  // check if nodes are inside of bounding box
172  if (_bounding_box.contains_point(**node) == inside)
173  {
174  // read out boundary ids for nodes
175  std::vector<boundary_id_type> node_boundary_ids;
176  boundary_info.boundary_ids(*node, node_boundary_ids);
177 
178  // sort boundary ids on node and sort boundary ids provided in input file
179  std::sort(node_boundary_ids.begin(), node_boundary_ids.end());
180  std::sort(_included_boundary_ids.begin(), _included_boundary_ids.end());
181 
182  // check if input boundary ids are all contained in the node
183  // if true, write new boundary id on respective node
184  if (std::includes(node_boundary_ids.begin(),
185  node_boundary_ids.end(),
186  _included_boundary_ids.begin(),
187  _included_boundary_ids.end()))
188  {
189  boundary_info.add_node(*node, boundary_id_new);
190  found_node = true;
191  }
192  }
193  }
194 
195  if (!found_node)
196  mooseError("No nodes found within the bounding box");
197  }
198 
199  mesh->set_isnt_prepared();
200  return dynamic_pointer_cast<MeshBase>(mesh);
201 }
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
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.
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:1122
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.
void deprecateParam(const std::string &old_name, const std::string &new_name, const std::string &removal_date)
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
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 ...
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.
bool isParamSetByUser(const std::string &nm) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
IntRange< T > make_range(T beg, T end)
libMesh::BoundingBox buildBoundingBox(const Point &p1, const Point &p2)
Construct a valid bounding box from 2 arbitrary points.
Definition: MooseUtils.C:1237
void makeParamRequired(const std::string &name)
Changes the parameter to be required.
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...
const InputParameters & parameters() const
Get the parameters of the object.
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
void setup(MeshBase &mesh)
This method is used to construct the FE object so we can compute normals of faces.