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 "PatternedMesh.h"
11 : #include "Parser.h"
12 : #include "InputParameters.h"
13 : #include "MooseApp.h"
14 :
15 : #include "libmesh/mesh_modification.h"
16 : #include "libmesh/serial_mesh.h"
17 : #include "libmesh/exodusII_io.h"
18 :
19 : registerMooseObject("MooseApp", PatternedMesh);
20 :
21 : InputParameters
22 14285 : PatternedMesh::validParams()
23 : {
24 14285 : InputParameters params = MooseMesh::validParams();
25 14285 : params.addRequiredParam<std::vector<MeshFileName>>("files",
26 : "The name of the mesh files to read. "
27 : " They are automatically assigned "
28 : "ids starting with zero.");
29 :
30 14285 : params.addRangeCheckedParam<Real>(
31 : "x_width", 0, "x_width>=0", "The tile width in the x direction");
32 14285 : params.addRangeCheckedParam<Real>(
33 : "y_width", 0, "y_width>=0", "The tile width in the y direction");
34 14285 : params.addRangeCheckedParam<Real>(
35 : "z_width", 0, "z_width>=0", "The tile width in the z direction");
36 :
37 : // x boundary names
38 14285 : params.addParam<BoundaryName>("left_boundary", "left_boundary", "name of the left (x) boundary");
39 14285 : params.addParam<BoundaryName>(
40 : "right_boundary", "right_boundary", "name of the right (x) boundary");
41 :
42 : // y boundary names
43 14285 : params.addParam<BoundaryName>("top_boundary", "top_boundary", "name of the top (y) boundary");
44 14285 : params.addParam<BoundaryName>(
45 : "bottom_boundary", "bottom_boundary", "name of the bottom (y) boundary");
46 :
47 14285 : params.addRequiredParam<std::vector<std::vector<unsigned int>>>(
48 : "pattern", "A double-indexed array starting with the upper-left corner");
49 :
50 14285 : params.addClassDescription("Creates a 2D mesh from a specified set of unique 'tiles' meshes and "
51 : "a two-dimensional pattern.");
52 :
53 14285 : return params;
54 0 : }
55 :
56 10 : PatternedMesh::PatternedMesh(const InputParameters & parameters)
57 : : MooseMesh(parameters),
58 10 : _files(getParam<std::vector<MeshFileName>>("files")),
59 10 : _pattern(getParam<std::vector<std::vector<unsigned int>>>("pattern")),
60 10 : _x_width(getParam<Real>("x_width")),
61 10 : _y_width(getParam<Real>("y_width")),
62 30 : _z_width(getParam<Real>("z_width"))
63 : {
64 : // The PatternedMesh class only works with ReplicatedMesh
65 10 : errorIfDistributedMesh("PatternedMesh");
66 :
67 10 : _meshes.reserve(_files.size());
68 10 : }
69 :
70 0 : PatternedMesh::PatternedMesh(const PatternedMesh & other_mesh)
71 : : MooseMesh(other_mesh),
72 0 : _files(other_mesh._files),
73 0 : _pattern(other_mesh._pattern),
74 0 : _x_width(other_mesh._x_width),
75 0 : _y_width(other_mesh._y_width),
76 0 : _z_width(other_mesh._z_width)
77 : {
78 0 : }
79 :
80 : std::unique_ptr<MooseMesh>
81 0 : PatternedMesh::safeClone() const
82 : {
83 0 : return _app.getFactory().copyConstruct(*this);
84 : }
85 :
86 : void
87 10 : PatternedMesh::buildMesh()
88 : {
89 : // Read in all of the meshes
90 30 : for (MooseIndex(_files) i = 0; i < _files.size(); ++i)
91 : {
92 20 : _meshes.emplace_back(std::make_unique<ReplicatedMesh>(_communicator));
93 20 : auto & mesh = _meshes.back();
94 :
95 20 : mesh->read(_files[i]);
96 : }
97 :
98 : // Create a mesh for all n-1 rows, the first row is the original mesh
99 10 : _row_meshes.reserve(_pattern.size() - 1);
100 120 : for (MooseIndex(_pattern) i = 0; i < _pattern.size() - 1; ++i)
101 110 : _row_meshes.emplace_back(std::make_unique<ReplicatedMesh>(_communicator));
102 :
103 : // Local pointers to simplify algorithm
104 10 : std::vector<ReplicatedMesh *> row_meshes;
105 10 : row_meshes.reserve(_pattern.size());
106 : // First row is the original mesh
107 10 : row_meshes.push_back(static_cast<ReplicatedMesh *>(&getMesh()));
108 : // Copy the remaining raw pointers into the local vector
109 120 : for (const auto & row_mesh : _row_meshes)
110 110 : row_meshes.push_back(row_mesh.get());
111 :
112 10 : BoundaryID left = getBoundaryID(getParam<BoundaryName>("left_boundary"));
113 10 : BoundaryID right = getBoundaryID(getParam<BoundaryName>("right_boundary"));
114 10 : BoundaryID top = getBoundaryID(getParam<BoundaryName>("top_boundary"));
115 10 : BoundaryID bottom = getBoundaryID(getParam<BoundaryName>("bottom_boundary"));
116 :
117 : // Build each row mesh
118 130 : for (MooseIndex(_pattern) i = 0; i < _pattern.size(); ++i)
119 1800 : for (MooseIndex(_pattern) j = 0; j < _pattern[i].size(); ++j)
120 : {
121 1680 : Real deltax = j * _x_width, deltay = i * _y_width;
122 :
123 : // If this is the first cell of the row initialize the row mesh
124 1680 : if (j == 0)
125 : {
126 120 : row_meshes[i]->read(_files[_pattern[i][j]]);
127 :
128 120 : MeshTools::Modification::translate(*row_meshes[i], deltax, -deltay, 0);
129 :
130 120 : continue;
131 : }
132 :
133 1560 : ReplicatedMesh & cell_mesh = *_meshes[_pattern[i][j]];
134 :
135 : // Move the mesh into the right spot. -i because we are starting at the top
136 1560 : MeshTools::Modification::translate(cell_mesh, deltax, -deltay, 0);
137 :
138 1560 : row_meshes[i]->stitch_meshes(dynamic_cast<ReplicatedMesh &>(cell_mesh),
139 : right,
140 : left,
141 : TOLERANCE,
142 : /*clear_stitched_boundary_ids=*/true);
143 :
144 : // Undo the translation
145 1560 : MeshTools::Modification::translate(cell_mesh, -deltax, deltay, 0);
146 : }
147 :
148 : // Now stitch together the rows
149 : // We're going to stitch them all to row 0 (which is the real mesh)
150 120 : for (MooseIndex(_pattern) i = 1; i < _pattern.size(); i++)
151 110 : row_meshes[0]->stitch_meshes(
152 110 : *row_meshes[i], bottom, top, TOLERANCE, /*clear_stitched_boundary_ids=*/true);
153 10 : }
|