https://mooseframework.inl.gov
RenumberBySubdomainGenerator.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 "CastUniquePointer.h"
12 #include "MooseMeshUtils.h"
13 
15 
18 {
20 
21  params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
22  params.addParam<std::vector<SubdomainName>>(
23  "blocks_to_renumber",
24  "Elements and nodes within these blocks will be renumbered. If none are specified, all "
25  "subdomains are affected by the renumbering");
26 
27  params.addClassDescription("Changes the element and node IDs so that elements and nodes are "
28  "contiguous within a subdomain. Note that DoF ordering may be "
29  "affected as well, and that the mesh renumbering will be turned off.");
30 
31  return params;
32 }
33 
35  : MeshGenerator(parameters), _input(getMesh("input"))
36 {
37 }
38 
39 std::unique_ptr<MeshBase>
41 {
42  std::unique_ptr<MeshBase> mesh = std::move(_input);
43 
44  // Not impossible to do.
45  if (!mesh->is_serial())
46  mooseError("Not implemented for non-serialized distributed meshes");
47 
48  // Orphaned nodes would cause problems on renumbering, we are looping on the nodes attached
49  // to elements
50  mesh->remove_orphaned_nodes();
51  mesh->renumber_nodes_and_elements();
52 
53  // Get the blocks provided by the user
54  std::optional<std::vector<SubdomainName>> blocks =
55  isParamValid("blocks_to_renumber")
56  ? getParam<std::vector<SubdomainName>>("blocks_to_renumber")
57  : std::vector<SubdomainName>();
58  std::vector<SubdomainID> block_ids(blocks->size());
59  std::stringstream missing_block;
60 
61  for (const auto i : index_range(block_ids))
62  {
63  const SubdomainName & name = blocks.value()[i];
64 
65  // Convert the SubdomainName to an id and store
66  const auto id = MooseMeshUtils::getSubdomainID(name, *mesh);
67  block_ids[i] = id;
68 
69  // Block does not exist - store for a future error
70  if (id == Moose::INVALID_BLOCK_ID)
71  missing_block << name << " ";
72  }
73  if (missing_block.str().size())
74  paramError("blocks_to_renumber",
75  "The following blocks were requested to be renumbered, but do not exist: ",
76  missing_block.str());
77 
78  // User did not specify blocks, just get them all
79  if (blocks->empty())
80  {
81  std::set<subdomain_id_type> block_ids_set;
82  mesh->subdomain_ids(block_ids_set);
83  block_ids.reserve(block_ids_set.size());
84  block_ids.assign(block_ids_set.begin(), block_ids_set.end());
85 
86  // Does not have useful data
87  blocks.reset();
88  }
89 
90  // Renumber all elements with an ID we can recognize (so we can tell an already renumbered elem)
91  const auto max_elem_id = mesh->max_elem_id();
92  const auto max_node_id = mesh->max_node_id();
93  std::unordered_map<dof_id_type, dof_id_type> new_elem_ids;
94  new_elem_ids.reserve(max_elem_id);
95  std::unordered_set<dof_id_type> renumbered_nodes;
96  renumbered_nodes.reserve(max_node_id);
97 
98  // Renumber block IDs one at a time
99  // We have to move them out of range, then back to range
100  dof_id_type elem_count = 0;
101  dof_id_type node_count = 0;
102  for (const auto i : index_range(block_ids))
103  {
104  for (auto elem : mesh->active_subdomain_elements_ptr_range(block_ids[i]))
105  {
106  // If we didn't specify all the subdomains, we might have to skip elem ids that are still
107  // taken
108  while (mesh->query_elem_ptr(elem_count))
109  {
110  elem_count++;
111  }
112  // We can't mess with the range while looping in them
113  new_elem_ids[elem->id()] = elem_count++;
114 
115  for (auto & node : elem->node_ref_range())
116  // prevent re-renumbering
117  if (!renumbered_nodes.count(node.id()))
118  {
119  // If we didn't specify all the subdomains, we might have to skip node ids that are still
120  // taken
121  while (mesh->query_node_ptr(node_count))
122  {
123  node_count++;
124  }
125  renumbered_nodes.insert(node.id());
126  mesh->renumber_node(node.id(), node_count++);
127  }
128  }
129  }
130 
131  // Now change the IDs
132  for (const auto [key, value] : new_elem_ids)
133  mesh->renumber_elem(key, value);
134 
135  // Update the max ids
136  mesh->contract();
137 
138  // Try to disallow renumbering from now on since we just renumbered
139  mesh->allow_renumbering(false);
140  // No gain if exodus just renumbers this. Better to tell the user
141  if (mesh->n_nodes() != mesh->max_node_id() || mesh->n_elem() != mesh->max_elem_id())
142  mooseWarning("Mesh is not contiguously numbered after renumbering. The numbering may be erased "
143  "by outputs that require contiguous numbering such as Exodus.\nNumber of nodes: " +
144  std::to_string(mesh->n_nodes()) +
145  "\nMax node ID: " + std::to_string(mesh->max_node_id() - 1) +
146  "\nNumber of elements: " + std::to_string(mesh->n_elem()) +
147  "\nMax elem ID: " + std::to_string(mesh->max_elem_id() - 1));
148 
149  mesh->unset_is_prepared();
150  return dynamic_pointer_cast<MeshBase>(mesh);
151 }
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:467
char ** blocks
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
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.
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...
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
Gets the subdomain ID associated with the given SubdomainName.
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
const SubdomainID INVALID_BLOCK_ID
Definition: MooseTypes.C:20
void mooseWarning(Args &&... args) const
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
registerMooseObject("MooseApp", RenumberBySubdomainGenerator)
MeshGenerator for re-numbering elements and nodes contiguously within subdomains. ...
static InputParameters validParams()
Definition: MeshGenerator.C:23
std::unique_ptr< MeshBase > & _input
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:281
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...
RenumberBySubdomainGenerator(const InputParameters &parameters)
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:33
auto index_range(const T &sizable)
uint8_t dof_id_type