https://mooseframework.inl.gov
Loading...
Searching...
No Matches
RenameBlockGenerator.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
12#include "CastUniquePointer.h"
13#include "MooseMeshUtils.h"
14
15#include "libmesh/mesh_modification.h"
16
18
21{
23
24 params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
25
26 params.addDeprecatedParam<std::vector<SubdomainID>>(
27 "old_block_id",
28 "Elements with this block number will be given the new_block_number or "
29 "new_block_name. You must supply either old_block_id or old_block_name. "
30 "You may supply a vector of old_block_id, in which case the new_block "
31 "information must also be a vector.",
32 "Use 'old_block' instead of 'old_block_id'.");
33 params.addDeprecatedParam<std::vector<SubdomainName>>(
34 "old_block_name",
35 "Elements with this block name will be given the new_block_number or "
36 "new_block_name. You must supply either old_block_id or old_block_name. "
37 "You may supply a vector of old_block_name, in which case the new_block "
38 "information must also be a vector.",
39 "Use 'old_block' instead of 'old_block_name'.");
40 params.addDeprecatedParam<std::vector<SubdomainID>>(
41 "new_block_id",
42 "Elements with the old block number (or name) will be given this block "
43 "number. If the old blocks are named, their names will be passed onto the "
44 "newly numbered blocks.",
45 "Use 'new_block' instead of 'new_block_id'.");
46 params.addDeprecatedParam<std::vector<SubdomainName>>(
47 "new_block_name",
48 "Elements with the old block number (or name) will be given this block "
49 "name. No change of block ID is performed, unless multiple old blocks are "
50 "given the same name, in which case they are all given the first old block "
51 "number.",
52 "Use 'new_block' instead of 'new_block_name'.");
53
54 params.addParam<std::vector<SubdomainName>>(
55 "old_block",
56 "Elements with these block ID(s)/name(s) will be given the new block information specified "
57 "in 'new_block'");
58 params.addParam<std::vector<SubdomainName>>(
59 "new_block",
60 "The new block ID(s)/name(s) to be given by the elements defined in 'old_block'.");
61
62 params.addClassDescription("Changes the block IDs and/or block names for a given set of blocks "
63 "defined by either block ID or block name. The changes are "
64 "independent of ordering. The merging of blocks is supported.");
65
66 return params;
67}
68
70 : MeshGenerator(parameters), _input(getMesh("input"))
71{
72 if (isParamValid("old_block_id") && isParamValid("old_block_name"))
73 paramError("old_block_id",
74 "Cannot use in combination with 'old_block_name'. Please use 'old_block' "
75 "instead; 'old_block_id' and 'old_block_name' are deprecated.");
76 if (isParamValid("new_block_id") && isParamValid("new_block_name"))
77 paramError("new_block_id",
78 "Cannot use in combination with 'new_block_name'. Please use 'new_block' "
79 "instead; 'new_block_id' and 'new_block_name' are deprecated.");
80
81 if (isParamValid("old_block"))
82 {
83 if (isParamValid("old_block_id"))
84 paramError("old_block_id",
85 "Cannot use with 'old_block'. Use only 'old_block'; 'old_block_id' is "
86 "deprecated.");
87 if (isParamValid("old_block_name"))
88 paramError("old_block_name",
89 "Cannot use with 'old_block'. Use only 'old_block'; 'old_block_name' is "
90 "deprecated.");
91 _old_block = getParam<std::vector<SubdomainName>>("old_block");
92 _old_block_param_name = "old_block";
93 }
94 else if (isParamValid("old_block_id"))
95 {
96 for (const auto id : getParam<std::vector<SubdomainID>>("old_block_id"))
97 _old_block.push_back(std::to_string(id));
98 _old_block_param_name = "old_block_id";
99 }
100 else
101 {
102 _old_block = isParamValid("old_block_name")
103 ? getParam<std::vector<SubdomainName>>("old_block_name")
104 : std::vector<SubdomainName>{};
105 _old_block_param_name = "old_block_name";
106 }
107
108 std::string new_block_param_name;
109 if (isParamValid("new_block"))
110 {
111 if (isParamValid("new_block_id"))
112 paramError("new_block_id",
113 "Cannot use with 'new_block'. Use only 'new_block'; 'new_block_id' is "
114 "deprecated.");
115 if (isParamValid("new_block_name"))
116 paramError("new_block_name",
117 "Cannot use with 'new_block'. Use only 'new_block'; 'new_block_name' is "
118 "deprecated.");
119 _new_block = getParam<std::vector<SubdomainName>>("new_block");
120 new_block_param_name = "new_block";
121 }
122 else if (isParamValid("new_block_id"))
123 {
124 for (const auto id : getParam<std::vector<SubdomainID>>("new_block_id"))
125 _new_block.push_back(std::to_string(id));
126 new_block_param_name = "new_block_id";
127 }
128 else
129 {
130 _new_block = isParamValid("new_block_name")
131 ? getParam<std::vector<SubdomainName>>("new_block_name")
132 : std::vector<SubdomainName>{};
133 new_block_param_name = "new_block_name";
134 }
135
136 if (_old_block.size() != _new_block.size())
137 paramError(new_block_param_name, "Must be the same length as '", _old_block_param_name, "'");
138}
139
140std::unique_ptr<MeshBase>
142{
143 std::unique_ptr<MeshBase> mesh = std::move(_input);
144
145 // MeshBase::subdomain_name will insert, so we need a const ref
146 const MeshBase & const_mesh = *mesh;
147
148 // Get the subdomains in the mesh (this is global)
149 if (!mesh->preparation().has_cached_elem_data)
150 mesh->cache_elem_data();
151 std::set<subdomain_id_type> block_ids;
152 mesh->subdomain_ids(block_ids);
153
154 // Helper for getting an unused block ID, and keeping track of it
155 // so that we can generate more later
156 auto get_unused_block_id = [this, &block_ids, &const_mesh]()
157 {
158 for (const auto id : make_range(Moose::INVALID_BLOCK_ID))
159 if (!block_ids.count(id) && !const_mesh.get_subdomain_name_map().count(id))
160 {
161 block_ids.insert(id);
162 return id;
163 }
164
165 mooseError("Failed to find an unused ID!");
166 };
167
168 const auto num_blocks = _old_block.size();
169
170 // Helper for checking whether or not a SubdomainName (which could be an ID or a name)
171 // is really input as an ID
172 const auto is_subdomain_id = [](const SubdomainName & subdomain_name)
173 { return MooseUtils::isDigits(subdomain_name); };
174
175 // Get the old block IDs and make sure they exist
176 std::vector<SubdomainID> old_block_ids(num_blocks, Moose::INVALID_BLOCK_ID);
177 std::vector<SubdomainName> old_block_names(num_blocks);
178 std::stringstream missing_block;
179 for (const auto i : make_range(num_blocks))
180 {
181 const SubdomainName & name = _old_block[i];
182
183 // Convert the SubdomainName to an id and store
184 const auto id = MooseMeshUtils::getSubdomainID(name, *mesh);
185 old_block_ids[i] = id;
186
187 // Block does not exist - store for a future error
188 if (!block_ids.count(id))
189 missing_block << name << " ";
190
191 // Keep track of the block names
192 // If this SubdomainName is an ID, try to see if it has a name set
193 if (is_subdomain_id(name))
194 old_block_names[i] = const_mesh.subdomain_name(id);
195 // If this SubdomainName is a name, use said name
196 else
197 old_block_names[i] = name;
198 }
199 if (missing_block.str().size())
201 "The following blocks were requested to be renamed, but do not exist: ",
202 missing_block.str());
203
204 // Get the block IDs that we're moving to
205 std::vector<SubdomainID> new_block_ids(num_blocks, Moose::INVALID_BLOCK_ID);
206 std::map<SubdomainID, std::string> new_names;
207 for (const auto i : make_range(num_blocks))
208 {
209 const SubdomainName & name = _new_block[i];
210
211 // If the user input an ID, we have the ID
212 if (is_subdomain_id(name))
213 {
214 const auto id = MooseMeshUtils::getSubdomainID(name, *mesh);
215 new_block_ids[i] = id;
216
217 // In the case that this is a new block ID, keep track of it so that we
218 // don't reuse it if we have to create temporaries
219 block_ids.insert(id);
220
221 // Preserve the old block name if there was one
222 if (old_block_names[i].size())
223 new_names[id] = old_block_names[i];
224 }
225 // If the user input a name, we will use the ID that it is coming from for the
226 // "new" name if the new name does not name a current block. If the name does
227 // exist, we will merge with said block.
228 else
229 {
230 bool name_already_exists = false;
231
232 // If the target block already exists, merge into that one
233 // Check both the old maps and the new map
234 for (const auto map : {&const_mesh.get_subdomain_name_map(),
235 const_cast<const std::map<SubdomainID, std::string> *>(&new_names)})
236 for (const auto & id_name_pair : *map)
237 if (!name_already_exists && id_name_pair.second == name)
238 {
239 new_block_ids[i] = id_name_pair.first;
240 new_names[id_name_pair.first] = name;
241 name_already_exists = true;
242 }
243
244 // Target name doesn't exist, so use the source id/name
245 if (!name_already_exists)
246 {
247 new_block_ids[i] = old_block_ids[i];
248 new_names[new_block_ids[i]] = name;
249 }
250 }
251 }
252
253 // Create temporaries if needed; recall that this generator is independent
254 // of input ordering and does _not_ merge subdomains.
255 //
256 // Take the example where we want to move 0 -> 1 and 1 -> 2. If we just
257 // move them in order, we will actually end up with (0, 1) -> 2. This is
258 // bad. In this case, we want to first make a temporary for 1 (call it 3).
259 // We then do: 0 -> 3, 1 -> 2, 3 -> 1 in order to get the desired behavior.
260 // We will accomplish this by creating temporaries as needed, modifying
261 // the initial move to the temporaries as needed, and then moving the
262 // temporaries back. temp_change_ids here are the (from -> to) pairs
263 // that we will move at the end.
264 auto temp_new_block_ids = new_block_ids;
265 std::vector<std::pair<SubdomainID, SubdomainID>> temp_change_ids;
266 // Loop through all new IDs
267 for (const auto new_i : make_range(num_blocks))
268 {
269 // Look at all of the old IDs that will be moved after the move to the new ID.
270 // If any of the old IDs after are IDs that we are moving to, create a temporary
271 // and keep track of it so we can move it back at the end.
272 for (const auto old_i : make_range(new_i + 1, num_blocks))
273 if (new_block_ids[new_i] == old_block_ids[old_i])
274 {
275 const auto temp_id = get_unused_block_id();
276 temp_change_ids.emplace_back(temp_id, new_block_ids[new_i]);
277 temp_new_block_ids[new_i] = temp_id;
278 break;
279 }
280 }
281
282 // First pass through changing the block ids
283 for (const auto i : make_range(num_blocks))
284 MeshTools::Modification::change_subdomain_id(*mesh, old_block_ids[i], temp_new_block_ids[i]);
285 // Pass through moving the temporaries to the actual blocks, if necessary
286 for (const auto & pair : temp_change_ids)
287 MeshTools::Modification::change_subdomain_id(*mesh, pair.first, pair.second);
288
289 // First go through and remove all of the old names
290 for (const auto i : make_range(num_blocks))
291 if (mesh->get_subdomain_name_map().count(old_block_ids[i]))
292 mesh->set_subdomain_name_map().erase(old_block_ids[i]);
293 // With the old names removed, add the new names if there are any to add
294 for (const auto & pair : new_names)
295 mesh->set_subdomain_name(pair.first, pair.second);
296
297 mesh->unset_is_prepared();
298 return dynamic_pointer_cast<MeshBase>(mesh);
299}
registerMooseObject("MooseApp", RenameBlockGenerator)
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 addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
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()
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
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
MeshGenerator for re-numbering or re-naming blocks.
std::vector< SubdomainName > _old_block
The old blocks.
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
std::vector< SubdomainName > _new_block
The new blocks.
std::unique_ptr< MeshBase > & _input
static InputParameters validParams()
RenameBlockGenerator(const InputParameters &parameters)
std::string _old_block_param_name
The name of the parameter that specifies the old blocks.
MeshBase & mesh
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
Gets the subdomain ID associated with the given SubdomainName.
const SubdomainID INVALID_BLOCK_ID
Definition MooseTypes.C:20