https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
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.");
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
53std::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 ",
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;
146 Real dmin(std::numeric_limits<Real>::max());
147 dof_id_type dmin_id(std::numeric_limits<dof_id_type>::max());
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 mesh->unset_is_prepared();
185 return dynamic_pointer_cast<MeshBase>(mesh);
186}
registerMooseObject("MooseApp", ExtraNodesetGenerator)
unsigned int dim
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
static InputParameters validParams()
ExtraNodesetGenerator(const InputParameters &parameters)
std::unique_ptr< MeshBase > & _input
mesh to modify
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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.
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 addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
MeshGenerators are objects that can modify or add to an existing mesh.
static InputParameters validParams()
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:457
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
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
void max(const T &r, T &o, Request &req) const
void minloc(T &r, unsigned int &min_id) const
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
const Parallel::Communicator & comm() const
MeshBase & mesh
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.
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64