https://mooseframework.inl.gov
FillBetweenSidesetsGenerator.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 
12 
13 #include "MooseMeshUtils.h"
14 #include "CastUniquePointer.h"
15 #include "libmesh/node.h"
16 #include "libmesh/mesh_serializer.h"
17 
19 
22 {
24  params.addRequiredParam<MeshGeneratorName>("input_mesh_1",
25  "The input mesh that contains boundary_1");
26  params.addRequiredParam<MeshGeneratorName>("input_mesh_2",
27  "The input mesh that contains boundary_2");
28  params.addRequiredParam<std::vector<BoundaryName>>(
29  "boundary_1", "the first boundary that needs to be connected.");
30  params.addRequiredParam<std::vector<BoundaryName>>(
31  "boundary_2", "the second boundary that needs to be connected.");
32  params.addParam<Point>(
33  "mesh_1_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_1");
34  params.addParam<Point>(
35  "mesh_2_shift", Point(0.0, 0.0, 0.0), "Translation vector to be applied to input_mesh_2");
36  params.addRequiredRangeCheckedParam<unsigned int>(
37  "num_layers", "num_layers>0", "Number of layers of elements created between the boundaries.");
38  params.addParam<subdomain_id_type>("block_id", 1, "ID to be assigned to the transition layer.");
39  params.addParam<boundary_id_type>(
40  "input_boundary_1_id",
41  10000,
42  "Boundary ID to be assigned to the boundary defined by positions_vector_1.");
43  params.addParam<boundary_id_type>(
44  "input_boundary_2_id",
45  10000,
46  "Boundary ID to be assigned to the boundary defined by positions_vector_2.");
47  params.addParam<boundary_id_type>("begin_side_boundary_id",
48  10000,
49  "Boundary ID to be assigned to the boundary connecting "
50  "starting points of the positions_vectors.");
51  params.addParam<boundary_id_type>("end_side_boundary_id",
52  10000,
53  "Boundary ID to be assigned to the boundary connecting ending "
54  "points of the positions_vectors.");
55  params.addParam<bool>(
56  "use_quad_elements",
57  false,
58  "Whether QUAD4 instead of TRI3 elements are used to construct the transition layer.");
59  params.addRangeCheckedParam<Real>(
60  "bias_parameter",
61  1.0,
62  "bias_parameter>=0",
63  "Parameter used to set up biasing of the layers: bias_parameter > 0.0 is used as the biasing "
64  "factor; bias_parameter = 0.0 activates automatic biasing based on local node density on "
65  "both input boundaries.");
66  params.addRangeCheckedParam<Real>(
67  "gaussian_sigma",
68  3.0,
69  "gaussian_sigma>0.0",
70  "Gaussian parameter used to smoothen local node density for automatic biasing; this "
71  "parameter is not used if another biasing option is selected.");
72  params.addParam<bool>(
73  "keep_inputs",
74  true,
75  "Whether to output the input meshes stitched with the transition layer connector.");
76  params.addClassDescription("This FillBetweenSidesetsGenerator object is designed to generate a "
77  "transition layer to connect two boundaries of two input meshes.");
78  return params;
79 }
80 
82  : MeshGenerator(parameters),
83  _input_name_1(getParam<MeshGeneratorName>("input_mesh_1")),
84  _input_name_2(getParam<MeshGeneratorName>("input_mesh_2")),
85  _boundary_1(getParam<std::vector<BoundaryName>>("boundary_1")),
86  _boundary_2(getParam<std::vector<BoundaryName>>("boundary_2")),
87  _mesh_1_shift(getParam<Point>("mesh_1_shift")),
88  _mesh_2_shift(getParam<Point>("mesh_2_shift")),
89  _num_layers(getParam<unsigned int>("num_layers")),
90  _block_id(getParam<subdomain_id_type>("block_id")),
91  _input_boundary_1_id(getParam<boundary_id_type>("input_boundary_1_id")),
92  _input_boundary_2_id(getParam<boundary_id_type>("input_boundary_2_id")),
93  _begin_side_boundary_id(getParam<boundary_id_type>("begin_side_boundary_id")),
94  _end_side_boundary_id(getParam<boundary_id_type>("end_side_boundary_id")),
95  _use_quad_elements(getParam<bool>("use_quad_elements")),
96  _bias_parameter(getParam<Real>("bias_parameter")),
97  _sigma(getParam<Real>("gaussian_sigma")),
98  _keep_inputs(getParam<bool>("keep_inputs")),
99  _input_1(getMeshByName(_input_name_1)),
100  _input_2(getMeshByName(_input_name_2))
101 {
102  if (_input_name_1.compare(_input_name_2) == 0)
103  paramError("input_mesh_2", "This parameter must be different from input_mesh_1.");
104 }
105 
106 std::unique_ptr<MeshBase>
108 {
109  auto input_mesh_1 = std::move(_input_1);
110  auto input_mesh_2 = std::move(_input_2);
111 
112  // Only serialized meshes are supported right now
113  libMesh::MeshSerializer serial_1(*input_mesh_1);
114  libMesh::MeshSerializer serial_2(*input_mesh_2);
115 
116  if (*(input_mesh_1->elem_dimensions().begin()) != 2 ||
117  *(input_mesh_1->elem_dimensions().rbegin()) != 2)
118  paramError("input_mesh_1", "Only 2D meshes are supported.");
119  if (*(input_mesh_2->elem_dimensions().begin()) != 2 ||
120  *(input_mesh_2->elem_dimensions().rbegin()) != 2)
121  paramError("input_mesh_2", "Only 2D meshes are supported.");
122 
123  MeshTools::Modification::translate(
124  *input_mesh_1, _mesh_1_shift(0), _mesh_1_shift(1), _mesh_1_shift(2));
125  MeshTools::Modification::translate(
126  *input_mesh_2, _mesh_2_shift(0), _mesh_2_shift(1), _mesh_2_shift(2));
127 
128  const auto input_mesh_1_external_bids =
129  MooseMeshUtils::getBoundaryIDs(*input_mesh_1, _boundary_1, false);
130  const auto input_mesh_2_external_bids =
131  MooseMeshUtils::getBoundaryIDs(*input_mesh_2, _boundary_2, false);
132 
133  for (unsigned int i = 1; i < input_mesh_1_external_bids.size(); i++)
134  {
136  *input_mesh_1, input_mesh_1_external_bids[i], input_mesh_1_external_bids.front(), true);
137  }
138  for (unsigned int i = 1; i < input_mesh_2_external_bids.size(); i++)
139  {
141  *input_mesh_2, input_mesh_2_external_bids[i], input_mesh_2_external_bids.front(), true);
142  }
143 
145  input_mesh_1_external_bids.front()))
146  paramError("boundary_1", "The boundary provided is not an external boundary.");
148  input_mesh_2_external_bids.front()))
149  paramError("boundary_2", "The boundary provided is not an external boundary.");
150 
151  Real max_input_mesh_1_node_radius;
152  Real max_input_mesh_2_node_radius;
153  std::vector<dof_id_type> boundary_1_ordered_nodes;
154  std::vector<dof_id_type> boundary_2_ordered_nodes;
155 
156  try
157  {
159  *input_mesh_1,
160  max_input_mesh_1_node_radius,
161  boundary_1_ordered_nodes,
163  input_mesh_1_external_bids.front());
164  }
165  catch (MooseException & e)
166  {
167  paramError("boundary_1", e.what());
168  }
169  try
170  {
172  *input_mesh_2,
173  max_input_mesh_2_node_radius,
174  boundary_2_ordered_nodes,
176  input_mesh_2_external_bids.front());
177  }
178  catch (MooseException & e)
179  {
180  paramError("boundary_2", e.what());
181  }
182 
183  std::vector<Point> positions_vector_1;
184  std::vector<Point> positions_vector_2;
185 
186  for (auto & boundary_1_node_id : boundary_1_ordered_nodes)
187  positions_vector_1.push_back(*input_mesh_1->node_ptr(boundary_1_node_id));
188 
189  for (auto & boundary_2_node_id : boundary_2_ordered_nodes)
190  positions_vector_2.push_back(*input_mesh_2->node_ptr(boundary_2_node_id));
191 
192  const boundary_id_type input_boundary_1_id = _keep_inputs ? (std::max({_input_boundary_1_id,
196  1)
198  const boundary_id_type input_boundary_2_id =
199  _keep_inputs ? (input_boundary_1_id + 1) : _input_boundary_2_id;
200  auto mesh = buildReplicatedMesh(2);
202  positions_vector_1,
203  positions_vector_2,
204  _num_layers,
205  _block_id,
206  input_boundary_1_id,
207  input_boundary_2_id,
210  _type,
211  _name,
214  _sigma);
215 
216  if (_keep_inputs)
217  {
218  mesh->prepare_for_use();
219  mesh->stitch_meshes(*input_mesh_1,
220  input_boundary_1_id,
221  input_mesh_1_external_bids.front(),
222  TOLERANCE,
223  true,
224  false,
225  true,
226  true);
227  mesh->stitch_meshes(*input_mesh_2,
228  input_boundary_2_id,
229  input_mesh_2_external_bids.front(),
230  TOLERANCE,
231  true,
232  false,
233  true,
234  true);
235  }
236  return dynamic_pointer_cast<MeshBase>(mesh);
237 }
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
These methods add an range checked parameters.
virtual const char * what() const
Get out the error message.
const std::string & _name
The name of this class.
Definition: MooseBase.h:359
const Point _mesh_1_shift
Translation applied to the first input mesh.
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh(unsigned int dim=libMesh::invalid_uint)
Build a replicated mesh.
const MeshGeneratorName _input_name_2
Name of the mesh which contains the second input boundary.
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:435
const Point _mesh_2_shift
Translation applied to the second input mesh.
std::unique_ptr< MeshBase > & _input_2
The mesh which contains the second input boundary.
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
MeshBase & mesh
const boundary_id_type _begin_side_boundary_id
ID to be assigned to the boundary that connects the starting points of positions_vectors.
const boundary_id_type _end_side_boundary_id
ID to be assigned to the boundary that connects the ending points of positions_vectors.
const boundary_id_type _input_boundary_1_id
ID to be assigned to the boundary that corresponds to the input boundary on the first input 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.
std::unique_ptr< MeshBase > & _input_1
The mesh which contains the first input boundary.
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...
auto max(const L &left, const R &right)
This FillBetweenSidesetsGenerator object is designed to generate a transition layer to connect two bo...
const std::vector< BoundaryName > _boundary_2
Name of the second input boundary for the transition layer generation.
bool isBoundaryOpenSingleSegment(MeshBase &mesh, Real &max_node_radius, std::vector< dof_id_type > &boundary_ordered_node_list, const Point origin_pt, const boundary_id_type bid)
Decides whether a boundary of a given mesh is an open single-segment boundary.
int8_t boundary_id_type
void fillBetweenPointVectorsGenerator(MeshBase &mesh, const std::vector< Point > &boundary_points_vec_1, const std::vector< Point > &boundary_points_vec_2, const unsigned int num_layers, const subdomain_id_type transition_layer_id, const boundary_id_type input_boundary_1_id, const boundary_id_type input_boundary_2_id, const boundary_id_type begin_side_boundary_id, const boundary_id_type end_side_boundary_id, const std::string type, const std::string name, const bool quad_elem=false, const Real bias_parameter=1.0, const Real sigma=3.0)
Generates a 2D mesh with triangular elements for a region defined by two curves (sets of Points) ...
registerMooseObject("MooseApp", FillBetweenSidesetsGenerator)
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.
static InputParameters validParams()
Definition: MeshGenerator.C:23
const Real _bias_parameter
A parameter used to set up mesh biasing of the layers.
const boundary_id_type _input_boundary_2_id
ID to be assigned to the boundary that corresponds to the input boundary on the second input mesh...
Provides a way for users to bail out of the current solve.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Real _sigma
Parameter used for Gaussian blurring of local node density.
const subdomain_id_type _block_id
Subdomain ID to be assigned to the generated transition layer.
FillBetweenSidesetsGenerator(const InputParameters &parameters)
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...
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Point meshCentroidCalculator(const MeshBase &mesh)
Calculates the centroid of a MeshBase.
void changeBoundaryId(MeshBase &mesh, const libMesh::boundary_id_type old_id, const libMesh::boundary_id_type new_id, bool delete_prev)
Changes the old boundary ID to a new ID in the mesh.
const bool _keep_inputs
Whether the input meshes are retained in the output.
const bool _use_quad_elements
A boolean parameter to determine whether QUAD4 elements are used instead of TRI3 elements.
bool isExternalBoundary(MeshBase &mesh, const boundary_id_type bid)
Decides whether a boundary of a given mesh is an external boundary.
const unsigned int _num_layers
Number of sublayers of the mesh to be generated.
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:32
void ErrorVector unsigned int
const std::string & _type
The type of this class.
Definition: MooseBase.h:356
const std::vector< BoundaryName > _boundary_1
Name of the first input boundary for the transition layer generation.
const MeshGeneratorName _input_name_1
Name of the mesh which contains the first input boundary.