Permalink
Browse files

Merge pull request #12512 from leorachapuis/new_mesh_generator_branch

Create RenameBoundaryGenerator.
  • Loading branch information...
friedmud committed Nov 20, 2018
2 parents 6428422 + 14c9f5d commit f826463239fed615b33ff1919e27ac93242815ac
@@ -0,0 +1,59 @@
# RenameBoundaryGenerator
!syntax description /MeshGenerators/RenameBoundaryGenerator
`RenameBoundaryGenerator` is usually used to provide meaningful names to boundaries.
For instance
```text
old_boundary_id = '1 2 3'
new_boundary_name = 'right top left'
```
Then the MOOSE input file can employ `boundary = right` rather than `boundary = 1`. `RenameBoundaryGenerator` may also
be used to provide more meaningful names to boundaries that are already named. For instance
```text
old_boundary_name = 'silly meaningless crazy'
new_boundary_name = 'right top left'
```
Then the MOOSE input file can employ `boundary = left` rather than `block = crazy`.
!alert warning
`RenameBoundaryGenerator` may also be used to merge boudaries, but care must be taken.
For instance
```
old_boundary_id = '1 2 3'
new_boundary_id = '4 4 4'
```
Then boudaries 1, 2 and 3 will be merged together into one boundary that may be used in the remainder of
the input file. However, when merging boundaries problems and even inconsistencies can occur.
Firstly, in the example just given, what if the boundaries 1, 2 and 3 were named? What should the name
of the boundary 4 be? The convention is that it is the name of the first old boundary that is given the
boundary ID of 4, which is the name of the old boundary 1 in this case. The user needs to be aware of this
convention. Similarly, if `old_boundary_name = 'oldA oldB'` and `new_boundary_name = 'new1 new1'`, then
the boundary ID of new1 is the boundary ID of oldA.
Secondly, in the example above, what if boundary 4 already existed? An inconsistency could arise in the
input file, because boundary 4 is now given the name of the old boundary 1.
Thirdly, in this example `old_boundary_id = '1 2'` and `new_boundary_name = 'wheel wheel'`
what if another boundary, with a different ID, already had the name
"wheel"? This can lead to great confusion in the MOOSE input file.
!alert note
Given all these potential problems, when merging boundaries it is strongly recommended to use just
**one** `RenameBoundaryGenerator` that includes the names or IDs of **all** the boundaries involved in the merging.
This will make the new boundary IDs and new boundary names unequivocally obvious.
!syntax parameters /MeshGenerators/RenameBoundaryGenerator
!syntax inputs /MeshGenerators/RenameBoundaryGenerator
!syntax children /MeshGenerators/RenameBoundaryGenerator
@@ -868,7 +868,7 @@ class MooseApp : public ConsoleStreamInterface, public libMesh::ParallelObject
std::map<std::string, std::shared_ptr<MeshGenerator>> _mesh_generators;
/// Holds the output for each mesh generator - including duplicates needed downstream
std::map<std::string, std::vector<std::unique_ptr<MeshBase>>> _mesh_generator_outputs;
std::map<std::string, std::list<std::unique_ptr<MeshBase>>> _mesh_generator_outputs;
/// The final Mesh that is generated by the generators
std::unique_ptr<MeshBase> _final_generated_mesh;
@@ -0,0 +1,93 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html
#ifndef RENAMEBOUNDARYGENERATOR_H
#define RENAMEBOUNDARYGENERATOR_H
#include "MeshGenerator.h"
// Forward declarations
class RenameBoundaryGenerator;
template <>
InputParameters validParams<RenameBoundaryGenerator>();
/**
* MeshGenerator for re-numbering or re-naming boundaries
*/
class RenameBoundaryGenerator : public MeshGenerator
{
public:
RenameBoundaryGenerator(const InputParameters & parameters);
std::unique_ptr<MeshBase> generate();
protected:
std::unique_ptr<MeshBase> & _input;
std::vector<boundary_id_type> _old_boundary_id;
std::vector<BoundaryName> _old_boundary_name;
std::vector<boundary_id_type> _new_boundary_id;
std::vector<BoundaryName> _new_boundary_name;
/**
* Given a new_boundary_id, provide a boundary name, based
* on the old boundary names provided (or deduced from
* the old_boundary_ids provided).
*
* Eg, if
* old_boundary_name = 'boundary1 boundary2'
* new_boundary_id = '4 5'
* Then
* newBoundaryName(4) = boundary1
* newBoundaryName(5) = boundary2
*
* In the case of merging boundaries, the *first encountered*
* boundary's name is used.
* Eg, if
* old_boundary_name = 'asdf boundary4 boundary1'
* new_boundary_id = '3 1 1'
* then
* newBoundaryName(1) = boundary4, because we look along
* new_boundary_id until we first encounter 1, and then get the corresponding name
* @param new_boundary_id the new boundary's ID number
* @return the name that will be given to that boundary
*/
BoundaryName newBoundaryName(const boundary_id_type & new_boundary_id);
/**
* Given a new_boundary_name, provide a boundary ID, based
* on the old boundary IDs provided (or deduced from
* the old_boundary_names provided).
*
* Eg, if
* old_boundary_id = '4 5'
* new_boundary_name = 'boundary1 boundary2'
* Then
* newBoundaryID(boundary1) = 4
* newBoundaryID(boundary2) = 5
*
* In the case of merging boundaries, the *first encountered*
* boundary's ID is used.
* Eg, if
* old_boundary_id = '3 1 1'
* new_boundary_name = 'asdf boundary4 boundary4'
* then
* newBoundaryID(boundary4) = 1, because we look along
* new_boundary_name until we first encounter boundary4, and then get the corresponding ID
* @param new_boundary_name the new boundary's name
* @return the ID number that will be given to that boundary
*/
BoundaryID newBoundaryID(const BoundaryName & new_boundary_name);
};
#endif // RENAMEBOUNDARYGENERATOR_H
@@ -1504,12 +1504,44 @@ MooseApp::executeMeshGenerators()
if (outputs.size())
{
// For the first one - just give it the same mesh that was just output
outputs[0] = std::move(_final_generated_mesh);
auto & first_output = *outputs.begin();
first_output = std::move(_final_generated_mesh);
const auto & copy_from = *first_output;
auto output_it = ++outputs.begin();
// For all of the rest we need to make a copy
for (size_t i = 1; i < outputs.size(); i++)
outputs[i] = outputs[0]->clone();
for (; output_it != outputs.end(); ++output_it)
{
(*output_it) = copy_from.clone();
(*output_it)->get_boundary_info() = copy_from.get_boundary_info();
(*output_it)->set_subdomain_name_map() = copy_from.get_subdomain_name_map();
// Get references to BoundaryInfo objects to make the code below cleaner...
const BoundaryInfo & first_boundary_info = copy_from.get_boundary_info();
BoundaryInfo & boundary_info = (*output_it)->get_boundary_info();
// Use the first BoundaryInfo object to build the list of side boundary ids
std::vector<boundary_id_type> side_boundaries;
first_boundary_info.build_side_boundary_ids(side_boundaries);
// Assign those boundary ids in our BoundaryInfo object
for (const auto & side_bnd_id : side_boundaries)
boundary_info.sideset_name(side_bnd_id) =
first_boundary_info.get_sideset_name(side_bnd_id);
// Do the same thing for node boundary ids
std::vector<boundary_id_type> node_boundaries;
first_boundary_info.build_node_boundary_ids(node_boundaries);
for (const auto & node_bnd_id : node_boundaries)
boundary_info.nodeset_name(node_bnd_id) =
first_boundary_info.get_nodeset_name(node_bnd_id);
}
}
}
}
@@ -0,0 +1,166 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html
#include "RenameBoundaryGenerator.h"
#include "CastUniquePointer.h"
registerMooseObject("MooseApp", RenameBoundaryGenerator);
template <>
InputParameters
validParams<RenameBoundaryGenerator>()
{
InputParameters params = validParams<MeshGenerator>();
params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
params.addParam<std::vector<boundary_id_type>>(
"old_boundary_id",
"Elements with this boundary number will be given the new_boundary_number or "
"new_boundary_name. You must supply either old_boundary_id or old_boundary_name. "
"You may supply a vector of old_boundary_id, in which case the new_boundary "
"information must also be a vector.");
params.addParam<std::vector<BoundaryName>>(
"old_boundary_name",
"Elements with this boundary name will be given the new_boundary_number or "
"new_boundary_name. You must supply either old_boundary_id or old_boundary_name. "
"You may supply a vector of old_boundary_name, in which case the new_boundary "
"information must also be a vector.");
params.addParam<std::vector<boundary_id_type>>(
"new_boundary_id",
"Elements with the old boundary number (or name) will be given this boundary "
"number. If the old boundaries are named, their names will be passed onto the "
"newly numbered boundarys.");
params.addParam<std::vector<BoundaryName>>(
"new_boundary_name",
"Elements with the old boundary number (or name) will be given this boundary "
"name. No change of boundary ID is performed, unless multiple old boundaries are "
"given the same name, in which case they are all given the first old boundary "
"number.");
params.addClassDescription(
"RenameBoundaryGenerator re-numbers or re-names an old_boundary_id or old_boundary_name "
"with a new_boundary_id or new_boundary_name. If using RenameBoundaryGenerator to "
"merge boundaries (by giving them the same name, for instance) it is "
"advisable to specify all your boundaries in old_boundaries to avoid inconsistencies");
return params;
}
RenameBoundaryGenerator::RenameBoundaryGenerator(const InputParameters & parameters)
: MeshGenerator(parameters), _input(getMesh("input"))
{
// error checking. Must have exactly one of old_boundary_id or old_boundary_name
if (isParamValid("old_boundary_id") && isParamValid("old_boundary_name"))
mooseError("RenameBoundaryGenerator: You must supply exactly one of old_boundary_id or "
"old_boundary_name\n");
else if (!isParamValid("old_boundary_id") && !isParamValid("old_boundary_name"))
mooseError("RenameBoundaryGenerator: You must supply exactly one of old_boundary_id or "
"old_boundary_name\n");
// error checking. Must have exactly one of new_boundary_id or new_boundary_name
// In principal we could have both (the old boundary would then be given a new ID and a new name)
// but i feel that could lead to confusion for the user. If the user wants to do that they
// should use two of these RenameBoundary MeshModifiers.
if (isParamValid("new_boundary_id") && isParamValid("new_boundary_name"))
mooseError("RenameBoundaryGenerator: You must supply exactly one of new_boundary_id or "
"new_boundary_name\n");
else if (!isParamValid("new_boundary_id") && !isParamValid("new_boundary_name"))
mooseError("RenameBoundaryGenerator: You must supply exactly one of new_boundary_id or "
"new_boundary_name\n");
}
std::unique_ptr<MeshBase>
RenameBoundaryGenerator::generate()
{
std::unique_ptr<MeshBase> mesh = std::move(_input);
auto & boundary_info = mesh->get_boundary_info();
// grab the user input. Can't do all this in the constructor as some things may not
// have been put into the mesh yet, eg old_boundary_name might have been inserted by
// another MeshGenerator
if (isParamValid("old_boundary_id"))
{
// user must have supplied old_boundary_id
_old_boundary_id = getParam<std::vector<boundary_id_type>>("old_boundary_id");
_old_boundary_name.reserve(_old_boundary_id.size());
for (const auto & boundary_id : _old_boundary_id)
_old_boundary_name.emplace_back(boundary_info.get_sideset_name(boundary_id));
}
else
{
// user must have supplied old_boundary_name
_old_boundary_name = getParam<std::vector<BoundaryName>>("old_boundary_name");
_old_boundary_id.reserve(_old_boundary_name.size());
for (const auto & boundary_name : _old_boundary_name)
_old_boundary_id.emplace_back(mesh->get_id_by_name(boundary_name));
}
// construct new_boundary_id and new_boundary_name
if (isParamValid("new_boundary_id"))
{
_new_boundary_id = getParam<std::vector<boundary_id_type>>("new_boundary_id");
if (_new_boundary_id.size() != _old_boundary_id.size())
mooseError(
"RenameBoundaryGenerator: The vector of old_boundary information must have the same"
" length as the vector of new_boundary information\n");
// construct the _new_boundary_name
_new_boundary_name.reserve(_new_boundary_id.size());
for (const auto & boundary_id : _new_boundary_id)
_new_boundary_name.emplace_back(newBoundaryName(boundary_id));
}
else // must have supplied new_boundary_name
{
_new_boundary_name = getParam<std::vector<BoundaryName>>("new_boundary_name");
if (_new_boundary_name.size() != _old_boundary_id.size())
mooseError(
"RenameBoundaryGenerator: The vector of old_boundary information must have the same"
" length as the vector of new_boundary information\n");
_new_boundary_id.reserve(_new_boundary_name.size());
for (const auto & boundary_name : _new_boundary_name)
_new_boundary_id.emplace_back(newBoundaryID(boundary_name));
}
for (const auto & elem : mesh->active_element_ptr_range())
{
for (unsigned int side = 0; side < elem->n_sides(); side++)
{
for (unsigned i = 0; i < _old_boundary_id.size(); ++i)
if (boundary_info.has_boundary_id(elem, side, _old_boundary_id[i]))
{
boundary_info.remove_side(elem, side);
boundary_info.add_side(elem, side, _new_boundary_id[i]);
}
}
}
for (unsigned i = 0; i < _old_boundary_id.size(); ++i)
if (_new_boundary_name[i].size() > 0)
boundary_info.sideset_name(_old_boundary_id[i]) = _new_boundary_name[i];
return dynamic_pointer_cast<MeshBase>(mesh);
}
BoundaryName
RenameBoundaryGenerator::newBoundaryName(const boundary_id_type & new_boundary_id)
{
for (unsigned i = 0; i < _new_boundary_id.size(); ++i)
if (_new_boundary_id[i] == new_boundary_id)
return _old_boundary_name[i];
mooseError("RenameBoundaryGenerator: error in code");
}
boundary_id_type
RenameBoundaryGenerator::newBoundaryID(const BoundaryName & new_boundary_name)
{
for (unsigned i = 0; i < _new_boundary_name.size(); ++i)
if (_new_boundary_name[i] == new_boundary_name)
return _old_boundary_id[i];
mooseError("RenameBoundaryGenerator: error in code");
}
Oops, something went wrong.

0 comments on commit f826463

Please sign in to comment.