www.mooseframework.org
CartesianMeshGenerator.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 "CartesianMeshGenerator.h"
11 #include "CastUniquePointer.h"
12 
13 // libMesh includes
14 #include "libmesh/mesh_generation.h"
15 #include "libmesh/unstructured_mesh.h"
16 #include "libmesh/replicated_mesh.h"
17 #include "libmesh/point.h"
18 #include "libmesh/elem.h"
19 #include "libmesh/node.h"
20 
22 
23 template <>
26 {
28  MooseEnum dims("1=1 2 3");
29  params.addRequiredParam<MooseEnum>("dim", dims, "The dimension of the mesh to be generated");
30 
31  params.addRequiredParam<std::vector<Real>>("dx", "Intervals in the X direction");
32  params.addParam<std::vector<unsigned int>>(
33  "ix", "Number of grids in all intervals in the X direction (default to all one)");
34  params.addParam<std::vector<Real>>(
35  "dy", "Intervals in the Y direction (required when dim>1 otherwise ignored)");
36  params.addParam<std::vector<unsigned int>>(
37  "iy", "Number of grids in all intervals in the Y direction (default to all one)");
38  params.addParam<std::vector<Real>>(
39  "dz", "Intervals in the Z direction (required when dim>2 otherwise ignored)");
40  params.addParam<std::vector<unsigned int>>(
41  "iz", "Number of grids in all intervals in the Z direction (default to all one)");
42  params.addParam<std::vector<unsigned int>>("subdomain_id", "Block IDs (default to all zero)");
43  params.addParamNamesToGroup("dim", "Main");
44  params.addClassDescription("This CartesianMeshGenerator creates a non-uniform Cartesian mesh.");
45  return params;
46 }
47 
49  : MeshGenerator(parameters),
50  _dim(getParam<MooseEnum>("dim")),
51  _dx(getParam<std::vector<Real>>("dx"))
52 {
53  // get all other parameters if provided and check their sizes
54  if (isParamValid("ix"))
55  {
56  _ix = getParam<std::vector<unsigned int>>("ix");
57  if (_ix.size() != _dx.size())
58  mooseError("ix must be in the same size of dx");
59  for (unsigned int i = 0; i < _ix.size(); ++i)
60  if (_ix[i] == 0)
61  mooseError("ix cannot be zero");
62  }
63  else
64  _ix = std::vector<unsigned int>(_dx.size(), 1);
65 
66  for (unsigned int i = 0; i < _dx.size(); ++i)
67  if (_dx[i] <= 0)
68  mooseError("dx must be greater than zero");
69 
70  if (isParamValid("dy"))
71  {
72  _dy = getParam<std::vector<Real>>("dy");
73  for (unsigned int i = 0; i < _dy.size(); ++i)
74  if (_dy[i] <= 0)
75  mooseError("dy must be greater than zero");
76  }
77 
78  if (isParamValid("iy"))
79  {
80  _iy = getParam<std::vector<unsigned int>>("iy");
81  if (_iy.size() != _dy.size())
82  mooseError("iy must be in the same size of dy");
83  for (unsigned int i = 0; i < _iy.size(); ++i)
84  if (_iy[i] == 0)
85  mooseError("iy cannot be zero");
86  }
87  else
88  _iy = std::vector<unsigned int>(_dy.size(), 1);
89 
90  if (isParamValid("dz"))
91  {
92  _dz = getParam<std::vector<Real>>("dz");
93  for (unsigned int i = 0; i < _dz.size(); ++i)
94  if (_dz[i] <= 0)
95  mooseError("dz must be greater than zero");
96  }
97 
98  if (isParamValid("iz"))
99  {
100  _iz = getParam<std::vector<unsigned int>>("iz");
101  if (_iz.size() != _dz.size())
102  mooseError("iz must be in the same size of dz");
103  for (unsigned int i = 0; i < _iz.size(); ++i)
104  if (_iz[i] == 0)
105  mooseError("iz cannot be zero");
106  }
107  else
108  _iz = std::vector<unsigned int>(_dz.size(), 1);
109 
110  if (isParamValid("subdomain_id"))
111  {
112  _subdomain_id = getParam<std::vector<unsigned int>>("subdomain_id");
113  if (isParamValid("dz") && isParamValid("dy"))
114  {
115  if (_subdomain_id.size() != _dx.size() * _dy.size() * _dz.size())
116  mooseError("subdomain_id must be in the size of product of sizes of dx, dy and dz");
117  }
118  else if (isParamValid("dy"))
119  {
120  if (_subdomain_id.size() != _dx.size() * _dy.size())
121  mooseError("subdomain_id must be in the size of product of sizes of dx and dy");
122  }
123  else
124  {
125  if (_subdomain_id.size() != _dx.size())
126  mooseError("subdomain_id must be in the size of product of sizes of dx");
127  }
128  }
129  else
130  {
131  if (isParamValid("dz"))
132  _subdomain_id = std::vector<unsigned int>(_dx.size() * _dy.size() * _dz.size(), 0);
133  else if (isParamValid("dy"))
134  _subdomain_id = std::vector<unsigned int>(_dx.size() * _dy.size(), 0);
135  else
136  _subdomain_id = std::vector<unsigned int>(_dx.size(), 0);
137  }
138 
139  // do dimension checks and expand block IDs for all sub-grids
140  switch (_dim)
141  {
142  case 1:
143  {
144  _nx = 0;
145  for (unsigned int i = 0; i < _dx.size(); ++i)
146  _nx += _ix[i];
147  _ny = 1;
148  _nz = 1;
149 
150  std::vector<unsigned int> new_id;
151  for (unsigned int i = 0; i < _dx.size(); ++i)
152  for (unsigned int ii = 0; ii < _ix[i]; ++ii)
153  new_id.push_back(_subdomain_id[i]);
154 
155  _subdomain_id = new_id;
156 
157  if (isParamValid("dy"))
158  mooseWarning("dy provided for 1D");
159  if (isParamValid("iy"))
160  mooseWarning("iy provided for 1D");
161  if (isParamValid("dz"))
162  mooseWarning("dz provided for 1D");
163  if (isParamValid("iz"))
164  mooseWarning("iz provided for 1D");
165  break;
166  }
167  case 2:
168  {
169  _nx = 0;
170  for (unsigned int i = 0; i < _dx.size(); ++i)
171  _nx += _ix[i];
172  _ny = 0;
173  for (unsigned int i = 0; i < _dy.size(); ++i)
174  _ny += _iy[i];
175  _nz = 1;
176 
177  std::vector<unsigned int> new_id;
178  for (unsigned int j = 0; j < _dy.size(); ++j)
179  for (unsigned int jj = 0; jj < _iy[j]; ++jj)
180  for (unsigned int i = 0; i < _dx.size(); ++i)
181  for (unsigned int ii = 0; ii < _ix[i]; ++ii)
182  new_id.push_back(_subdomain_id[j * _dx.size() + i]);
183 
184  _subdomain_id = new_id;
185 
186  if (!isParamValid("dy"))
187  mooseError("dy is not provided for 2D");
188  if (isParamValid("dz"))
189  mooseWarning("dz provided for 2D");
190  if (isParamValid("iz"))
191  mooseWarning("iz provided for 2D");
192  break;
193  }
194  case 3:
195  {
196  _nx = 0;
197  for (unsigned int i = 0; i < _dx.size(); ++i)
198  _nx += _ix[i];
199  _ny = 0;
200  for (unsigned int i = 0; i < _dy.size(); ++i)
201  _ny += _iy[i];
202  _nz = 0;
203  for (unsigned int i = 0; i < _dz.size(); ++i)
204  _nz += _iz[i];
205 
206  std::vector<unsigned int> new_id;
207  for (unsigned int k = 0; k < _dz.size(); ++k)
208  for (unsigned int kk = 0; kk < _iz[k]; ++kk)
209  for (unsigned int j = 0; j < _dy.size(); ++j)
210  for (unsigned int jj = 0; jj < _iy[j]; ++jj)
211  for (unsigned int i = 0; i < _dx.size(); ++i)
212  for (unsigned int ii = 0; ii < _ix[i]; ++ii)
213  new_id.push_back(_subdomain_id[k * _dx.size() * _dy.size() + j * _dx.size() + i]);
214 
215  _subdomain_id = new_id;
216 
217  if (!isParamValid("dy"))
218  mooseError("dy is not provided for 3D");
219  if (!isParamValid("dz"))
220  mooseError("dz is not provided for 3D");
221  break;
222  }
223  }
224 }
225 
226 std::unique_ptr<MeshBase>
228 {
229  std::unique_ptr<ReplicatedMesh> mesh = libmesh_make_unique<ReplicatedMesh>(comm(), 2);
230 
231  // switching on MooseEnum to generate the reference mesh
232  // Note: element type is fixed
233  switch (_dim)
234  {
235  case 1:
236  MeshTools::Generation::build_line(static_cast<UnstructuredMesh &>(*mesh), _nx, 0, _nx, EDGE2);
237  break;
238  case 2:
239  MeshTools::Generation::build_square(
240  static_cast<UnstructuredMesh &>(*mesh), _nx, _ny, 0, _nx, 0, _ny, QUAD4);
241  break;
242  case 3:
244  static_cast<UnstructuredMesh &>(*mesh), _nx, _ny, _nz, 0, _nx, 0, _ny, 0, _nz, HEX8);
245  break;
246  }
247 
248  // assign block IDs
249  MeshBase::element_iterator el = mesh->active_elements_begin();
250  MeshBase::element_iterator el_end = mesh->active_elements_end();
251  for (; el != el_end; ++el)
252  {
253  const Point p = (*el)->centroid();
254  unsigned int ix = std::floor(p(0));
255  unsigned int iy = std::floor(p(1));
256  unsigned int iz = std::floor(p(2));
257  unsigned int i = iz * _nx * _ny + iy * _nx + ix;
258  (*el)->subdomain_id() = _subdomain_id[i];
259  }
260 
261  // adjust node coordinates
262  switch (_dim)
263  {
264  case 1:
265  {
266  Real base;
267 
268  std::vector<Real> mapx;
269  // Note: the starting coordinate is zero
270  base = 0;
271  mapx.push_back(base);
272  for (unsigned int i = 0; i < _dx.size(); ++i)
273  {
274  for (unsigned int j = 1; j <= _ix[i]; ++j)
275  mapx.push_back(base + _dx[i] / _ix[i] * j);
276  base += _dx[i];
277  }
278 
279  MeshBase::node_iterator node = mesh->active_nodes_begin();
280  MeshBase::node_iterator node_end = mesh->active_nodes_end();
281  for (; node != node_end; ++node)
282  {
283  unsigned int i = (*(*node))(0) + 0.5;
284  (*(*node))(0) = mapx.at(i);
285  }
286  break;
287  }
288  case 2:
289  {
290  Real base;
291 
292  std::vector<Real> mapx;
293  base = 0;
294  mapx.push_back(base);
295  for (unsigned int i = 0; i < _dx.size(); ++i)
296  {
297  for (unsigned int j = 1; j <= _ix[i]; ++j)
298  mapx.push_back(base + _dx[i] / _ix[i] * j);
299  base += _dx[i];
300  }
301 
302  std::vector<Real> mapy;
303  base = 0;
304  mapy.push_back(base);
305  for (unsigned int i = 0; i < _dy.size(); ++i)
306  {
307  for (unsigned int j = 1; j <= _iy[i]; ++j)
308  mapy.push_back(base + _dy[i] / _iy[i] * j);
309  base += _dy[i];
310  }
311 
312  MeshBase::node_iterator node = mesh->active_nodes_begin();
313  MeshBase::node_iterator node_end = mesh->active_nodes_end();
314  for (; node != node_end; ++node)
315  {
316  unsigned int i = (*(*node))(0) + 0.5;
317  (*(*node))(0) = mapx.at(i);
318  unsigned int j = (*(*node))(1) + 0.5;
319  (*(*node))(1) = mapy.at(j);
320  }
321  break;
322  }
323  case 3:
324  {
325  Real base;
326 
327  std::vector<Real> mapx;
328  base = 0;
329  mapx.push_back(base);
330  for (unsigned int i = 0; i < _dx.size(); ++i)
331  {
332  for (unsigned int j = 1; j <= _ix[i]; ++j)
333  mapx.push_back(base + _dx[i] / _ix[i] * j);
334  base += _dx[i];
335  }
336 
337  std::vector<Real> mapy;
338  base = 0;
339  mapy.push_back(base);
340  for (unsigned int i = 0; i < _dy.size(); ++i)
341  {
342  for (unsigned int j = 1; j <= _iy[i]; ++j)
343  mapy.push_back(base + _dy[i] / _iy[i] * j);
344  base += _dy[i];
345  }
346 
347  std::vector<Real> mapz;
348  base = 0;
349  mapz.push_back(base);
350  for (unsigned int i = 0; i < _dz.size(); ++i)
351  {
352  for (unsigned int j = 1; j <= _iz[i]; ++j)
353  mapz.push_back(base + _dz[i] / _iz[i] * j);
354  base += _dz[i];
355  }
356 
357  MeshBase::node_iterator node = mesh->active_nodes_begin();
358  MeshBase::node_iterator node_end = mesh->active_nodes_end();
359  for (; node != node_end; ++node)
360  {
361  unsigned int i = (*(*node))(0) + 0.5;
362  (*(*node))(0) = mapx.at(i);
363  unsigned int j = (*(*node))(1) + 0.5;
364  (*(*node))(1) = mapy.at(j);
365  unsigned int k = (*(*node))(2) + 0.5;
366  (*(*node))(2) = mapz.at(k);
367  }
368  break;
369  }
370  }
371 
372  return dynamic_pointer_cast<MeshBase>(mesh);
373 }
MooseEnum _dim
The dimension of the mesh.
void build_cube(UnstructuredMesh &mesh, const unsigned int nx, unsigned int ny, unsigned int nz, const Real xmin, const Real xmax, const Real ymin, const Real ymax, const Real zmin, const Real zmax, const ElemType type, bool verbose)
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
void mooseWarning(Args &&... args) const
Definition: MooseObject.h:155
CartesianMeshGenerator(const InputParameters &parameters)
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
int _nx
Number of elements in x, y, z direction.
std::vector< Real > _dy
Intervals in y direction.
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...
std::vector< unsigned int > _ix
Number of grids in all intervals in x direction.
std::vector< unsigned int > _subdomain_id
Block IDs.
InputParameters validParams< CartesianMeshGenerator >()
registerMooseObject("MooseApp", CartesianMeshGenerator)
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
std::vector< unsigned int > _iy
Number of grids in all intervals in y direction.
std::vector< Real > _dx
Intervals in x direction.
std::vector< unsigned int > _iz
Number of grids in all intervals in z direction.
std::vector< Real > _dz
Intervals in z direction.
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...
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
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:30
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...