12 #include "libmesh/mesh_generation.h"
13 #include "libmesh/string_to_enum.h"
14 #include "libmesh/periodic_boundaries.h"
15 #include "libmesh/periodic_boundary_base.h"
16 #include "libmesh/unstructured_mesh.h"
17 #include "libmesh/partitioner.h"
18 #include "libmesh/metis_csr_graph.h"
19 #include "libmesh/edge_edge2.h"
20 #include "libmesh/edge_edge3.h"
21 #include "libmesh/edge_edge4.h"
22 #include "libmesh/mesh_communication.h"
23 #include "libmesh/remote_elem.h"
24 #include "libmesh/face_quad4.h"
25 #include "libmesh/cell_hex8.h"
38 InputParameters params = validParams<MooseMesh>();
40 MooseEnum elem_types(
"EDGE2 QUAD4 HEX8");
42 MooseEnum dims(
"1=1 2 3",
"2");
43 params.addRequiredParam<MooseEnum>(
44 "dim", dims,
"The dimension of the mesh to be generated");
46 params.addParam<dof_id_type>(
"nx", 11,
"Number of elements in the X direction");
47 params.addParam<dof_id_type>(
"ny", 11,
"Number of elements in the Y direction");
48 params.addParam<dof_id_type>(
"nz", 11,
"Number of elements in the Z direction");
49 params.addParam<Real>(
"xmin", 0.0,
"Lower X Coordinate of the generated mesh");
50 params.addParam<Real>(
"ymin", 0.0,
"Lower Y Coordinate of the generated mesh");
51 params.addParam<Real>(
"zmin", 0.0,
"Lower Z Coordinate of the generated mesh");
52 params.addParam<Real>(
"xmax", 1.0,
"Upper X Coordinate of the generated mesh");
53 params.addParam<Real>(
"ymax", 1.0,
"Upper Y Coordinate of the generated mesh");
54 params.addParam<Real>(
"zmax", 1.0,
"Upper Z Coordinate of the generated mesh");
55 params.addParam<MooseEnum>(
"elem_type",
57 "The type of element from libMesh to "
58 "generate (default: linear element for "
59 "requested dimension)");
61 params.addParamNamesToGroup(
"dim",
"Main");
63 params.addClassDescription(
64 "Create a line, square, or cube mesh with uniformly spaced memsh using PETSc DMDA.");
67 params.set<MooseEnum>(
"parallel_type") =
"DISTRIBUTED";
73 : MooseMesh(parameters),
74 _dim(getParam<MooseEnum>(
"dim")),
75 _nx(getParam<dof_id_type>(
"nx")),
76 _ny(getParam<dof_id_type>(
"ny")),
77 _nz(getParam<dof_id_type>(
"nz")),
78 _xmin(getParam<Real>(
"xmin")),
79 _xmax(getParam<Real>(
"xmax")),
80 _ymin(getParam<Real>(
"ymin")),
81 _ymax(getParam<Real>(
"ymax")),
82 _zmin(getParam<Real>(
"zmin")),
83 _zmax(getParam<Real>(
"zmax"))
86 _regular_orthogonal_mesh =
true;
91 mooseError(
"Support 2 dimensional mesh only");
93 #if LIBMESH_HAVE_PETSC
108 DMDACreate2d(_communicator.get(),
122 DMSetFromOptions(
_dmda);
128 mooseError(
"You need PETSc installed to use PETScDMDAMesh");
144 mooseError(
"Invalid component");
160 mooseError(
"Invalid component");
164 std::unique_ptr<MooseMesh>
167 return libmesh_make_unique<PETScDMDAMesh>(*
this);
172 const dof_id_type nx,
181 return i + j * (nx + 1);
186 const dof_id_type nx,
187 const dof_id_type ny,
190 const dof_id_type elem_id,
191 const processor_id_type pid,
195 BoundaryInfo & boundary_info = mesh.get_boundary_info();
197 #if LIBMESH_HAVE_PETSC
202 PetscInt Mx, My, xp, yp;
218 const PetscInt *lx, *ly;
221 #if PETSC_VERSION_LESS_THAN(3, 9, 0)
222 DMGetWorkArray(da, xp + yp + 2, PETSC_INT, &lxo);
225 DMGetWorkArray(da, xp + yp + 2, MPIU_INT, &lxo);
230 DMDAGetOwnershipRanges(da, &lx, &ly, NULL);
232 for (PetscInt i = 0; i < xp; i++)
233 lxo[i + 1] = lxo[i] + lx[i];
237 for (PetscInt i = 0; i < yp; i++)
238 lyo[i + 1] = lyo[i] + ly[i];
241 PetscInt xpid, ypid, xpidplus, ypidplus;
245 PetscFindInt(i, xp + 1, lxo, &xpid);
247 xpid = xpid < 0 ? -xpid - 1 - 1 : xpid;
249 PetscFindInt(i + 1, xp + 1, lxo, &xpidplus);
251 xpidplus = xpidplus < 0 ? -xpidplus - 1 - 1 : xpidplus;
253 PetscFindInt(j, yp + 1, lyo, &ypid);
255 ypid = ypid < 0 ? -ypid - 1 - 1 : ypid;
257 PetscFindInt(j + 1, yp + 1, lyo, &ypidplus);
259 ypidplus = ypidplus < 0 ? -ypidplus - 1 - 1 : ypidplus;
260 #if PETSC_VERSION_LESS_THAN(3, 9, 0)
261 DMRestoreWorkArray(da, xp + yp + 2, PETSC_INT, &lxo);
263 DMRestoreWorkArray(da, xp + yp + 2, MPIU_INT, &lxo);
267 auto node0_ptr = mesh.add_point(Point(static_cast<Real>(i) / nx, static_cast<Real>(j) / ny, 0),
269 node0_ptr->set_unique_id() =
node_id_Quad4(type, nx, 0, i, j, 0);
270 node0_ptr->set_id() = node0_ptr->unique_id();
272 node0_ptr->processor_id() = xpid + ypid * xp;
276 mesh.add_point(Point(static_cast<Real>(i + 1) / nx, static_cast<Real>(j) / ny, 0),
278 node1_ptr->set_unique_id() =
node_id_Quad4(type, nx, 0, i + 1, j, 0);
279 node1_ptr->set_id() = node1_ptr->unique_id();
280 node1_ptr->processor_id() = xpidplus + ypid * xp;
284 mesh.add_point(Point(static_cast<Real>(i + 1) / nx, static_cast<Real>(j + 1) / ny, 0),
286 node2_ptr->set_unique_id() =
node_id_Quad4(type, nx, 0, i + 1, j + 1, 0);
287 node2_ptr->set_id() = node2_ptr->unique_id();
288 node2_ptr->processor_id() = xpidplus + ypidplus * xp;
292 mesh.add_point(Point(static_cast<Real>(i) / nx, static_cast<Real>(j + 1) / ny, 0),
294 node3_ptr->set_unique_id() =
node_id_Quad4(type, nx, 0, i, j + 1, 0);
295 node3_ptr->set_id() = node3_ptr->unique_id();
296 node3_ptr->processor_id() = xpid + ypidplus * xp;
299 Elem * elem =
new Quad4;
300 elem->set_id(elem_id);
301 elem->processor_id() = pid;
302 elem->set_unique_id() = elem_id;
303 elem = mesh.add_elem(elem);
304 elem->set_node(0) = node0_ptr;
305 elem->set_node(1) = node1_ptr;
306 elem->set_node(2) = node2_ptr;
307 elem->set_node(3) = node3_ptr;
311 boundary_info.add_side(elem, 0, 0);
315 boundary_info.add_side(elem, 1, 1);
319 boundary_info.add_side(elem, 2, 2);
323 boundary_info.add_side(elem, 3, 3);
329 boundary_info.sideset_name(0) =
"bottom";
330 boundary_info.sideset_name(1) =
"right";
331 boundary_info.sideset_name(2) =
"top";
332 boundary_info.sideset_name(3) =
"left";
338 const dof_id_type elem_id,
343 j = (elem_id - i) / nx;
358 const dof_id_type ny,
361 std::vector<dof_id_type> & neighbors)
363 std::fill(neighbors.begin(), neighbors.end(), Elem::invalid_id);
384 const dof_id_type ny,
385 const MeshBase & mesh,
386 std::set<dof_id_type> & ghost_elems)
388 auto & boundary_info = mesh.get_boundary_info();
392 std::vector<dof_id_type> neighbors(4);
394 for (
auto elem_ptr : mesh.element_ptr_range())
396 for (
unsigned int s = 0; s < elem_ptr->n_sides(); s++)
399 if (!elem_ptr->neighbor_ptr(s))
402 if (!boundary_info.n_boundary_ids(elem_ptr, s))
404 auto elem_id = elem_ptr->id();
410 ghost_elems.insert(neighbors[s]);
422 processor_id_type pid,
427 auto node0_ptr = mesh.add_point(Point(static_cast<Real>(i) / nx, static_cast<Real>(j) / ny, 0),
429 node0_ptr->set_unique_id() =
node_id_Quad4(type, nx, 0, i, j, 0);
430 node0_ptr->processor_id() = pid;
433 #if LIBMESH_HAVE_PETSC
437 const auto pid = mesh.comm().rank();
439 BoundaryInfo & boundary_info = mesh.get_boundary_info();
448 PetscInt xs, ys, xm, ym, Mx, My, xp, yp;
451 DMDAGetCorners(da, &xs, &ys, PETSC_IGNORE, &xm, &ym, PETSC_IGNORE);
467 for (PetscInt j = ys; j < ys + ym; j++)
468 for (PetscInt i = xs; i < xs + xm; i++)
478 dof_id_type ele_id = (i - 1) + (j - 1) * (Mx - 1);
485 if ((ys == 0 && ym == 1) || (xs == 0 && xm == 1))
486 for (PetscInt j = ys; j < ys + ym; j++)
487 for (PetscInt i = xs; i < xs + xm; i++)
491 mesh.find_neighbors();
493 mesh.find_neighbors(
true);
496 for (
auto & elem_ptr : mesh.element_ptr_range())
497 for (
unsigned int s = 0; s < elem_ptr->n_sides(); s++)
498 if (!elem_ptr->neighbor_ptr(s) && !boundary_info.n_boundary_ids(elem_ptr, s))
499 elem_ptr->set_neighbor(s, const_cast<RemoteElem *>(remote_elem));
503 mesh.skip_partitioning(
true);
510 mesh.allow_renumbering(
false);
511 mesh.prepare_for_use(
false,
520 MeshBase & mesh = getMesh();
522 MooseEnum elem_type_enum = getParam<MooseEnum>(
"elem_type");
524 if (!isParamValid(
"elem_type"))
530 elem_type_enum =
"QUAD4";
534 mooseError(
"Does not support dimension ",
_dim,
"yet");
538 _elem_type = Utility::string_to_enum<ElemType>(elem_type_enum);
540 mesh.set_mesh_dimension(
_dim);
541 mesh.set_spatial_dimension(
_dim);
546 #if LIBMESH_HAVE_PETSC
552 mooseError(
"Does not support dimension ",
_dim,
"yet");