https://mooseframework.inl.gov
ExtraNodesetGenerator.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 "ExtraNodesetGenerator.h"
11 #include "MooseMesh.h"
12 #include "Conversion.h"
13 #include "MooseMeshUtils.h"
14 #include "CastUniquePointer.h"
15 
16 #include "libmesh/elem.h"
17 
19 
22 {
24 
25  params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
26  params.addRequiredParam<std::vector<BoundaryName>>("new_boundary",
27  "The names of the boundaries to create");
28 
29  params.addParam<std::vector<unsigned int>>("nodes",
30  "The nodes you want to be in the nodeset "
31  "(Either this parameter or \"coord\" must be "
32  "supplied).");
33  params.addParam<std::vector<std::vector<Real>>>(
34  "coord",
35  {},
36  "The nodes with coordinates you want to be in the "
37  "nodeset. Separate multple coords with ';' (Either this parameter or \"nodes\" must be "
38  "supplied).");
39  params.addParam<Real>(
40  "tolerance", TOLERANCE, "The tolerance in which two nodes are considered identical");
41  params.addParam<bool>("use_closest_node", false, "Use the node closest to the coordinate.");
42  params.addClassDescription(
43  "Creates a new node set and a new boundary made with the nodes the user provides.");
44 
45  return params;
46 }
47 
49  : MeshGenerator(parameters), _input(getMesh("input"))
50 {
51 }
52 
53 std::unique_ptr<MeshBase>
55 {
56  std::unique_ptr<MeshBase> mesh = std::move(_input);
57 
58  // Get the BoundaryIDs from the mesh
59  std::vector<BoundaryName> boundary_names = getParam<std::vector<BoundaryName>>("new_boundary");
60  std::vector<boundary_id_type> boundary_ids =
61  MooseMeshUtils::getBoundaryIDs(*mesh, boundary_names, true);
62 
63  // Get a reference to our BoundaryInfo object
64  BoundaryInfo & boundary_info = mesh->get_boundary_info();
65 
66  // add nodes with their ids
67  if (isParamValid("nodes"))
68  for (const auto & node_id : getParam<std::vector<unsigned int>>("nodes"))
69  {
70  // Our mesh may be distributed and this node may not exist on this process
71  if (!mesh->query_node_ptr(node_id))
72  continue;
73 
74  for (const auto & boundary_id : boundary_ids)
75  boundary_info.add_node(node_id, boundary_id);
76  }
77 
78  // add nodes with their coordinates
79  const auto dim = mesh->mesh_dimension();
80 
81  std::unique_ptr<libMesh::PointLocatorBase> locator = mesh->sub_point_locator();
82  locator->enable_out_of_mesh_mode();
83 
84  const auto tolerance = getParam<Real>("tolerance");
85  const bool use_closest_node = getParam<bool>("use_closest_node");
86  const auto coords = getParam<std::vector<std::vector<Real>>>("coord");
87  if (use_closest_node && coords.empty())
88  paramError("coord", "A coordinate should be specified to use 'use_closest_node'");
89  for (const auto & c : coords)
90  {
91  Point p;
92  if (c.size() < dim)
93  paramError("coord",
94  "Coordinate ",
96  " does not have enough components for a ",
97  dim,
98  "D mesh.");
99 
100  if (c.size() > 3)
101  paramError("coord",
102  "Coordinate ",
103  Moose::stringify(c),
104  " has too many components. Did you maybe forget to separate multiple coordinates "
105  "with a ';'?");
106 
107  for (unsigned int j = 0; j < c.size(); ++j)
108  p(j) = c[j];
109 
110  // locate candidate element
111  bool on_node = false;
112  bool found_elem = false;
113  const Elem * elem = (*locator)(p);
114  if (elem)
115  {
116  found_elem = true;
117  for (unsigned int j = 0; j < elem->n_nodes(); ++j)
118  {
119  const Node * node = elem->node_ptr(j);
120  if (p.absolute_fuzzy_equals(*node, tolerance))
121  {
122  for (const auto & boundary_id : boundary_ids)
123  boundary_info.add_node(node, boundary_id);
124 
125  on_node = true;
126  break;
127  }
128  }
129  }
130 
131  // If we are on a distributed mesh, then any particular processor
132  // may be unable to find any particular node, but *some* processor
133  // should have found it.
134  if (!mesh->is_replicated())
135  {
136  this->comm().max(found_elem);
137  this->comm().max(on_node);
138  }
139 
140  // only search for closest node if it is not found on a node
141  if (use_closest_node && !on_node)
142  {
143  // these are always true when using closest node
144  found_elem = true;
145  on_node = true;
148  // find this processors closest node and save distance and the node id
149  for (const auto & node_iter : as_range(mesh->local_nodes_begin(), mesh->local_nodes_end()))
150  {
151  Real dist = (*node_iter - p).norm_sq();
152  if (dist < dmin)
153  {
154  dmin = dist;
155  dmin_id = node_iter->id();
156  }
157  }
158 
159  // get proc id with the global closest node and then communicate that procs closest node_id
160  processor_id_type dmin_proc_id;
161  this->comm().minloc(dmin, dmin_proc_id);
162  this->comm().broadcast(dmin_id, dmin_proc_id);
163 
164  const Node * node = mesh->query_node_ptr(dmin_id);
165  if (node)
166  for (const auto & boundary_id : boundary_ids)
167  boundary_info.add_node(node, boundary_id);
168  }
169 
170  if (!found_elem)
171  mooseError("Unable to locate the following point within the domain, please check its "
172  "coordinates:\n",
173  p);
174 
175  if (!on_node)
176  mooseError("No node found at point:\n",
177  p,
178  "\nSet use_closest_node=true if you want to find the closest node.");
179  }
180 
181  for (unsigned int i = 0; i < boundary_ids.size(); ++i)
182  boundary_info.nodeset_name(boundary_ids[i]) = boundary_names[i];
183 
184  // This is a terrible hack that we'll want to remove once BMBBG isn't terrible
186  mesh->set_isnt_prepared();
187  return dynamic_pointer_cast<MeshBase>(mesh);
188 }
void minloc(T &r, unsigned int &min_id) const
MeshBase & mesh
registerMooseObject("MooseApp", ExtraNodesetGenerator)
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:154
const Parallel::Communicator & comm() const
std::unique_ptr< MeshBase > & _input
mesh to modify
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.
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
bool hasBreakMeshByBlockGenerator() const
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...
auto max(const L &left, const R &right)
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
uint8_t processor_id_type
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
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.
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:84
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()
Definition: MeshGenerator.C:23
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
ExtraNodesetGenerator(const InputParameters &parameters)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void max(const T &r, T &o, Request &req) const
auto norm_sq(const T &a) -> decltype(std::norm(a))
static InputParameters validParams()
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...
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...
MeshGeneratorSystem & getMeshGeneratorSystem()
Gets the system that manages the MeshGenerators.
Definition: MooseApp.h:863
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:32
uint8_t dof_id_type