https://mooseframework.inl.gov
GridPartitioner.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 "GridPartitioner.h"
11 
12 #include "GeneratedMesh.h"
13 #include "MooseApp.h"
14 
15 #include "libmesh/mesh_tools.h"
16 #include "libmesh/elem.h"
17 
19 
20 #include <memory>
21 
24 {
26 
27  MooseEnum method("manual automatic", "manual");
28  params.addParam<MooseEnum>(
29  "grid_computation",
30  method,
31  "Whether to determine the grid manually (using nx, ny and nz) or automatically. When using "
32  "the automatic mode, the user can impose a certain value for nx, ny or nz, and the automatic "
33  "factorization will adjust the number of processors in the other directions.");
34 
35  // Users specify how many processors they need along each direction
36  params.addParam<unsigned int>(
37  "nx", "Number of processors in the X direction. Defaults to 1 in manual mode");
38  params.addParam<unsigned int>(
39  "ny", "Number of processors in the Y direction. Defaults to 1 in manual mode");
40  params.addParam<unsigned int>(
41  "nz", "Number of processors in the Z direction. Defaults to 1 in manual mode");
42 
43  params.addClassDescription("Create a uniform grid that overlays the mesh to be partitioned. "
44  "Assign all elements within each cell of the grid to the same "
45  "processor.");
46 
47  return params;
48 }
49 
51  : MoosePartitioner(params), _mesh(*getCheckedPointerParam<MooseMesh *>("mesh"))
52 {
53 }
54 
56 
57 std::unique_ptr<Partitioner>
59 {
60  return _app.getFactory().clone(*this);
61 }
62 
63 void
64 GridPartitioner::_do_partition(MeshBase & mesh, const unsigned int /*n*/)
65 {
66  // By default, there are one processor along each direction
67  // nx: the number of processors along x direction
68  // ny: the number of processors along y direction
69  // nz: the number of processors along z direction
70  unsigned int nx = 1, ny = 1, nz = 1;
71 
72  // Figure out the physical bounds of the given mesh
73  auto bounding_box = MeshTools::create_bounding_box(mesh);
74  const auto & min = bounding_box.min();
75  const auto & max = bounding_box.max();
76 
77  auto dim = mesh.mesh_dimension();
78 
79  // Gather user parameters
80  nx = isParamValid("nx") ? getParam<unsigned int>("nx") : nx;
81  if (dim >= 2)
82  ny = isParamValid("ny") ? getParam<unsigned int>("ny") : ny;
83  if (dim == 3)
84  nz = isParamValid("nz") ? getParam<unsigned int>("nz") : nz;
85 
86  // simple info message unused parameters as this can be normal: we could be partitioning
87  // a 2D mesh before extruding it to 3D. The nz parameter is needed for the 3D mesh
88  if (dim < 2 && isParamValid("ny") && getParam<unsigned int>("ny") > 1)
89  paramInfo("ny", "Parameter ignored as mesh is currently of dimension less than 2.");
90  if (dim < 3 && isParamValid("nz") && getParam<unsigned int>("nz") > 1)
91  paramInfo("nz", "Parameter ignored as mesh is currently of dimension less than 3.");
92 
93  // User parameters, which should match the number of partitions needed
94  if (getParam<MooseEnum>("grid_computation") == "manual")
95  {
96  // Need to make sure the number of grid cells matches the number of procs to partition for
97  if ((nx * ny * nz) != mesh.n_partitions())
98  mooseError("Number of grid cells (" + std::to_string(nx * ny * nz) +
99  ") does not match the number of MPI processes (" +
100  std::to_string(mesh.n_partitions()) + ")");
101  }
102 
103  else if (getParam<MooseEnum>("grid_computation") == "automatic")
104  {
105  // remove over-constraint and tell user
106  if (nx * ny * nz > mesh.n_partitions())
107  {
108  nx = 0;
109  ny = 0;
110  nz = 0;
111  paramWarning("grid_computation",
112  "User specified (nx,ny,nz) grid exceeded number of partitions, these parameters "
113  "will be ignored.");
114  }
115  // 0 means no restriction on which number to choose
116  int dims[] = {isParamValid("nx") ? int(nx) : 0,
117  isParamValid("ny") ? int(ny) : 0,
118  isParamValid("nz") ? int(nz) : 0};
119 
120  if ((dims[0] > 0 && dim == 1 && dims[0] != int(mesh.n_partitions())) ||
121  (dims[0] > 0 && dims[1] > 0 && dim == 2 && dims[0] * dims[1] != int(mesh.n_partitions())) ||
122  (dims[0] > 0 && dims[1] > 0 && dims[2] > 0 && dim == 3 &&
123  dims[0] * dims[1] * dims[2] != int(mesh.n_partitions())))
124  {
125  dims[0] = 0;
126  dims[1] = 0;
127  dims[2] = 0;
128  paramWarning("grid_computation",
129  "User specified grid for the current dimension of the mesh (" +
130  std::to_string(dim) + ") does not fit the number of partitions (" +
131  std::to_string(mesh.n_partitions()) +
132  ") and constrain the grid partitioner in every direction, these parameters "
133  "will be ignored.");
134  }
135 
136  // This will error if the factorization is not possible
137  MPI_Dims_create(mesh.n_partitions(), dim, dims);
138 
139  nx = dims[0];
140  if (dim >= 2)
141  ny = dims[1];
142  if (dim == 3)
143  nz = dims[2];
144  }
145 
146  // hx: grid interval along x direction
147  // hy: grid interval along y direction
148  // hz: grid interval along z direction
149  // Lx: domain length along x direction
150  // Ly: domain length along y direction
151  // Lz: domain length along z direction
152  Real hx = 1., hy = 1., hz = 1., Lx = 1., Ly = 1., Lz = 1.;
153  Lx = max(0) - min(0);
154  hx = Lx / nx;
155  if (dim >= 2)
156  {
157  Ly = max(1) - min(1);
158  hy = Ly / ny;
159  }
160 
161  if (dim == 3)
162  {
163  Lz = max(2) - min(2);
164  hz = Lz / nz;
165  }
166 
167  // Processor coordinates along x, y, z directions
168  unsigned int k = 0, j = 0, i = 0;
169  // Coordinates for current element centroid
170  Real coordx = 0, coordy = 0, coordz = 0;
171 
172  // Loop over all of the elements in the given mesh
173  for (auto & elem_ptr : mesh.active_element_ptr_range())
174  {
175  // Find the element it lands in in the GeneratedMesh
176  auto centroid = elem_ptr->vertex_average();
177 
178  coordx = centroid(0);
179  mooseAssert(coordx >= min(0) && coordy <= max(0),
180  "element is outside of bounding box along x direction");
181  if (dim >= 2)
182  {
183  coordy = centroid(1);
184  mooseAssert(coordy >= min(1) && coordy <= max(1),
185  "element is outside of bounding box along y direction");
186  }
187  if (dim == 3)
188  {
189  coordz = centroid(2);
190  mooseAssert(coordz >= min(2) && coordz <= max(2),
191  "element is outside of bounding box along z direction");
192  }
193 
194  // Compute processor coordinates
195  j = k = 0;
196  i = (coordx - min(0)) / hx;
197  if (dim >= 2)
198  j = (coordy - min(1)) / hy;
199  if (dim == 3)
200  k = (coordz - min(2)) / hz;
201 
202  mooseAssert(i < nx, "Index calculation is wrong along x direction");
203  mooseAssert(j < ny || ny == 0, "Index calculation is wrong along y direction");
204  mooseAssert(k < nz || nz == 0, "Index calculation is wrong along z direction");
205  // Assign processor ID to current element
206  elem_ptr->processor_id() = k * nx * ny + j * nx + i;
207  }
208 }
static InputParameters validParams()
static InputParameters validParams()
virtual ~GridPartitioner()
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:154
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
Definition: MooseApp.h:424
auto max(const L &left, const R &right)
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:88
registerMooseObject("MooseApp", GridPartitioner)
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:84
Partitions a mesh using a regular grid.
virtual std::unique_ptr< Partitioner > clone() const override
GridPartitioner(const InputParameters &params)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Base class for MOOSE partitioner.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
virtual void _do_partition(MeshBase &mesh, const unsigned int n) override
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 paramWarning(const std::string &param, Args... args) const
Emits a warning prefixed with the file and line number of the given param (from the input file) along...
std::unique_ptr< T > clone(const T &object)
Clones the object object.
Definition: Factory.h:275
auto min(const L &left, const R &right)
void paramInfo(const std::string &param, Args... args) const
Emits an informational message prefixed with the file and line number of the given param (from the in...
void ErrorVector unsigned int