www.mooseframework.org
Functions
PETScDMDAMesh.C File Reference

Go to the source code of this file.

Functions

 registerMooseObject ("ExternalPetscSolverApp", PETScDMDAMesh)
 
template<>
InputParameters validParams< PETScDMDAMesh > ()
 
dof_id_type node_id_Quad4 (const ElemType, const dof_id_type nx, const dof_id_type, const dof_id_type i, const dof_id_type j, const dof_id_type)
 
void add_element_Quad4 (DM da, const dof_id_type nx, const dof_id_type ny, const dof_id_type i, const dof_id_type j, const dof_id_type elem_id, const processor_id_type pid, const ElemType type, MeshBase &mesh)
 
void set_boundary_names_Quad4 (BoundaryInfo &boundary_info)
 
void get_indices_Quad4 (const dof_id_type nx, const dof_id_type, const dof_id_type elem_id, dof_id_type &i, dof_id_type &j)
 
dof_id_type elem_id_Quad4 (const dof_id_type nx, const dof_id_type, const dof_id_type i, const dof_id_type j, const dof_id_type)
 
void get_neighbors_Quad4 (const dof_id_type nx, const dof_id_type ny, const dof_id_type i, const dof_id_type j, std::vector< dof_id_type > &neighbors)
 
void get_ghost_neighbors_Quad4 (const dof_id_type nx, const dof_id_type ny, const MeshBase &mesh, std::set< dof_id_type > &ghost_elems)
 
void add_node_Qua4 (dof_id_type nx, dof_id_type ny, dof_id_type i, dof_id_type j, processor_id_type pid, ElemType type, MeshBase &mesh)
 
void build_cube_Quad4 (UnstructuredMesh &mesh, DM da, const ElemType type)
 

Function Documentation

◆ add_element_Quad4()

void add_element_Quad4 ( DM  da,
const dof_id_type  nx,
const dof_id_type  ny,
const dof_id_type  i,
const dof_id_type  j,
const dof_id_type  elem_id,
const processor_id_type  pid,
const ElemType  type,
MeshBase &  mesh 
)

Definition at line 185 of file PETScDMDAMesh.C.

Referenced by build_cube_Quad4().

