https://mooseframework.inl.gov
CartesianMeshGenerator.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 
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 
25 {
27  MooseEnum dims("1=1 2 3");
28  params.addRequiredParam<MooseEnum>("dim", dims, "The dimension of the mesh to be generated");
29 
30  params.addRequiredParam<std::vector<Real>>("dx", "Intervals in the X direction");
31  params.addParam<std::vector<unsigned int>>(
32  "ix", "Number of grids in all intervals in the X direction (default to all one)");
33  params.addParam<std::vector<Real>>(
34  "max_sizes_in_x",
35  "Maximum element size in the X direction. This can be specified once for all 'dx' intervals "
36  "or specified for each interval. 'ix' is then determined using the ceiling of dx/size");
37  params.addParam<std::vector<Real>>(
38  "dy", "Intervals in the Y direction (required when dim>1 otherwise ignored)");
39  params.addParam<std::vector<unsigned int>>(
40  "iy", "Number of grids in all intervals in the Y direction (default to all one)");
41  params.addParam<std::vector<Real>>(
42  "max_sizes_in_y",
43  "Maximum element size in the Y direction. This can be specified once for all 'dy' intervals "
44  "or specified for each interval. 'iy' is then determined using the ceiling of dy/size");
45  params.addParam<std::vector<Real>>(
46  "dz", "Intervals in the Z direction (required when dim>2 otherwise ignored)");
47  params.addParam<std::vector<unsigned int>>(
48  "iz", "Number of grids in all intervals in the Z direction (default to all one)");
49  params.addParam<std::vector<Real>>(
50  "max_sizes_in_z",
51  "Maximum element size in the Z direction. This can be specified once for all 'dz' intervals "
52  "or specified for each interval. 'iz' is then determined using the ceiling of dz/size");
53  params.addParam<std::vector<unsigned int>>("subdomain_id", "Block IDs (default to all zero)");
54  params.addClassDescription("This CartesianMeshGenerator creates a non-uniform Cartesian mesh.");
55  return params;
56 }
57 
59  : MeshGenerator(parameters),
60  _dim(getParam<MooseEnum>("dim")),
61  _dx(getParam<std::vector<Real>>("dx"))
62 {
63  // get all other parameters if provided and check their sizes
64  if (isParamValid("ix"))
65  {
66  _ix = getParam<std::vector<unsigned int>>("ix");
67  if (_ix.size() != _dx.size())
68  mooseError("ix must be the same size as dx");
69  for (unsigned int i = 0; i < _ix.size(); ++i)
70  if (_ix[i] == 0)
71  mooseError("ix cannot be zero");
72  if (isParamValid("max_sizes_in_x"))
73  paramError("max_sizes_in_x", "Cannot be provided if 'ix' is specified");
74  }
75  else if (isParamValid("max_sizes_in_x"))
76  {
77  _ix.resize(_dx.size());
78  auto max_sizes = getParam<std::vector<Real>>("max_sizes_in_x");
79  if (max_sizes.size() == 1)
80  max_sizes.resize(_dx.size(), max_sizes[0]);
81  if (max_sizes.size() != _dx.size())
82  paramError("max_sizes_in_x", "max_sizes_in_x must be size 1 or the same size as dx");
83  for (const auto i : index_range(_dx))
84  if (max_sizes[i] <= 0)
85  paramError("max_sizes_in_x", "max_sizes_in_x must be strictly positive.");
86  for (const auto i : index_range(_dx))
87  _ix[i] = std::ceil(_dx[i] / max_sizes[i]);
88  }
89  else
90  _ix = std::vector<unsigned int>(_dx.size(), 1);
91 
92  for (unsigned int i = 0; i < _dx.size(); ++i)
93  if (_dx[i] <= 0)
94  mooseError("dx must be greater than zero. dx: ", Moose::stringify(_dx));
95 
96  if (isParamValid("dy"))
97  {
98  _dy = getParam<std::vector<Real>>("dy");
99  for (unsigned int i = 0; i < _dy.size(); ++i)
100  if (_dy[i] <= 0)
101  mooseError("dy must be greater than zero. dy: ", Moose::stringify(_dy));
102  }
103 
104  if (isParamValid("iy"))
105  {
106  _iy = getParam<std::vector<unsigned int>>("iy");
107  if (_iy.size() != _dy.size())
108  mooseError("iy must be the same size as dy");
109  for (unsigned int i = 0; i < _iy.size(); ++i)
110  if (_iy[i] == 0)
111  mooseError("iy cannot be zero");
112  if (isParamValid("max_sizes_in_y"))
113  paramError("max_sizes_in_y", "Cannot be provided if 'iy' is specified");
114  }
115  else if (isParamValid("max_sizes_in_y"))
116  {
117  _iy.resize(_dy.size());
118  auto max_sizes = getParam<std::vector<Real>>("max_sizes_in_y");
119  if (max_sizes.size() == 1)
120  max_sizes.resize(_dy.size(), max_sizes[0]);
121  if (max_sizes.size() != _dy.size())
122  paramError("max_sizes_in_y", "max_sizes_in_y must be size 1 or the same size as dy");
123  for (const auto i : index_range(_dy))
124  if (max_sizes[i] <= 0)
125  paramError("max_sizes_in_y", "max_sizes_in_y must be strictly positive.");
126  for (const auto i : index_range(_dy))
127  _iy[i] = std::ceil(_dy[i] / max_sizes[i]);
128  }
129  else
130  _iy = std::vector<unsigned int>(_dy.size(), 1);
131 
132  if (isParamValid("dz"))
133  {
134  _dz = getParam<std::vector<Real>>("dz");
135  for (unsigned int i = 0; i < _dz.size(); ++i)
136  if (_dz[i] <= 0)
137  mooseError("dz must be greater than zero dz: ", Moose::stringify(_dz));
138  }
139 
140  if (isParamValid("iz"))
141  {
142  _iz = getParam<std::vector<unsigned int>>("iz");
143  if (_iz.size() != _dz.size())
144  mooseError("iz must be the same size as dz");
145  for (unsigned int i = 0; i < _iz.size(); ++i)
146  if (_iz[i] == 0)
147  mooseError("iz cannot be zero");
148  if (isParamValid("max_sizes_in_z"))
149  paramError("max_sizes_in_z", "Cannot be provided if 'iz' is specified");
150  }
151  else if (isParamValid("max_sizes_in_z"))
152  {
153  _iz.resize(_dz.size());
154  auto max_sizes = getParam<std::vector<Real>>("max_sizes_in_z");
155  if (max_sizes.size() == 1)
156  max_sizes.resize(_dz.size(), max_sizes[0]);
157  if (max_sizes.size() != _dz.size())
158  paramError("max_sizes_in_z", "max_sizes_in_z must be size 1 or the same size as dz");
159  for (const auto i : index_range(_dz))
160  if (max_sizes[i] <= 0)
161  paramError("max_sizes_in_z", "max_sizes_in_z must be strictly positive.");
162  for (const auto i : index_range(_dz))
163  _iz[i] = std::ceil(_dz[i] / max_sizes[i]);
164  }
165  else
166  _iz = std::vector<unsigned int>(_dz.size(), 1);
167 
168  if (isParamValid("subdomain_id"))
169  {
170  _subdomain_id = getParam<std::vector<unsigned int>>("subdomain_id");
171  if (isParamValid("dz") && isParamValid("dy"))
172  {
173  if (_subdomain_id.size() != _dx.size() * _dy.size() * _dz.size())
174  mooseError(
175  "subdomain_id must be the size of the product of sizes of dx, dy and dz. Sizes are '" +
176  std::to_string(_subdomain_id.size()) + "' and '" +
177  std::to_string(_dx.size() * _dy.size() * _dz.size()) + "' respectively");
178  }
179  else if (isParamValid("dy"))
180  {
181  if (_subdomain_id.size() != _dx.size() * _dy.size())
182  mooseError(
183  "subdomain_id must be the size of the product of sizes of dx and dy. Sizes are '" +
184  std::to_string(_subdomain_id.size()) + "' and '" +
185  std::to_string(_dx.size() * _dy.size()) + "' respectively");
186  }
187  else
188  {
189  if (_subdomain_id.size() != _dx.size())
190  mooseError("subdomain_id must be the size of the product of sizes of dx. Sizes are '" +
191  std::to_string(_subdomain_id.size()) + "' and '" + std::to_string(_dx.size()) +
192  "' respectively");
193  }
194  }
195  else
196  {
197  if (isParamValid("dz"))
198  _subdomain_id = std::vector<unsigned int>(_dx.size() * _dy.size() * _dz.size(), 0);
199  else if (isParamValid("dy"))
200  _subdomain_id = std::vector<unsigned int>(_dx.size() * _dy.size(), 0);
201  else
202  _subdomain_id = std::vector<unsigned int>(_dx.size(), 0);
203  }
204 
205  // do dimension checks and expand block IDs for all sub-grids
206  switch (_dim)
207  {
208  case 1:
209  {
210  _nx = 0;
211  for (unsigned int i = 0; i < _dx.size(); ++i)
212  _nx += _ix[i];
213  _ny = 1;
214  _nz = 1;
215 
216  std::vector<unsigned int> new_id;
217  for (unsigned int i = 0; i < _dx.size(); ++i)
218  for (unsigned int ii = 0; ii < _ix[i]; ++ii)
219  new_id.push_back(_subdomain_id[i]);
220 
221  _subdomain_id = new_id;
222 
223  if (isParamValid("dy"))
224  mooseWarning("dy provided for 1D");
225  if (isParamValid("iy"))
226  mooseWarning("iy provided for 1D");
227  if (isParamValid("dz"))
228  mooseWarning("dz provided for 1D");
229  if (isParamValid("iz"))
230  mooseWarning("iz provided for 1D");
231  if (isParamValid("max_sizes_in_y"))
232  paramWarning("max_sizes_in_y", "Should not be provided for 1D");
233  if (isParamValid("max_sizes_in_z"))
234  paramWarning("max_sizes_in_z", "Should not be provided for 1D");
235  break;
236  }
237  case 2:
238  {
239  _nx = 0;
240  for (unsigned int i = 0; i < _dx.size(); ++i)
241  _nx += _ix[i];
242  _ny = 0;
243  for (unsigned int i = 0; i < _dy.size(); ++i)
244  _ny += _iy[i];
245  _nz = 1;
246 
247  std::vector<unsigned int> new_id;
248  for (unsigned int j = 0; j < _dy.size(); ++j)
249  for (unsigned int jj = 0; jj < _iy[j]; ++jj)
250  for (unsigned int i = 0; i < _dx.size(); ++i)
251  for (unsigned int ii = 0; ii < _ix[i]; ++ii)
252  new_id.push_back(_subdomain_id[j * _dx.size() + i]);
253 
254  _subdomain_id = new_id;
255 
256  if (!isParamValid("dy"))
257  mooseError("dy is not provided for 2D");
258  if (isParamValid("dz"))
259  mooseWarning("dz provided for 2D");
260  if (isParamValid("iz"))
261  mooseWarning("iz provided for 2D");
262  if (isParamValid("max_sizes_in_z"))
263  paramWarning("max_sizes_in_z", "Should not be provided for 2D");
264  break;
265  }
266  case 3:
267  {
268  _nx = 0;
269  for (unsigned int i = 0; i < _dx.size(); ++i)
270  _nx += _ix[i];
271  _ny = 0;
272  for (unsigned int i = 0; i < _dy.size(); ++i)
273  _ny += _iy[i];
274  _nz = 0;
275  for (unsigned int i = 0; i < _dz.size(); ++i)
276  _nz += _iz[i];
277 
278  std::vector<unsigned int> new_id;
279  for (unsigned int k = 0; k < _dz.size(); ++k)
280  for (unsigned int kk = 0; kk < _iz[k]; ++kk)
281  for (unsigned int j = 0; j < _dy.size(); ++j)
282  for (unsigned int jj = 0; jj < _iy[j]; ++jj)
283  for (unsigned int i = 0; i < _dx.size(); ++i)
284  for (unsigned int ii = 0; ii < _ix[i]; ++ii)
285  new_id.push_back(_subdomain_id[k * _dx.size() * _dy.size() + j * _dx.size() + i]);
286 
287  _subdomain_id = new_id;
288 
289  if (!isParamValid("dy"))
290  mooseError("dy is not provided for 3D");
291  if (!isParamValid("dz"))
292  mooseError("dz is not provided for 3D");
293  break;
294  }
295  }
296 }
297 
298 std::unique_ptr<MeshBase>
300 {
301  auto mesh = buildMeshBaseObject();
302 
303  // switching on MooseEnum to generate the reference mesh
304  // Note: element type is fixed
305  switch (_dim)
306  {
307  case 1:
308  MeshTools::Generation::build_line(static_cast<UnstructuredMesh &>(*mesh), _nx, 0, _nx, EDGE2);
309  break;
310  case 2:
311  MeshTools::Generation::build_square(
312  static_cast<UnstructuredMesh &>(*mesh), _nx, _ny, 0, _nx, 0, _ny, QUAD4);
313  break;
314  case 3:
315  MeshTools::Generation::build_cube(
316  static_cast<UnstructuredMesh &>(*mesh), _nx, _ny, _nz, 0, _nx, 0, _ny, 0, _nz, HEX8);
317  break;
318  }
319 
320  // assign block IDs
321  MeshBase::element_iterator el = mesh->active_elements_begin();
322  MeshBase::element_iterator el_end = mesh->active_elements_end();
323  for (; el != el_end; ++el)
324  {
325  const Point p = (*el)->vertex_average();
326  unsigned int ix = std::floor(p(0));
327  unsigned int iy = std::floor(p(1));
328  unsigned int iz = std::floor(p(2));
329  unsigned int i = iz * _nx * _ny + iy * _nx + ix;
330  (*el)->subdomain_id() = _subdomain_id[i];
331  }
332 
333  // adjust node coordinates
334  switch (_dim)
335  {
336  case 1:
337  {
338  Real base;
339 
340  std::vector<Real> mapx;
341  // Note: the starting coordinate is zero
342  base = 0;
343  mapx.push_back(base);
344  for (unsigned int i = 0; i < _dx.size(); ++i)
345  {
346  for (unsigned int j = 1; j <= _ix[i]; ++j)
347  mapx.push_back(base + _dx[i] / _ix[i] * j);
348  base += _dx[i];
349  }
350 
351  MeshBase::node_iterator node = mesh->active_nodes_begin();
352  MeshBase::node_iterator node_end = mesh->active_nodes_end();
353  for (; node != node_end; ++node)
354  {
355  unsigned int i = (*(*node))(0) + 0.5;
356  (*(*node))(0) = mapx.at(i);
357  }
358  break;
359  }
360  case 2:
361  {
362  Real base;
363 
364  std::vector<Real> mapx;
365  base = 0;
366  mapx.push_back(base);
367  for (unsigned int i = 0; i < _dx.size(); ++i)
368  {
369  for (unsigned int j = 1; j <= _ix[i]; ++j)
370  mapx.push_back(base + _dx[i] / _ix[i] * j);
371  base += _dx[i];
372  }
373 
374  std::vector<Real> mapy;
375  base = 0;
376  mapy.push_back(base);
377  for (unsigned int i = 0; i < _dy.size(); ++i)
378  {
379  for (unsigned int j = 1; j <= _iy[i]; ++j)
380  mapy.push_back(base + _dy[i] / _iy[i] * j);
381  base += _dy[i];
382  }
383 
384  MeshBase::node_iterator node = mesh->active_nodes_begin();
385  MeshBase::node_iterator node_end = mesh->active_nodes_end();
386  for (; node != node_end; ++node)
387  {
388  unsigned int i = (*(*node))(0) + 0.5;
389  (*(*node))(0) = mapx.at(i);
390  unsigned int j = (*(*node))(1) + 0.5;
391  (*(*node))(1) = mapy.at(j);
392  }
393  break;
394  }
395  case 3:
396  {
397  Real base;
398 
399  std::vector<Real> mapx;
400  base = 0;
401  mapx.push_back(base);
402  for (unsigned int i = 0; i < _dx.size(); ++i)
403  {
404  for (unsigned int j = 1; j <= _ix[i]; ++j)
405  mapx.push_back(base + _dx[i] / _ix[i] * j);
406  base += _dx[i];
407  }
408 
409  std::vector<Real> mapy;
410  base = 0;
411  mapy.push_back(base);
412  for (unsigned int i = 0; i < _dy.size(); ++i)
413  {
414  for (unsigned int j = 1; j <= _iy[i]; ++j)
415  mapy.push_back(base + _dy[i] / _iy[i] * j);
416  base += _dy[i];
417  }
418 
419  std::vector<Real> mapz;
420  base = 0;
421  mapz.push_back(base);
422  for (unsigned int i = 0; i < _dz.size(); ++i)
423  {
424  for (unsigned int j = 1; j <= _iz[i]; ++j)
425  mapz.push_back(base + _dz[i] / _iz[i] * j);
426  base += _dz[i];
427  }
428 
429  MeshBase::node_iterator node = mesh->active_nodes_begin();
430  MeshBase::node_iterator node_end = mesh->active_nodes_end();
431  for (; node != node_end; ++node)
432  {
433  unsigned int i = (*(*node))(0) + 0.5;
434  (*(*node))(0) = mapx.at(i);
435  unsigned int j = (*(*node))(1) + 0.5;
436  (*(*node))(1) = mapy.at(j);
437  unsigned int k = (*(*node))(2) + 0.5;
438  (*(*node))(2) = mapz.at(k);
439  }
440  break;
441  }
442  }
443 
444  mesh->prepare_for_use();
445  return dynamic_pointer_cast<MeshBase>(mesh);
446 }
MooseEnum _dim
The dimension of the mesh.
HEX8
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
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:467
CartesianMeshGenerator(const InputParameters &parameters)
MeshBase & 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.
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...
QUAD4
void mooseWarning(Args &&... args) const
std::vector< unsigned int > _ix
Number of grids in all intervals in x direction.
std::vector< unsigned int > _subdomain_id
Block IDs.
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:54
std::vector< unsigned int > _iy
Number of grids in all intervals in y direction.
static InputParameters validParams()
Definition: MeshGenerator.C:23
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
std::vector< Real > _dx
Intervals in x direction.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
EDGE2
std::vector< unsigned int > _iz
Number of grids in all intervals in z direction.
std::vector< Real > _dz
Intervals in z direction.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:281
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...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
void paramWarning(const std::string &param, Args... args) const
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
Build a MeshBase object whose underlying type will be determined by the Mesh input file block...
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:33
auto index_range(const T &sizable)
static InputParameters validParams()