www.mooseframework.org
MeshExtruderGenerator.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "MeshExtruderGenerator.h"
11 #include "MooseMeshUtils.h"
12 #include "CastUniquePointer.h"
13 
14 #include "libmesh/replicated_mesh.h"
15 #include "libmesh/boundary_info.h"
16 #include "libmesh/elem.h"
17 
19 
20 template <>
23 {
25 
26  params.addRequiredParam<MeshGeneratorName>("input", "the mesh we want to extrude");
27  params.addClassDescription("Takes a 1D or 2D mesh and extrudes the entire structure along the "
28  "specified axis increasing the dimensionality of the mesh.");
29  params.addRequiredParam<RealVectorValue>("extrusion_vector",
30  "The direction and length of the extrusion");
31  params.addParam<unsigned int>("num_layers", 1, "The number of layers in the extruded mesh");
32  params.addParam<std::vector<BoundaryName>>(
33  "bottom_sideset", "The boundary that will be applied to the bottom of the extruded mesh");
34  params.addParam<std::vector<BoundaryName>>(
35  "top_sideset", "The boundary that will be to the top of the extruded mesh");
36 
37  params.addParam<std::vector<SubdomainID>>(
38  "existing_subdomains",
39  std::vector<SubdomainID>(),
40  "The subdomains that will be remapped for specific layers");
41  params.addParam<std::vector<unsigned int>>(
42  "layers",
43  std::vector<unsigned int>(),
44  "The layers where the \"existing_subdomain\" will be remapped to new ids");
45  params.addParam<std::vector<unsigned int>>(
46  "new_ids",
47  std::vector<unsigned int>(),
48  "The list of new ids, This list should be either length \"existing_subdomains\" or "
49  "\"existing_subdomains\" * layers");
50 
51  return params;
52 }
53 
55  : MeshGenerator(parameters),
56  _input(getMesh("input")),
57  _extrusion_vector(getParam<RealVectorValue>("extrusion_vector")),
58  _num_layers(getParam<unsigned int>("num_layers")),
59  _existing_subdomains(getParam<std::vector<SubdomainID>>("existing_subdomains")),
60  _layers(getParam<std::vector<unsigned int>>("layers")),
61  _new_ids(getParam<std::vector<unsigned int>>("new_ids"))
62 {
63  // Check the length of the vectors
64  if (_existing_subdomains.size() != _new_ids.size() &&
65  _existing_subdomains.size() * _layers.size() != _new_ids.size())
66  mooseError(
67  "The length of the \"existing_subdomains\", \"layers\", and \"new_ids\" are not valid");
68 }
69 
70 std::unique_ptr<MeshBase>
72 {
73  std::unique_ptr<MeshBase> source_mesh = std::move(_input);
74 
75  std::unique_ptr<ReplicatedMesh> mesh = libmesh_make_unique<ReplicatedMesh>(comm());
76 
77  if (source_mesh->mesh_dimension() == 3)
78  mooseError("You cannot extrude a 3D mesh !");
79 
80  std::unique_ptr<QueryElemSubdomainID> elem_subdomain_id;
81  if (_existing_subdomains.size() > 0)
82  elem_subdomain_id = libmesh_make_unique<QueryElemSubdomainID>(
84 
85  MeshTools::Generation::build_extrusion(
86  *mesh, *source_mesh, _num_layers, _extrusion_vector, elem_subdomain_id.get());
87 
88  // See if the user has requested specific sides for the top and bottom
89  std::set<boundary_id_type> side_ids = mesh->get_boundary_info().get_side_boundary_ids();
90 
91  // Handle distributed meshes: processors may not know all side ids
92  _communicator.set_union(side_ids);
93 
94  std::set<boundary_id_type>::reverse_iterator last_side_it = side_ids.rbegin();
95 
96  const boundary_id_type old_top = *last_side_it;
97  mooseAssert(last_side_it != side_ids.rend(), "Error in generating sidesets for extruded mesh");
98  const boundary_id_type old_bottom = *++last_side_it;
99 
100  // Update the IDs
101  if (isParamValid("bottom_sideset"))
102  changeID(*mesh, getParam<std::vector<BoundaryName>>("bottom_sideset"), old_bottom);
103  if (isParamValid("top_sideset"))
104  changeID(*mesh, getParam<std::vector<BoundaryName>>("top_sideset"), old_top);
105 
106  return dynamic_pointer_cast<MeshBase>(mesh);
107 }
108 
109 void
111  const std::vector<BoundaryName> & names,
112  BoundaryID old_id)
113 {
114  std::vector<boundary_id_type> boundary_ids = MooseMeshUtils::getBoundaryIDs(mesh, names, true);
115 
116  if (std::find(boundary_ids.begin(), boundary_ids.end(), old_id) == boundary_ids.end())
117  MooseMeshUtils::changeBoundaryId(mesh, old_id, boundary_ids[0], true);
118 
119  for (unsigned int i = 0; i < boundary_ids.size(); ++i)
120  {
121  mesh.get_boundary_info().sideset_name(boundary_ids[i]) = names[i];
122  mesh.get_boundary_info().nodeset_name(boundary_ids[i]) = names[i];
123  }
124 }
125 
127  const std::vector<SubdomainID> & existing_subdomains,
128  std::vector<unsigned int> layers,
129  const std::vector<unsigned int> & new_ids,
130  unsigned int num_layers)
131  : QueryElemSubdomainIDBase(), _num_layers(num_layers)
132 {
133  // Setup our stride depending on whether the user passed unique sets in new ids or just a single
134  // set of new ids
135  const unsigned int stride =
136  existing_subdomains.size() == new_ids.size() ? 0 : existing_subdomains.size();
137 
138  if (layers.size() == 0)
139  for (unsigned int i = 0; i < _num_layers; i++)
140  layers.push_back(i);
141 
142  // Populate the data structure
143  for (unsigned int i = 0; i < layers.size(); ++i)
144  for (unsigned int j = 0; j < existing_subdomains.size(); ++j)
145  _layer_data[layers[i]][existing_subdomains[j]] = new_ids[i * stride + j];
146 }
147 
148 subdomain_id_type
150  unsigned int layer)
151 {
152  mooseAssert(layer < _num_layers, "Access out of bounds: " << layer);
153 
154  // First locate the layer if it exists
155  std::map<unsigned int, std::map<SubdomainID, unsigned int>>::const_iterator layer_it =
156  _layer_data.find(layer);
157 
158  if (layer_it == _layer_data.end())
159  // If the layer wasn't found, there is no mapping so just return the original subdomain id
160  return old_elem->subdomain_id();
161  else
162  {
163  std::map<SubdomainID, unsigned int>::const_iterator sub_id_it =
164  layer_it->second.find(old_elem->subdomain_id());
165 
166  if (sub_id_it == layer_it->second.end())
167  // If the subdomain wasn't found, it won't be remapped, so just return the original subdomain
168  // id
169  return old_elem->subdomain_id();
170 
171  // Return the remapped id
172  return sub_id_it->second;
173  }
174 }
Extrude a 1D or 2D mesh to a 2D or 3D mesh respectively.
QueryElemSubdomainID(const std::vector< SubdomainID > &existing_subdomains, std::vector< unsigned int > layers, const std::vector< unsigned int > &new_ids, unsigned int num_layers)
VectorValue< Real > RealVectorValue
Definition: Assembly.h:31
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
InputParameters validParams< MeshExtruderGenerator >()
virtual subdomain_id_type get_subdomain_for_layer(const Elem *old_elem, unsigned int layer)
The override from the base class for obtaining a new id based on the old (original) element and the s...
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 mooseError(Args &&... args) const
Definition: MooseObject.h:147
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition: MooseObject.h:191
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...
registerMooseObject("MooseApp", MeshExtruderGenerator)
boundary_id_type BoundaryID
void changeID(MeshBase &mesh, const std::vector< BoundaryName > &names, BoundaryID old_id)
std::vector< unsigned int > _layers
subdomain_id_type SubdomainID
std::vector< libMesh::boundary_id_type > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown)
std::unique_ptr< MeshBase > & _input
Mesh that comes from another generator.
std::map< unsigned int, std::map< SubdomainID, unsigned int > > _layer_data
Data structure for holding the old -> new id mapping based on the layer number.
const RealVectorValue _extrusion_vector
std::vector< SubdomainID > _existing_subdomains
MPI_Comm comm
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 option parameter and a documentation string to the InputParameters object...
void changeBoundaryId(MeshBase &mesh, const libMesh::boundary_id_type old_id, const libMesh::boundary_id_type new_id, bool delete_prev)
InputParameters validParams< MeshGenerator >()
Definition: MeshGenerator.C:16
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseObject.h:89
MeshExtruderGenerator(const InputParameters &parameters)
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:30
std::vector< unsigned int > _new_ids
unsigned int _num_layers
The total number of layers in the extrusion.