Line data Source code
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 :
10 : #include "StackGenerator.h"
11 : #include "CastUniquePointer.h"
12 :
13 : #include "libmesh/replicated_mesh.h"
14 : #include "libmesh/distributed_mesh.h"
15 : #include "libmesh/boundary_info.h"
16 : #include "libmesh/mesh_modification.h"
17 : #include "libmesh/bounding_box.h"
18 : #include "libmesh/mesh_tools.h"
19 : #include "libmesh/point.h"
20 : #include "MooseMeshUtils.h"
21 :
22 : #include <typeinfo>
23 :
24 : registerMooseObject("MooseApp", StackGenerator);
25 :
26 : InputParameters
27 14305 : StackGenerator::validParams()
28 : {
29 14305 : InputParameters params = MeshGenerator::validParams();
30 :
31 14305 : MooseEnum dims("2=2 3=3");
32 14305 : params.addRequiredParam<MooseEnum>("dim", dims, "The dimension of the mesh to be generated");
33 :
34 14305 : params.addRequiredParam<std::vector<MeshGeneratorName>>("inputs",
35 : "The meshes we want to stitch together");
36 :
37 14305 : params.addParam<Real>("bottom_height", 0, "The height of the bottom of the final mesh");
38 :
39 : // y boundary names (2D case)
40 14305 : params.addParam<BoundaryName>("top_boundary", "top", "name of the top (y) boundary");
41 14305 : params.addParam<BoundaryName>("bottom_boundary", "bottom", "name of the bottom (y) boundary");
42 :
43 : // z boundary names (3D case)
44 14305 : params.addParam<BoundaryName>("front_boundary", "front", "name of the front (z) boundary");
45 14305 : params.addParam<BoundaryName>("back_boundary", "back", "name of the back (z) boundary");
46 :
47 14305 : params.addClassDescription("Use the supplied meshes and stitch them on top of each other");
48 :
49 28610 : return params;
50 14305 : }
51 :
52 20 : StackGenerator::StackGenerator(const InputParameters & parameters)
53 : : MeshGenerator(parameters),
54 20 : _dim(getParam<MooseEnum>("dim")),
55 20 : _mesh_ptrs(getMeshes("inputs")),
56 20 : _input_names(getParam<std::vector<MeshGeneratorName>>("inputs")),
57 40 : _bottom_height(getParam<Real>("bottom_height"))
58 : {
59 20 : }
60 :
61 : std::unique_ptr<MeshBase>
62 20 : StackGenerator::generate()
63 : {
64 20 : std::unique_ptr<ReplicatedMesh> mesh = dynamic_pointer_cast<ReplicatedMesh>(*_mesh_ptrs[0]);
65 20 : if (mesh == nullptr)
66 0 : mooseError("StackGenerator only works with ReplicatedMesh : mesh from Meshgenerator ",
67 0 : _input_names[0],
68 : "is not a ReplicatedMesh.");
69 :
70 20 : int dim = static_cast<int>(_dim);
71 :
72 20 : if (dim != int(mesh->mesh_dimension()))
73 0 : paramError("dim",
74 : "incompatible mesh dimensions: dim=",
75 : dim,
76 : " and first mesh dimension is ",
77 0 : mesh->mesh_dimension());
78 :
79 : // Reserve spaces for the other meshes (no need to store the first one another time)
80 20 : _meshes.reserve(_input_names.size() - 1);
81 :
82 : // Read in all of the other meshes
83 72 : for (MooseIndex(_input_names) i = 1; i < _input_names.size(); ++i)
84 52 : _meshes.push_back(dynamic_pointer_cast<ReplicatedMesh>(*_mesh_ptrs[i]));
85 :
86 : // Check that the casts didn't fail, and that the dimensions match
87 68 : for (MooseIndex(_meshes) i = 0; i < _meshes.size(); ++i)
88 : {
89 52 : if (_meshes[i] == nullptr)
90 0 : mooseError("StackGenerator only works with ReplicatedMesh : mesh from Meshgenerator ",
91 0 : _input_names[i + 1],
92 : "is not a ReplicatedMesh.");
93 52 : if (static_cast<int>(_meshes[i]->mesh_dimension()) != dim)
94 4 : mooseError("Mesh from MeshGenerator : ", _input_names[i + 1], " is not in ", _dim, "D.");
95 : }
96 :
97 : // Getting the boundaries provided by the user
98 : std::vector<BoundaryName> boundary_names = {getParam<BoundaryName>("top_boundary"),
99 48 : getParam<BoundaryName>("bottom_boundary")};
100 16 : if (dim == 3)
101 24 : boundary_names = {getParam<BoundaryName>("front_boundary"),
102 24 : getParam<BoundaryName>("back_boundary")};
103 :
104 : std::vector<boundary_id_type> ids =
105 16 : MooseMeshUtils::getBoundaryIDs(*_meshes[0], boundary_names, true);
106 :
107 : mooseAssert(ids.size() == boundary_names.size(),
108 : "Unexpected number of ids returned for MooseMeshUtils::getBoundaryIDs");
109 :
110 16 : boundary_id_type first = ids[0], second = ids[1];
111 :
112 : // Getting the width of each mesh
113 16 : std::vector<Real> heights;
114 16 : heights.push_back(computeWidth(*mesh, _dim) + _bottom_height);
115 64 : for (MooseIndex(_meshes) i = 0; i < _meshes.size(); ++i)
116 48 : heights.push_back(computeWidth(*_meshes[i], _dim) + *heights.rbegin());
117 :
118 : // Move the first mesh at the provided height
119 16 : switch (_dim)
120 : {
121 8 : case 2:
122 8 : MeshTools::Modification::translate(*mesh, 0, _bottom_height, 0);
123 8 : break;
124 8 : case 3:
125 8 : MeshTools::Modification::translate(*mesh, 0, 0, _bottom_height);
126 8 : break;
127 : }
128 :
129 : // Move all of the other meshes in the right spots then stitch them one by one to the first one
130 64 : for (MooseIndex(_meshes) i = 0; i < _meshes.size(); ++i)
131 : {
132 48 : switch (_dim)
133 : {
134 24 : case 2:
135 24 : MeshTools::Modification::translate(*_meshes[i], 0, heights[i], 0);
136 24 : break;
137 24 : case 3:
138 24 : MeshTools::Modification::translate(*_meshes[i], 0, 0, heights[i]);
139 24 : break;
140 : }
141 96 : mesh->stitch_meshes(
142 48 : *_meshes[i], first, second, TOLERANCE, /*clear_stitched_boundary_ids=*/true);
143 : }
144 :
145 32 : return dynamic_pointer_cast<MeshBase>(mesh);
146 56 : }
147 :
148 : Real
149 64 : StackGenerator::computeWidth(const MeshBase & mesh, const int & dim)
150 : {
151 64 : BoundingBox bbox = MeshTools::create_bounding_box(mesh);
152 64 : return bbox.max()(dim - 1) - bbox.min()(dim - 1);
153 : }
|