194 {
195  BoundaryInfo & boundary_info = mesh.get_boundary_info();
196 
197 #if LIBMESH_HAVE_PETSC
198  // Mx: number of grid points in x direction for all processors
199  // My: number of grid points in y direction for all processors
200  // xp: number of processors in x direction
201  // yp: number of processors in y direction
202  PetscInt Mx, My, xp, yp;
203  DMDAGetInfo(da,
204  PETSC_IGNORE,
205  &Mx,
206  &My,
207  PETSC_IGNORE,
208  &xp,
209  &yp,
210  PETSC_IGNORE,
211  PETSC_IGNORE,
212  PETSC_IGNORE,
213  PETSC_IGNORE,
214  PETSC_IGNORE,
215  PETSC_IGNORE,
216  PETSC_IGNORE);
217 
218  const PetscInt *lx, *ly;
219  PetscInt *lxo, *lyo;
220  // PETSc-3.8.x or older use PetscDataType
221 #if PETSC_VERSION_LESS_THAN(3, 9, 0)
222  DMGetWorkArray(da, xp + yp + 2, PETSC_INT, &lxo);
223 #else
224  // PETSc-3.9.x or newer use MPI_DataType
225  DMGetWorkArray(da, xp + yp + 2, MPIU_INT, &lxo);
226 #endif
227  // Gets the ranges of indices in the x, y and z direction that are owned by each process
228  // Ranges here are different from what we have in Mat and Vec.
229  // It means how many points each processor holds
230  DMDAGetOwnershipRanges(da, &lx, &ly, NULL);
231  lxo[0] = 0;
232  for (PetscInt i = 0; i < xp; i++)
233  lxo[i + 1] = lxo[i] + lx[i];
234 
235  lyo = lxo + xp + 1;
236  lyo[0] = 0;
237  for (PetscInt i = 0; i < yp; i++)
238  lyo[i + 1] = lyo[i] + ly[i];
239 
240  // Try to calculate processor-grid coordinate (xpid, ypid)
241  PetscInt xpid, ypid, xpidplus, ypidplus;
242  // Finds integer in a sorted array of integers
243  // Loc: the location if found, otherwise -(slot+1)
244  // where slot is the place the value would go
245  PetscFindInt(i, xp + 1, lxo, &xpid);
246 
247  xpid = xpid < 0 ? -xpid - 1 - 1 : xpid;
248 
249  PetscFindInt(i + 1, xp + 1, lxo, &xpidplus);
250 
251  xpidplus = xpidplus < 0 ? -xpidplus - 1 - 1 : xpidplus;
252 
253  PetscFindInt(j, yp + 1, lyo, &ypid);
254 
255  ypid = ypid < 0 ? -ypid - 1 - 1 : ypid;
256 
257  PetscFindInt(j + 1, yp + 1, lyo, &ypidplus);
258 
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);
262 #else
263  DMRestoreWorkArray(da, xp + yp + 2, MPIU_INT, &lxo);
264 #endif
265 #endif
266  // Bottom Left
267  auto node0_ptr = mesh.add_point(Point(static_cast<Real>(i) / nx, static_cast<Real>(j) / ny, 0),
268  node_id_Quad4(type, nx, 0, i, j, 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();
271  // xpid + ypid * xp is the global processor ID
272  node0_ptr->processor_id() = xpid + ypid * xp;
273 
274  // Bottom Right
275  auto node1_ptr =
276  mesh.add_point(Point(static_cast<Real>(i + 1) / nx, static_cast<Real>(j) / ny, 0),
277  node_id_Quad4(type, nx, 0, i + 1, j, 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;
281 
282  // Top Right
283  auto node2_ptr =
284  mesh.add_point(Point(static_cast<Real>(i + 1) / nx, static_cast<Real>(j + 1) / ny, 0),
285  node_id_Quad4(type, nx, 0, i + 1, j + 1, 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;
289 
290  // Top Left
291  auto node3_ptr =
292  mesh.add_point(Point(static_cast<Real>(i) / nx, static_cast<Real>(j + 1) / ny, 0),
293  node_id_Quad4(type, nx, 0, i, j + 1, 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;
297 
298  // New an element and attach four nodes to it
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;
308 
309  // Bottom
310  if (j == 0)
311  boundary_info.add_side(elem, 0, 0);
312 
313  // Right
314  if (i == nx - 1)
315  boundary_info.add_side(elem, 1, 1);
316 
317  // Top
318  if (j == ny - 1)
319  boundary_info.add_side(elem, 2, 2);
320 
321  // Left
322  if (i == 0)
323  boundary_info.add_side(elem, 3, 3);
324 }
dof_id_type node_id_Quad4(const ElemType, const dof_id_type nx, const dof_id_type, const dof_id_type i, const dof_id_type j, const dof_id_type)

◆ add_node_Qua4()

void add_node_Qua4 ( dof_id_type  nx,
dof_id_type  ny,
dof_id_type  i,
dof_id_type  j,
processor_id_type  pid,
ElemType  type,
MeshBase &  mesh 
)

Definition at line 418 of file PETScDMDAMesh.C.

Referenced by build_cube_Quad4().

425 {
426  // Bottom Left
427  auto node0_ptr = mesh.add_point(Point(static_cast<Real>(i) / nx, static_cast<Real>(j) / ny, 0),
428  node_id_Quad4(type, nx, 0, i, j, 0));
429  node0_ptr->set_unique_id() = node_id_Quad4(type, nx, 0, i, j, 0);
430  node0_ptr->processor_id() = pid;
431 }
dof_id_type node_id_Quad4(const ElemType, const dof_id_type nx, const dof_id_type, const dof_id_type i, const dof_id_type j, const dof_id_type)

◆ build_cube_Quad4()

void build_cube_Quad4 ( UnstructuredMesh &  mesh,
DM  da,
const ElemType  type 
)

Definition at line 435 of file PETScDMDAMesh.C.

Referenced by PETScDMDAMesh::buildMesh().

436 {
437  const auto pid = mesh.comm().rank();
438 
439  BoundaryInfo & boundary_info = mesh.get_boundary_info();
440  // xs: start grid point (not element) index on local in x direction
441  // ys: start grid point index on local in y direction
442  // xm: number of grid points owned by the local processor in x direction
443  // ym: number of grid points owned by the local processor in y direction
444  // Mx: number of grid points on all processors in x direction
445  // My: number of grid points on all processors in y direction
446  // xp: number of processor cores in x direction
447  // yp: number of processor cores in y direction
448  PetscInt xs, ys, xm, ym, Mx, My, xp, yp;
449 
450  /* Get local grid boundaries */
451  DMDAGetCorners(da, &xs, &ys, PETSC_IGNORE, &xm, &ym, PETSC_IGNORE);
452  DMDAGetInfo(da,
453  PETSC_IGNORE,
454  &Mx,
455  &My,
456  PETSC_IGNORE,
457  &xp,
458  &yp,
459  PETSC_IGNORE,
460  PETSC_IGNORE,
461  PETSC_IGNORE,
462  PETSC_IGNORE,
463  PETSC_IGNORE,
464  PETSC_IGNORE,
465  PETSC_IGNORE);
466 
467  for (PetscInt j = ys; j < ys + ym; j++)
468  for (PetscInt i = xs; i < xs + xm; i++)
469  {
470  // We loop over grid points, but we are
471  // here building elements. So that we just
472  // simply skip the first x and y points since the
473  // number of grid ponts is one more than
474  // the number of grid elements
475  if (!i || !j)
476  continue;
477 
478  dof_id_type ele_id = (i - 1) + (j - 1) * (Mx - 1);
479 
480  add_element_Quad4(da, Mx - 1, My - 1, i - 1, j - 1, ele_id, pid, type, mesh);
481  }
482 
483  // If there is no element at the given processor
484  // We need to manually add all mesh nodes
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++)
488  add_node_Qua4(Mx, My, i, j, pid, type, mesh);
489 
490  // Need to link up the local elements before we can know what's missing
491  mesh.find_neighbors();
492 
493  mesh.find_neighbors(true);
494 
495  // Set RemoteElem neighbors
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));
500 
501  set_boundary_names_Quad4(boundary_info);
502  // Already partitioned!
503  mesh.skip_partitioning(true);
504 
505  // No need to renumber or find neighbors - done did it.
506  // Avoid deprecation message/error by _also_ setting
507  // allow_renumbering(false). This is a bit silly, but we want to
508  // catch cases where people are purely using the old "skip"
509  // interface and not the new flag setting one.
510  mesh.allow_renumbering(false);
511  mesh.prepare_for_use(/*skip_renumber (ignored!) = */ false,
512  /*skip_find_neighbors = */ true);
513 }
void add_element_Quad4(DM da, const dof_id_type nx, const dof_id_type ny, const dof_id_type i, const dof_id_type j, const dof_id_type elem_id, const processor_id_type pid, const ElemType type, MeshBase &mesh)
void add_node_Qua4(dof_id_type nx, dof_id_type ny, dof_id_type i, dof_id_type j, processor_id_type pid, ElemType type, MeshBase &mesh)
void set_boundary_names_Quad4(BoundaryInfo &boundary_info)

◆ elem_id_Quad4()

dof_id_type elem_id_Quad4 ( const dof_id_type  nx,
const dof_id_type  ,
const dof_id_type  i,
const dof_id_type  j,
const dof_id_type   
)

Definition at line 347 of file PETScDMDAMesh.C.

Referenced by get_neighbors_Quad4().

352 {
353  return (j * nx) + i;
354 }

◆ get_ghost_neighbors_Quad4()

void get_ghost_neighbors_Quad4 ( const dof_id_type  nx,
const dof_id_type  ny,
const MeshBase &  mesh,
std::set< dof_id_type > &  ghost_elems 
)

Definition at line 383 of file PETScDMDAMesh.C.

387 {
388  auto & boundary_info = mesh.get_boundary_info();
389 
390  dof_id_type i, j;
391 
392  std::vector<dof_id_type> neighbors(4);
393 
394  for (auto elem_ptr : mesh.element_ptr_range())
395  {
396  for (unsigned int s = 0; s < elem_ptr->n_sides(); s++)
397  {
398  // No current neighbor
399  if (!elem_ptr->neighbor_ptr(s))
400  {
401  // Not on a boundary
402  if (!boundary_info.n_boundary_ids(elem_ptr, s))
403  {
404  auto elem_id = elem_ptr->id();
405 
406  get_indices_Quad4(nx, 0, elem_id, i, j);
407 
408  get_neighbors_Quad4(nx, ny, i, j, neighbors);
409 
410  ghost_elems.insert(neighbors[s]);
411  }
412  }
413  }
414  }
415 }
void get_indices_Quad4(const dof_id_type nx, const dof_id_type, const dof_id_type elem_id, dof_id_type &i, dof_id_type &j)
void get_neighbors_Quad4(const dof_id_type nx, const dof_id_type ny, const dof_id_type i, const dof_id_type j, std::vector< dof_id_type > &neighbors)

◆ get_indices_Quad4()

void get_indices_Quad4 ( const dof_id_type  nx,
const dof_id_type  ,
const dof_id_type  elem_id,
dof_id_type &  i,
dof_id_type &  j 
)

Definition at line 336 of file PETScDMDAMesh.C.

Referenced by get_ghost_neighbors_Quad4().

341 {
342  i = elem_id % nx;
343  j = (elem_id - i) / nx;
344 }

◆ get_neighbors_Quad4()

void get_neighbors_Quad4 ( const dof_id_type  nx,
const dof_id_type  ny,
const dof_id_type  i,
const dof_id_type  j,
std::vector< dof_id_type > &  neighbors 
)
inline

Definition at line 357 of file PETScDMDAMesh.C.

Referenced by get_ghost_neighbors_Quad4().

362 {
363  std::fill(neighbors.begin(), neighbors.end(), Elem::invalid_id);
364 
365  // Bottom
366  if (j != 0)
367  neighbors[0] = elem_id_Quad4(nx, 0, i, j - 1, 0);
368 
369  // Right
370  if (i != nx - 1)
371  neighbors[1] = elem_id_Quad4(nx, 0, i + 1, j, 0);
372 
373  // Top
374  if (j != ny - 1)
375  neighbors[2] = elem_id_Quad4(nx, 0, i, j + 1, 0);
376 
377  // Left
378  if (i != 0)
379  neighbors[3] = elem_id_Quad4(nx, 0, i - 1, j, 0);
380 }
dof_id_type elem_id_Quad4(const dof_id_type nx, const dof_id_type, const dof_id_type i, const dof_id_type j, const dof_id_type)

◆ node_id_Quad4()

dof_id_type node_id_Quad4 ( const ElemType  ,
const dof_id_type  nx,
const dof_id_type  ,
const dof_id_type  i,
const dof_id_type  j,
const dof_id_type   
)
inline

Definition at line 171 of file PETScDMDAMesh.C.

Referenced by add_element_Quad4(), and add_node_Qua4().

178 {
179  // Transform a grid coordinate (i, j) to its global node ID
180  // This match what PETSc does
181  return i + j * (nx + 1);
182 }

◆ registerMooseObject()

registerMooseObject ( "ExternalPetscSolverApp"  ,
PETScDMDAMesh   
)

◆ set_boundary_names_Quad4()

void set_boundary_names_Quad4 ( BoundaryInfo &  boundary_info)

Definition at line 327 of file PETScDMDAMesh.C.

Referenced by build_cube_Quad4().

328 {
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";
333 }

◆ validParams< PETScDMDAMesh >()

template<>
InputParameters validParams< PETScDMDAMesh > ( )

Definition at line 36 of file PETScDMDAMesh.C.

37 {
38  InputParameters params = validParams<MooseMesh>();
39 
40  MooseEnum elem_types("EDGE2 QUAD4 HEX8"); // no default
41 
42  MooseEnum dims("1=1 2 3", "2");
43  params.addRequiredParam<MooseEnum>(
44  "dim", dims, "The dimension of the mesh to be generated"); // Make this parameter required
45 
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",
56  elem_types,
57  "The type of element from libMesh to "
58  "generate (default: linear element for "
59  "requested dimension)");
60 
61  params.addParamNamesToGroup("dim", "Main");
62 
63  params.addClassDescription(
64  "Create a line, square, or cube mesh with uniformly spaced memsh using PETSc DMDA.");
65 
66  // This mesh is always distributed
67  params.set<MooseEnum>("parallel_type") = "DISTRIBUTED";
68 
69  return params;
70 }