xref: /petsc/src/dm/impls/plex/tests/ex18.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
1c4762a1bSJed Brown static char help[] = "Tests for parallel mesh loading and parallel topological interpolation\n\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown #include <petsc/private/dmpleximpl.h>
4c4762a1bSJed Brown /* List of test meshes
5c4762a1bSJed Brown 
6c4762a1bSJed Brown Network
7c4762a1bSJed Brown -------
8c4762a1bSJed Brown Test 0 (2 ranks):
9c4762a1bSJed Brown 
10c4762a1bSJed Brown network=0:
11c4762a1bSJed Brown ---------
12c4762a1bSJed Brown   cell 0   cell 1   cell 2          nCells-1       (edge)
13c4762a1bSJed Brown 0 ------ 1 ------ 2 ------ 3 -- -- v --  -- nCells (vertex)
14c4762a1bSJed Brown 
15c4762a1bSJed Brown   vertex distribution:
16c4762a1bSJed Brown     rank 0: 0 1
17c4762a1bSJed Brown     rank 1: 2 3 ... nCells
18c4762a1bSJed Brown   cell(edge) distribution:
19c4762a1bSJed Brown     rank 0: 0 1
20c4762a1bSJed Brown     rank 1: 2 ... nCells-1
21c4762a1bSJed Brown 
22c4762a1bSJed Brown network=1:
23c4762a1bSJed Brown ---------
24c4762a1bSJed Brown                v2
25c4762a1bSJed Brown                 ^
26c4762a1bSJed Brown                 |
27c4762a1bSJed Brown                cell 2
28c4762a1bSJed Brown                 |
29c4762a1bSJed Brown  v0 --cell 0--> v3--cell 1--> v1
30c4762a1bSJed Brown 
31c4762a1bSJed Brown   vertex distribution:
32c4762a1bSJed Brown     rank 0: 0 1 3
33c4762a1bSJed Brown     rank 1: 2
34c4762a1bSJed Brown   cell(edge) distribution:
35c4762a1bSJed Brown     rank 0: 0 1
36c4762a1bSJed Brown     rank 1: 2
37c4762a1bSJed Brown 
38c4762a1bSJed Brown   example:
39c4762a1bSJed Brown     mpiexec -n 2 ./ex18 -distribute 1 -dim 1 -orig_dm_view -dist_dm_view -dist_dm_view -petscpartitioner_type parmetis -ncells 50
40c4762a1bSJed Brown 
41c4762a1bSJed Brown Triangle
42c4762a1bSJed Brown --------
43c4762a1bSJed Brown Test 0 (2 ranks):
44c4762a1bSJed Brown Two triangles sharing a face
45c4762a1bSJed Brown 
46c4762a1bSJed Brown         2
47c4762a1bSJed Brown       / | \
48c4762a1bSJed Brown      /  |  \
49c4762a1bSJed Brown     /   |   \
50c4762a1bSJed Brown    0  0 | 1  3
51c4762a1bSJed Brown     \   |   /
52c4762a1bSJed Brown      \  |  /
53c4762a1bSJed Brown       \ | /
54c4762a1bSJed Brown         1
55c4762a1bSJed Brown 
56c4762a1bSJed Brown   vertex distribution:
57c4762a1bSJed Brown     rank 0: 0 1
58c4762a1bSJed Brown     rank 1: 2 3
59c4762a1bSJed Brown   cell distribution:
60c4762a1bSJed Brown     rank 0: 0
61c4762a1bSJed Brown     rank 1: 1
62c4762a1bSJed Brown 
63c4762a1bSJed Brown Test 1 (3 ranks):
64c4762a1bSJed Brown Four triangles partitioned across 3 ranks
65c4762a1bSJed Brown 
66c4762a1bSJed Brown    0 _______ 3
67c4762a1bSJed Brown    | \     / |
68c4762a1bSJed Brown    |  \ 1 /  |
69c4762a1bSJed Brown    |   \ /   |
70c4762a1bSJed Brown    | 0  2  2 |
71c4762a1bSJed Brown    |   / \   |
72c4762a1bSJed Brown    |  / 3 \  |
73c4762a1bSJed Brown    | /     \ |
74c4762a1bSJed Brown    1 ------- 4
75c4762a1bSJed Brown 
76c4762a1bSJed Brown   vertex distribution:
77c4762a1bSJed Brown     rank 0: 0 1
78c4762a1bSJed Brown     rank 1: 2 3
79c4762a1bSJed Brown     rank 2: 4
80c4762a1bSJed Brown   cell distribution:
81c4762a1bSJed Brown     rank 0: 0
82c4762a1bSJed Brown     rank 1: 1
83c4762a1bSJed Brown     rank 2: 2 3
84c4762a1bSJed Brown 
85c4762a1bSJed Brown Test 2 (3 ranks):
86c4762a1bSJed Brown Four triangles partitioned across 3 ranks
87c4762a1bSJed Brown 
88c4762a1bSJed Brown    1 _______ 3
89c4762a1bSJed Brown    | \     / |
90c4762a1bSJed Brown    |  \ 1 /  |
91c4762a1bSJed Brown    |   \ /   |
92c4762a1bSJed Brown    | 0  0  2 |
93c4762a1bSJed Brown    |   / \   |
94c4762a1bSJed Brown    |  / 3 \  |
95c4762a1bSJed Brown    | /     \ |
96c4762a1bSJed Brown    2 ------- 4
97c4762a1bSJed Brown 
98c4762a1bSJed Brown   vertex distribution:
99c4762a1bSJed Brown     rank 0: 0 1
100c4762a1bSJed Brown     rank 1: 2 3
101c4762a1bSJed Brown     rank 2: 4
102c4762a1bSJed Brown   cell distribution:
103c4762a1bSJed Brown     rank 0: 0
104c4762a1bSJed Brown     rank 1: 1
105c4762a1bSJed Brown     rank 2: 2 3
106c4762a1bSJed Brown 
107c4762a1bSJed Brown Tetrahedron
108c4762a1bSJed Brown -----------
109c4762a1bSJed Brown Test 0:
110c4762a1bSJed Brown Two tets sharing a face
111c4762a1bSJed Brown 
112c4762a1bSJed Brown  cell   3 _______    cell
113c4762a1bSJed Brown  0    / | \      \   1
114c4762a1bSJed Brown      /  |  \      \
115c4762a1bSJed Brown     /   |   \      \
116c4762a1bSJed Brown    0----|----4-----2
117c4762a1bSJed Brown     \   |   /      /
118c4762a1bSJed Brown      \  |  /      /
119c4762a1bSJed Brown       \ | /      /
120c4762a1bSJed Brown         1-------
121c4762a1bSJed Brown    y
122c4762a1bSJed Brown    | x
123c4762a1bSJed Brown    |/
124c4762a1bSJed Brown    *----z
125c4762a1bSJed Brown 
126c4762a1bSJed Brown   vertex distribution:
127c4762a1bSJed Brown     rank 0: 0 1
128c4762a1bSJed Brown     rank 1: 2 3 4
129c4762a1bSJed Brown   cell distribution:
130c4762a1bSJed Brown     rank 0: 0
131c4762a1bSJed Brown     rank 1: 1
132c4762a1bSJed Brown 
133c4762a1bSJed Brown Quadrilateral
134c4762a1bSJed Brown -------------
135c4762a1bSJed Brown Test 0 (2 ranks):
136c4762a1bSJed Brown Two quads sharing a face
137c4762a1bSJed Brown 
138c4762a1bSJed Brown    3-------2-------5
139c4762a1bSJed Brown    |       |       |
140c4762a1bSJed Brown    |   0   |   1   |
141c4762a1bSJed Brown    |       |       |
142c4762a1bSJed Brown    0-------1-------4
143c4762a1bSJed Brown 
144c4762a1bSJed Brown   vertex distribution:
145c4762a1bSJed Brown     rank 0: 0 1 2
146c4762a1bSJed Brown     rank 1: 3 4 5
147c4762a1bSJed Brown   cell distribution:
148c4762a1bSJed Brown     rank 0: 0
149c4762a1bSJed Brown     rank 1: 1
150c4762a1bSJed Brown 
151c4762a1bSJed Brown TODO Test 1:
152c4762a1bSJed Brown A quad and a triangle sharing a face
153c4762a1bSJed Brown 
154c4762a1bSJed Brown    5-------4
155c4762a1bSJed Brown    |       | \
156c4762a1bSJed Brown    |   0   |  \
157c4762a1bSJed Brown    |       | 1 \
158c4762a1bSJed Brown    2-------3----6
159c4762a1bSJed Brown 
160c4762a1bSJed Brown Hexahedron
161c4762a1bSJed Brown ----------
162c4762a1bSJed Brown Test 0 (2 ranks):
163c4762a1bSJed Brown Two hexes sharing a face
164c4762a1bSJed Brown 
165c4762a1bSJed Brown cell   7-------------6-------------11 cell
166c4762a1bSJed Brown 0     /|            /|            /|     1
167c4762a1bSJed Brown      / |   F1      / |   F7      / |
168c4762a1bSJed Brown     /  |          /  |          /  |
169c4762a1bSJed Brown    4-------------5-------------10  |
170c4762a1bSJed Brown    |   |     F4  |   |     F10 |   |
171c4762a1bSJed Brown    |   |         |   |         |   |
172c4762a1bSJed Brown    |F5 |         |F3 |         |F9 |
173c4762a1bSJed Brown    |   |  F2     |   |   F8    |   |
174c4762a1bSJed Brown    |   3---------|---2---------|---9
175c4762a1bSJed Brown    |  /          |  /          |  /
176c4762a1bSJed Brown    | /   F0      | /    F6     | /
177c4762a1bSJed Brown    |/            |/            |/
178c4762a1bSJed Brown    0-------------1-------------8
179c4762a1bSJed Brown 
180c4762a1bSJed Brown   vertex distribution:
181c4762a1bSJed Brown     rank 0: 0 1 2 3 4 5
182c4762a1bSJed Brown     rank 1: 6 7 8 9 10 11
183c4762a1bSJed Brown   cell distribution:
184c4762a1bSJed Brown     rank 0: 0
185c4762a1bSJed Brown     rank 1: 1
186c4762a1bSJed Brown 
187c4762a1bSJed Brown */
188c4762a1bSJed Brown 
1899371c9d4SSatish Balay typedef enum {
1909371c9d4SSatish Balay   NONE,
1919371c9d4SSatish Balay   CREATE,
1929371c9d4SSatish Balay   AFTER_CREATE,
1939371c9d4SSatish Balay   AFTER_DISTRIBUTE
1949371c9d4SSatish Balay } InterpType;
195c4762a1bSJed Brown 
196c4762a1bSJed Brown typedef struct {
197c4762a1bSJed Brown   PetscInt    debug;        /* The debugging level */
198c4762a1bSJed Brown   PetscInt    testNum;      /* Indicates the mesh to create */
199c4762a1bSJed Brown   PetscInt    dim;          /* The topological mesh dimension */
200c4762a1bSJed Brown   PetscBool   cellSimplex;  /* Use simplices or hexes */
201c4762a1bSJed Brown   PetscBool   distribute;   /* Distribute the mesh */
202c4762a1bSJed Brown   InterpType  interpolate;  /* Interpolate the mesh before or after DMPlexDistribute() */
203c4762a1bSJed Brown   PetscBool   useGenerator; /* Construct mesh with a mesh generator */
204c4762a1bSJed Brown   PetscBool   testOrientIF; /* Test for different original interface orientations */
205c4762a1bSJed Brown   PetscBool   testHeavy;    /* Run the heavy PointSF test */
206c4762a1bSJed Brown   PetscBool   customView;   /* Show results of DMPlexIsInterpolated() etc. */
207c4762a1bSJed Brown   PetscInt    ornt[2];      /* Orientation of interface on rank 0 and rank 1 */
208c4762a1bSJed Brown   PetscInt    faces[3];     /* Number of faces per dimension for generator */
209d3e1f4ccSVaclav Hapla   PetscScalar coords[128];
210c4762a1bSJed Brown   PetscReal   coordsTol;
211c4762a1bSJed Brown   PetscInt    ncoords;
212c4762a1bSJed Brown   PetscInt    pointsToExpand[128];
213c4762a1bSJed Brown   PetscInt    nPointsToExpand;
214c4762a1bSJed Brown   PetscBool   testExpandPointsEmpty;
215c4762a1bSJed Brown   char        filename[PETSC_MAX_PATH_LEN]; /* Import mesh from file */
216c4762a1bSJed Brown } AppCtx;
217c4762a1bSJed Brown 
218c4762a1bSJed Brown struct _n_PortableBoundary {
219c4762a1bSJed Brown   Vec           coordinates;
220c4762a1bSJed Brown   PetscInt      depth;
221c4762a1bSJed Brown   PetscSection *sections;
222c4762a1bSJed Brown };
223c4762a1bSJed Brown typedef struct _n_PortableBoundary *PortableBoundary;
224c4762a1bSJed Brown 
225956f8c0dSBarry Smith #if defined(PETSC_USE_LOG)
226c4762a1bSJed Brown static PetscLogStage stage[3];
227956f8c0dSBarry Smith #endif
228c4762a1bSJed Brown 
229c4762a1bSJed Brown static PetscErrorCode DMPlexCheckPointSFHeavy(DM, PortableBoundary);
230c4762a1bSJed Brown static PetscErrorCode DMPlexSetOrientInterface_Private(DM, PetscBool);
231c4762a1bSJed Brown static PetscErrorCode DMPlexGetExpandedBoundary_Private(DM, PortableBoundary *);
232c4762a1bSJed Brown static PetscErrorCode DMPlexExpandedConesToFaces_Private(DM, IS, PetscSection, IS *);
233c4762a1bSJed Brown 
2349371c9d4SSatish Balay static PetscErrorCode PortableBoundaryDestroy(PortableBoundary *bnd) {
235c4762a1bSJed Brown   PetscInt d;
236c4762a1bSJed Brown 
237c4762a1bSJed Brown   PetscFunctionBegin;
238c4762a1bSJed Brown   if (!*bnd) PetscFunctionReturn(0);
2399566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(*bnd)->coordinates));
240*48a46eb9SPierre Jolivet   for (d = 0; d < (*bnd)->depth; d++) PetscCall(PetscSectionDestroy(&(*bnd)->sections[d]));
2419566063dSJacob Faibussowitsch   PetscCall(PetscFree((*bnd)->sections));
2429566063dSJacob Faibussowitsch   PetscCall(PetscFree(*bnd));
243c4762a1bSJed Brown   PetscFunctionReturn(0);
244c4762a1bSJed Brown }
245c4762a1bSJed Brown 
2469371c9d4SSatish Balay static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) {
247c4762a1bSJed Brown   const char *interpTypes[4] = {"none", "create", "after_create", "after_distribute"};
248c4762a1bSJed Brown   PetscInt    interp         = NONE, dim;
249c4762a1bSJed Brown   PetscBool   flg1, flg2;
250c4762a1bSJed Brown 
251c4762a1bSJed Brown   PetscFunctionBegin;
252c4762a1bSJed Brown   options->debug                 = 0;
253c4762a1bSJed Brown   options->testNum               = 0;
254c4762a1bSJed Brown   options->dim                   = 2;
255c4762a1bSJed Brown   options->cellSimplex           = PETSC_TRUE;
256c4762a1bSJed Brown   options->distribute            = PETSC_FALSE;
257c4762a1bSJed Brown   options->interpolate           = NONE;
258c4762a1bSJed Brown   options->useGenerator          = PETSC_FALSE;
259c4762a1bSJed Brown   options->testOrientIF          = PETSC_FALSE;
260c4762a1bSJed Brown   options->testHeavy             = PETSC_TRUE;
261c4762a1bSJed Brown   options->customView            = PETSC_FALSE;
262c4762a1bSJed Brown   options->testExpandPointsEmpty = PETSC_FALSE;
263c4762a1bSJed Brown   options->ornt[0]               = 0;
264c4762a1bSJed Brown   options->ornt[1]               = 0;
265c4762a1bSJed Brown   options->faces[0]              = 2;
266c4762a1bSJed Brown   options->faces[1]              = 2;
267c4762a1bSJed Brown   options->faces[2]              = 2;
268c4762a1bSJed Brown   options->filename[0]           = '\0';
269c4762a1bSJed Brown   options->coordsTol             = PETSC_DEFAULT;
270c4762a1bSJed Brown 
271d0609cedSBarry Smith   PetscOptionsBegin(comm, "", "Meshing Interpolation Test Options", "DMPLEX");
2729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-debug", "The debugging level", "ex18.c", options->debug, &options->debug, NULL, 0));
2739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-testnum", "The mesh to create", "ex18.c", options->testNum, &options->testNum, NULL, 0));
2749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-cell_simplex", "Generate simplices if true, otherwise hexes", "ex18.c", options->cellSimplex, &options->cellSimplex, NULL));
2759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-distribute", "Distribute the mesh", "ex18.c", options->distribute, &options->distribute, NULL));
2769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-interpolate", "Type of mesh interpolation (none, create, after_create, after_distribute)", "ex18.c", interpTypes, 4, interpTypes[options->interpolate], &interp, NULL));
277c4762a1bSJed Brown   options->interpolate = (InterpType)interp;
2781dca8a05SBarry Smith   PetscCheck(options->distribute || options->interpolate != AFTER_DISTRIBUTE, comm, PETSC_ERR_SUP, "-interpolate after_distribute  needs  -distribute 1");
2799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-use_generator", "Use a mesh generator to build the mesh", "ex18.c", options->useGenerator, &options->useGenerator, NULL));
280c4762a1bSJed Brown   options->ncoords = 128;
2819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsScalarArray("-view_vertices_from_coords", "Print DAG points corresponding to vertices with given coordinates", "ex18.c", options->coords, &options->ncoords, NULL));
2829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-view_vertices_from_coords_tol", "Tolerance for -view_vertices_from_coords", "ex18.c", options->coordsTol, &options->coordsTol, NULL));
283c4762a1bSJed Brown   options->nPointsToExpand = 128;
2849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-test_expand_points", "Expand given array of DAG point using DMPlexGetConeRecursive() and print results", "ex18.c", options->pointsToExpand, &options->nPointsToExpand, NULL));
285*48a46eb9SPierre Jolivet   if (options->nPointsToExpand) PetscCall(PetscOptionsBool("-test_expand_points_empty", "For -test_expand_points, rank 0 will have empty input array", "ex18.c", options->testExpandPointsEmpty, &options->testExpandPointsEmpty, NULL));
2869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-test_heavy", "Run the heavy PointSF test", "ex18.c", options->testHeavy, &options->testHeavy, NULL));
2879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-custom_view", "Custom DMPlex view", "ex18.c", options->customView, &options->customView, NULL));
2889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRangeInt("-dim", "The topological mesh dimension", "ex18.c", options->dim, &options->dim, &flg1, 1, 3));
289c4762a1bSJed Brown   dim = 3;
2909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-faces", "Number of faces per dimension", "ex18.c", options->faces, &dim, &flg2));
291c4762a1bSJed Brown   if (flg2) {
2921dca8a05SBarry Smith     PetscCheck(!flg1 || dim == options->dim, comm, PETSC_ERR_ARG_OUTOFRANGE, "specified -dim %" PetscInt_FMT " is not equal to length %" PetscInt_FMT " of -faces (note that -dim can be omitted)", options->dim, dim);
293c4762a1bSJed Brown     options->dim = dim;
294c4762a1bSJed Brown   }
2959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-filename", "The mesh file", "ex18.c", options->filename, options->filename, sizeof(options->filename), NULL));
2969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-rotate_interface_0", "Rotation (relative orientation) of interface on rank 0; implies -interpolate create -distribute 0", "ex18.c", options->ornt[0], &options->ornt[0], &options->testOrientIF, 0));
2979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-rotate_interface_1", "Rotation (relative orientation) of interface on rank 1; implies -interpolate create -distribute 0", "ex18.c", options->ornt[1], &options->ornt[1], &flg2, 0));
29808401ef6SPierre Jolivet   PetscCheck(flg2 == options->testOrientIF, comm, PETSC_ERR_ARG_OUTOFRANGE, "neither or both -rotate_interface_0 -rotate_interface_1 must be set");
299c4762a1bSJed Brown   if (options->testOrientIF) {
300c4762a1bSJed Brown     PetscInt i;
301c4762a1bSJed Brown     for (i = 0; i < 2; i++) {
302c4762a1bSJed Brown       if (options->ornt[i] >= 10) options->ornt[i] = -(options->ornt[i] - 10); /* 11 12 13 become -1 -2 -3 */
303c4762a1bSJed Brown     }
304c4762a1bSJed Brown     options->filename[0]  = 0;
305c4762a1bSJed Brown     options->useGenerator = PETSC_FALSE;
306c4762a1bSJed Brown     options->dim          = 3;
307c4762a1bSJed Brown     options->cellSimplex  = PETSC_TRUE;
308c4762a1bSJed Brown     options->interpolate  = CREATE;
309c4762a1bSJed Brown     options->distribute   = PETSC_FALSE;
310c4762a1bSJed Brown   }
311d0609cedSBarry Smith   PetscOptionsEnd();
312c4762a1bSJed Brown   PetscFunctionReturn(0);
313c4762a1bSJed Brown }
314c4762a1bSJed Brown 
3159371c9d4SSatish Balay static PetscErrorCode CreateMesh_1D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) {
316c4762a1bSJed Brown   PetscInt    testNum = user->testNum;
317c4762a1bSJed Brown   PetscMPIInt rank, size;
318c4762a1bSJed Brown   PetscInt    numCorners = 2, i;
319c4762a1bSJed Brown   PetscInt    numCells, numVertices, network;
320a4a685f2SJacob Faibussowitsch   PetscInt   *cells;
321c4762a1bSJed Brown   PetscReal  *coords;
322c4762a1bSJed Brown 
323c4762a1bSJed Brown   PetscFunctionBegin;
3249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
3259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
32663a3b9bcSJacob Faibussowitsch   PetscCheck(size <= 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for <=2 processes", testNum);
327c4762a1bSJed Brown 
328c4762a1bSJed Brown   numCells = 3;
3299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-ncells", &numCells, NULL));
33063a3b9bcSJacob Faibussowitsch   PetscCheck(numCells >= 3, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test ncells %" PetscInt_FMT " must >=3", numCells);
331c4762a1bSJed Brown 
332c4762a1bSJed Brown   if (size == 1) {
333c4762a1bSJed Brown     numVertices = numCells + 1;
3349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numVertices, &coords));
335c4762a1bSJed Brown     for (i = 0; i < numCells; i++) {
3369371c9d4SSatish Balay       cells[2 * i]      = i;
3379371c9d4SSatish Balay       cells[2 * i + 1]  = i + 1;
3389371c9d4SSatish Balay       coords[2 * i]     = i;
3399371c9d4SSatish Balay       coords[2 * i + 1] = i + 1;
340c4762a1bSJed Brown     }
341c4762a1bSJed Brown 
3429566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromCellListPetsc(comm, user->dim, numCells, numVertices, numCorners, PETSC_FALSE, cells, user->dim, coords, dm));
3439566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cells, coords));
344c4762a1bSJed Brown     PetscFunctionReturn(0);
345c4762a1bSJed Brown   }
346c4762a1bSJed Brown 
347c4762a1bSJed Brown   network = 0;
3489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-network_case", &network, NULL));
349c4762a1bSJed Brown   if (network == 0) {
350c4762a1bSJed Brown     switch (rank) {
3519371c9d4SSatish Balay     case 0: {
352c4762a1bSJed Brown       numCells    = 2;
353c4762a1bSJed Brown       numVertices = numCells;
3549566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numCells, &coords));
3559371c9d4SSatish Balay       cells[0]  = 0;
3569371c9d4SSatish Balay       cells[1]  = 1;
3579371c9d4SSatish Balay       cells[2]  = 1;
3589371c9d4SSatish Balay       cells[3]  = 2;
3599371c9d4SSatish Balay       coords[0] = 0.;
3609371c9d4SSatish Balay       coords[1] = 1.;
3619371c9d4SSatish Balay       coords[2] = 1.;
3629371c9d4SSatish Balay       coords[3] = 2.;
3639371c9d4SSatish Balay     } break;
3649371c9d4SSatish Balay     case 1: {
365c4762a1bSJed Brown       numCells -= 2;
366c4762a1bSJed Brown       numVertices = numCells + 1;
3679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numCells, &coords));
368c4762a1bSJed Brown       for (i = 0; i < numCells; i++) {
3699371c9d4SSatish Balay         cells[2 * i]      = 2 + i;
3709371c9d4SSatish Balay         cells[2 * i + 1]  = 2 + i + 1;
3719371c9d4SSatish Balay         coords[2 * i]     = 2 + i;
3729371c9d4SSatish Balay         coords[2 * i + 1] = 2 + i + 1;
373c4762a1bSJed Brown       }
3749371c9d4SSatish Balay     } break;
37598921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
376c4762a1bSJed Brown     }
377c4762a1bSJed Brown   } else { /* network_case = 1 */
378c4762a1bSJed Brown     /* ----------------------- */
379c4762a1bSJed Brown     switch (rank) {
3809371c9d4SSatish Balay     case 0: {
381c4762a1bSJed Brown       numCells    = 2;
382c4762a1bSJed Brown       numVertices = 3;
3839566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numCells, &coords));
3849371c9d4SSatish Balay       cells[0] = 0;
3859371c9d4SSatish Balay       cells[1] = 3;
3869371c9d4SSatish Balay       cells[2] = 3;
3879371c9d4SSatish Balay       cells[3] = 1;
3889371c9d4SSatish Balay     } break;
3899371c9d4SSatish Balay     case 1: {
390c4762a1bSJed Brown       numCells    = 1;
391c4762a1bSJed Brown       numVertices = 1;
3929566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numCells, &coords));
3939371c9d4SSatish Balay       cells[0] = 3;
3949371c9d4SSatish Balay       cells[1] = 2;
3959371c9d4SSatish Balay     } break;
39698921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
397c4762a1bSJed Brown     }
398c4762a1bSJed Brown   }
3999566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, PETSC_FALSE, cells, user->dim, coords, NULL, NULL, dm));
4009566063dSJacob Faibussowitsch   PetscCall(PetscFree2(cells, coords));
401c4762a1bSJed Brown   PetscFunctionReturn(0);
402c4762a1bSJed Brown }
403c4762a1bSJed Brown 
4049371c9d4SSatish Balay static PetscErrorCode CreateSimplex_2D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) {
405c4762a1bSJed Brown   PetscInt    testNum = user->testNum, p;
406c4762a1bSJed Brown   PetscMPIInt rank, size;
407c4762a1bSJed Brown 
408c4762a1bSJed Brown   PetscFunctionBegin;
4099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
4109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
411c4762a1bSJed Brown   switch (testNum) {
412c4762a1bSJed Brown   case 0:
41363a3b9bcSJacob Faibussowitsch     PetscCheck(size == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 2 processes", testNum);
414c4762a1bSJed Brown     switch (rank) {
4159371c9d4SSatish Balay     case 0: {
416c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
417a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {0, 1, 2};
418c4762a1bSJed Brown       PetscReal      coords[4]       = {-0.5, 0.5, 0.0, 0.0};
419c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
420c4762a1bSJed Brown 
4219566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4229566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4239371c9d4SSatish Balay     } break;
4249371c9d4SSatish Balay     case 1: {
425c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
426a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {1, 3, 2};
427c4762a1bSJed Brown       PetscReal      coords[4]       = {0.0, 1.0, 0.5, 0.5};
428c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
429c4762a1bSJed Brown 
4309566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4319566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4329371c9d4SSatish Balay     } break;
43398921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
434c4762a1bSJed Brown     }
435c4762a1bSJed Brown     break;
436c4762a1bSJed Brown   case 1:
43763a3b9bcSJacob Faibussowitsch     PetscCheck(size == 3, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 3 processes", testNum);
438c4762a1bSJed Brown     switch (rank) {
4399371c9d4SSatish Balay     case 0: {
440c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
441a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {0, 1, 2};
442c4762a1bSJed Brown       PetscReal      coords[4]       = {0.0, 1.0, 0.0, 0.0};
443c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
444c4762a1bSJed Brown 
4459566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4469566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4479371c9d4SSatish Balay     } break;
4489371c9d4SSatish Balay     case 1: {
449c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
450a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {0, 2, 3};
451c4762a1bSJed Brown       PetscReal      coords[4]       = {0.5, 0.5, 1.0, 1.0};
452c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
453c4762a1bSJed Brown 
4549566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4559566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4569371c9d4SSatish Balay     } break;
4579371c9d4SSatish Balay     case 2: {
458c4762a1bSJed Brown       const PetscInt numCells = 2, numVertices = 1, numCorners = 3;
459a4a685f2SJacob Faibussowitsch       const PetscInt cells[6]         = {2, 4, 3, 2, 1, 4};
460c4762a1bSJed Brown       PetscReal      coords[2]        = {1.0, 0.0};
461c4762a1bSJed Brown       PetscInt       markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1};
462c4762a1bSJed Brown 
4639566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4649566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4659371c9d4SSatish Balay     } break;
46698921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
467c4762a1bSJed Brown     }
468c4762a1bSJed Brown     break;
469c4762a1bSJed Brown   case 2:
47063a3b9bcSJacob Faibussowitsch     PetscCheck(size == 3, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 3 processes", testNum);
471c4762a1bSJed Brown     switch (rank) {
4729371c9d4SSatish Balay     case 0: {
473c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
474a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {1, 2, 0};
475c4762a1bSJed Brown       PetscReal      coords[4]       = {0.5, 0.5, 0.0, 1.0};
476c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
477c4762a1bSJed Brown 
4789566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4799566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4809371c9d4SSatish Balay     } break;
4819371c9d4SSatish Balay     case 1: {
482c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
483a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {1, 0, 3};
484c4762a1bSJed Brown       PetscReal      coords[4]       = {0.0, 0.0, 1.0, 1.0};
485c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
486c4762a1bSJed Brown 
4879566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4889566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4899371c9d4SSatish Balay     } break;
4909371c9d4SSatish Balay     case 2: {
491c4762a1bSJed Brown       const PetscInt numCells = 2, numVertices = 1, numCorners = 3;
492a4a685f2SJacob Faibussowitsch       const PetscInt cells[6]         = {0, 4, 3, 0, 2, 4};
493c4762a1bSJed Brown       PetscReal      coords[2]        = {1.0, 0.0};
494c4762a1bSJed Brown       PetscInt       markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1};
495c4762a1bSJed Brown 
4969566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4979566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4989371c9d4SSatish Balay     } break;
49998921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
500c4762a1bSJed Brown     }
501c4762a1bSJed Brown     break;
50263a3b9bcSJacob Faibussowitsch   default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %" PetscInt_FMT, testNum);
503c4762a1bSJed Brown   }
504c4762a1bSJed Brown   PetscFunctionReturn(0);
505c4762a1bSJed Brown }
506c4762a1bSJed Brown 
5079371c9d4SSatish Balay static PetscErrorCode CreateSimplex_3D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) {
508c4762a1bSJed Brown   PetscInt    testNum = user->testNum, p;
509c4762a1bSJed Brown   PetscMPIInt rank, size;
510c4762a1bSJed Brown 
511c4762a1bSJed Brown   PetscFunctionBegin;
5129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
514c4762a1bSJed Brown   switch (testNum) {
515c4762a1bSJed Brown   case 0:
51663a3b9bcSJacob Faibussowitsch     PetscCheck(size == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 2 processes", testNum);
517c4762a1bSJed Brown     switch (rank) {
5189371c9d4SSatish Balay     case 0: {
519c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 4;
520a4a685f2SJacob Faibussowitsch       const PetscInt cells[4]        = {0, 2, 1, 3};
521c4762a1bSJed Brown       PetscReal      coords[6]       = {0.0, 0.0, -0.5, 0.0, -0.5, 0.0};
522c4762a1bSJed Brown       PetscInt       markerPoints[8] = {1, 1, 2, 1, 3, 1, 4, 1};
523c4762a1bSJed Brown 
5249566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5259566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5269371c9d4SSatish Balay     } break;
5279371c9d4SSatish Balay     case 1: {
528c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 3, numCorners = 4;
529a4a685f2SJacob Faibussowitsch       const PetscInt cells[4]        = {1, 2, 4, 3};
530c4762a1bSJed Brown       PetscReal      coords[9]       = {1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5};
531c4762a1bSJed Brown       PetscInt       markerPoints[8] = {1, 1, 2, 1, 3, 1, 4, 1};
532c4762a1bSJed Brown 
5339566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5349566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5359371c9d4SSatish Balay     } break;
53698921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
537c4762a1bSJed Brown     }
538c4762a1bSJed Brown     break;
53963a3b9bcSJacob Faibussowitsch   default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %" PetscInt_FMT, testNum);
540c4762a1bSJed Brown   }
541c4762a1bSJed Brown   if (user->testOrientIF) {
542c4762a1bSJed Brown     PetscInt ifp[] = {8, 6};
543c4762a1bSJed Brown 
5449566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*dm, "Mesh before orientation"));
5459566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(*dm, NULL, "-before_orientation_dm_view"));
546c4762a1bSJed Brown     /* rotate interface face ifp[rank] by given orientation ornt[rank] */
5479566063dSJacob Faibussowitsch     PetscCall(DMPlexOrientPoint(*dm, ifp[rank], user->ornt[rank]));
5489566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(*dm, NULL, "-before_orientation_dm_view"));
5499566063dSJacob Faibussowitsch     PetscCall(DMPlexCheckFaces(*dm, 0));
5509566063dSJacob Faibussowitsch     PetscCall(DMPlexOrientInterface_Internal(*dm));
5519566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm, "Orientation test PASSED\n"));
552c4762a1bSJed Brown   }
553c4762a1bSJed Brown   PetscFunctionReturn(0);
554c4762a1bSJed Brown }
555c4762a1bSJed Brown 
5569371c9d4SSatish Balay static PetscErrorCode CreateQuad_2D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) {
557c4762a1bSJed Brown   PetscInt    testNum = user->testNum, p;
558c4762a1bSJed Brown   PetscMPIInt rank, size;
559c4762a1bSJed Brown 
560c4762a1bSJed Brown   PetscFunctionBegin;
5619566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5629566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
563c4762a1bSJed Brown   switch (testNum) {
564c4762a1bSJed Brown   case 0:
56563a3b9bcSJacob Faibussowitsch     PetscCheck(size == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 2 processes", testNum);
566c4762a1bSJed Brown     switch (rank) {
5679371c9d4SSatish Balay     case 0: {
568c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 3, numCorners = 4;
569a4a685f2SJacob Faibussowitsch       const PetscInt cells[4]            = {0, 1, 2, 3};
570c4762a1bSJed Brown       PetscReal      coords[6]           = {-0.5, 0.0, 0.0, 0.0, 0.0, 1.0};
571c4762a1bSJed Brown       PetscInt       markerPoints[4 * 2] = {1, 1, 2, 1, 3, 1, 4, 1};
572c4762a1bSJed Brown 
5739566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5749566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5759371c9d4SSatish Balay     } break;
5769371c9d4SSatish Balay     case 1: {
577c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 3, numCorners = 4;
578a4a685f2SJacob Faibussowitsch       const PetscInt cells[4]            = {1, 4, 5, 2};
579c4762a1bSJed Brown       PetscReal      coords[6]           = {-0.5, 1.0, 0.5, 0.0, 0.5, 1.0};
580c4762a1bSJed Brown       PetscInt       markerPoints[4 * 2] = {1, 1, 2, 1, 3, 1, 4, 1};
581c4762a1bSJed Brown 
5829566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5839566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5849371c9d4SSatish Balay     } break;
58598921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
586c4762a1bSJed Brown     }
587c4762a1bSJed Brown     break;
58863a3b9bcSJacob Faibussowitsch   default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %" PetscInt_FMT, testNum);
589c4762a1bSJed Brown   }
590c4762a1bSJed Brown   PetscFunctionReturn(0);
591c4762a1bSJed Brown }
592c4762a1bSJed Brown 
5939371c9d4SSatish Balay static PetscErrorCode CreateHex_3D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) {
594c4762a1bSJed Brown   PetscInt    testNum = user->testNum, p;
595c4762a1bSJed Brown   PetscMPIInt rank, size;
596c4762a1bSJed Brown 
597c4762a1bSJed Brown   PetscFunctionBegin;
5989566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
600c4762a1bSJed Brown   switch (testNum) {
601c4762a1bSJed Brown   case 0:
60263a3b9bcSJacob Faibussowitsch     PetscCheck(size == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 2 processes", testNum);
603c4762a1bSJed Brown     switch (rank) {
6049371c9d4SSatish Balay     case 0: {
605c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 6, numCorners = 8;
606a4a685f2SJacob Faibussowitsch       const PetscInt cells[8]            = {0, 3, 2, 1, 4, 5, 6, 7};
607c4762a1bSJed Brown       PetscReal      coords[6 * 3]       = {-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.5, 1.0, 0.0, -0.5, 0.0, 1.0, 0.0, 0.0, 1.0};
608c4762a1bSJed Brown       PetscInt       markerPoints[8 * 2] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1};
609c4762a1bSJed Brown 
6109566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
6119566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
6129371c9d4SSatish Balay     } break;
6139371c9d4SSatish Balay     case 1: {
614c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 6, numCorners = 8;
615a4a685f2SJacob Faibussowitsch       const PetscInt cells[8]            = {1, 2, 9, 8, 5, 10, 11, 6};
616c4762a1bSJed Brown       PetscReal      coords[6 * 3]       = {0.0, 1.0, 1.0, -0.5, 1.0, 1.0, 0.5, 0.0, 0.0, 0.5, 1.0, 0.0, 0.5, 0.0, 1.0, 0.5, 1.0, 1.0};
617c4762a1bSJed Brown       PetscInt       markerPoints[8 * 2] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1};
618c4762a1bSJed Brown 
6199566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
6209566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
6219371c9d4SSatish Balay     } break;
62298921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
623c4762a1bSJed Brown     }
624c4762a1bSJed Brown     break;
62563a3b9bcSJacob Faibussowitsch   default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %" PetscInt_FMT, testNum);
626c4762a1bSJed Brown   }
627c4762a1bSJed Brown   PetscFunctionReturn(0);
628c4762a1bSJed Brown }
629c4762a1bSJed Brown 
6309371c9d4SSatish Balay static PetscErrorCode CustomView(DM dm, PetscViewer v) {
631c4762a1bSJed Brown   DMPlexInterpolatedFlag interpolated;
632c4762a1bSJed Brown   PetscBool              distributed;
633c4762a1bSJed Brown 
634c4762a1bSJed Brown   PetscFunctionBegin;
6359566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
6369566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpolated));
6379566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(v, "DMPlexIsDistributed: %s\n", PetscBools[distributed]));
6389566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(v, "DMPlexIsInterpolatedCollective: %s\n", DMPlexInterpolatedFlags[interpolated]));
639c4762a1bSJed Brown   PetscFunctionReturn(0);
640c4762a1bSJed Brown }
641c4762a1bSJed Brown 
6429371c9d4SSatish Balay static PetscErrorCode CreateMeshFromFile(MPI_Comm comm, AppCtx *user, DM *dm, DM *serialDM) {
643c4762a1bSJed Brown   const char *filename     = user->filename;
644c4762a1bSJed Brown   PetscBool   testHeavy    = user->testHeavy;
645c4762a1bSJed Brown   PetscBool   interpCreate = user->interpolate == CREATE ? PETSC_TRUE : PETSC_FALSE;
646c4762a1bSJed Brown   PetscBool   distributed  = PETSC_FALSE;
647c4762a1bSJed Brown 
648c4762a1bSJed Brown   PetscFunctionBegin;
649c4762a1bSJed Brown   *serialDM = NULL;
6509566063dSJacob Faibussowitsch   if (testHeavy && interpCreate) PetscCall(DMPlexSetOrientInterface_Private(NULL, PETSC_FALSE));
6519566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePush(stage[0]));
6529566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromFile(comm, filename, "ex18_plex", interpCreate, dm)); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */
6539566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePop());
6549566063dSJacob Faibussowitsch   if (testHeavy && interpCreate) PetscCall(DMPlexSetOrientInterface_Private(NULL, PETSC_TRUE));
6559566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(*dm, &distributed));
6569566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(comm, "DMPlexCreateFromFile produced %s mesh.\n", distributed ? "distributed" : "serial"));
657c4762a1bSJed Brown   if (testHeavy && distributed) {
6589566063dSJacob Faibussowitsch     PetscCall(PetscOptionsSetValue(NULL, "-dm_plex_hdf5_force_sequential", NULL));
6599566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(comm, filename, "ex18_plex", interpCreate, serialDM));
6609566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(*serialDM, &distributed));
66128b400f6SJacob Faibussowitsch     PetscCheck(!distributed, comm, PETSC_ERR_PLIB, "unable to create a serial DM from file");
662c4762a1bSJed Brown   }
6639566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(*dm, &user->dim));
664c4762a1bSJed Brown   PetscFunctionReturn(0);
665c4762a1bSJed Brown }
666c4762a1bSJed Brown 
6679371c9d4SSatish Balay static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) {
668c4762a1bSJed Brown   PetscPartitioner part;
669c4762a1bSJed Brown   PortableBoundary boundary       = NULL;
670c4762a1bSJed Brown   DM               serialDM       = NULL;
671c4762a1bSJed Brown   PetscBool        cellSimplex    = user->cellSimplex;
672c4762a1bSJed Brown   PetscBool        useGenerator   = user->useGenerator;
673c4762a1bSJed Brown   PetscBool        interpCreate   = user->interpolate == CREATE ? PETSC_TRUE : PETSC_FALSE;
674c4762a1bSJed Brown   PetscBool        interpSerial   = user->interpolate == AFTER_CREATE ? PETSC_TRUE : PETSC_FALSE;
675c4762a1bSJed Brown   PetscBool        interpParallel = user->interpolate == AFTER_DISTRIBUTE ? PETSC_TRUE : PETSC_FALSE;
676c4762a1bSJed Brown   PetscBool        testHeavy      = user->testHeavy;
677c4762a1bSJed Brown   PetscMPIInt      rank;
678c4762a1bSJed Brown 
679c4762a1bSJed Brown   PetscFunctionBegin;
6809566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
681c4762a1bSJed Brown   if (user->filename[0]) {
6829566063dSJacob Faibussowitsch     PetscCall(CreateMeshFromFile(comm, user, dm, &serialDM));
683c4762a1bSJed Brown   } else if (useGenerator) {
6849566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePush(stage[0]));
6859566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateBoxMesh(comm, user->dim, cellSimplex, user->faces, NULL, NULL, NULL, interpCreate, dm));
6869566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePop());
687c4762a1bSJed Brown   } else {
6889566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePush(stage[0]));
689c4762a1bSJed Brown     switch (user->dim) {
6909371c9d4SSatish Balay     case 1: PetscCall(CreateMesh_1D(comm, interpCreate, user, dm)); break;
691c4762a1bSJed Brown     case 2:
692c4762a1bSJed Brown       if (cellSimplex) {
6939566063dSJacob Faibussowitsch         PetscCall(CreateSimplex_2D(comm, interpCreate, user, dm));
694c4762a1bSJed Brown       } else {
6959566063dSJacob Faibussowitsch         PetscCall(CreateQuad_2D(comm, interpCreate, user, dm));
696c4762a1bSJed Brown       }
697c4762a1bSJed Brown       break;
698c4762a1bSJed Brown     case 3:
699c4762a1bSJed Brown       if (cellSimplex) {
7009566063dSJacob Faibussowitsch         PetscCall(CreateSimplex_3D(comm, interpCreate, user, dm));
701c4762a1bSJed Brown       } else {
7029566063dSJacob Faibussowitsch         PetscCall(CreateHex_3D(comm, interpCreate, user, dm));
703c4762a1bSJed Brown       }
704c4762a1bSJed Brown       break;
7059371c9d4SSatish Balay     default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, user->dim);
706c4762a1bSJed Brown     }
7079566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePop());
708c4762a1bSJed Brown   }
70963a3b9bcSJacob Faibussowitsch   PetscCheck(user->ncoords % user->dim == 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "length of coordinates array %" PetscInt_FMT " must be divisable by spatial dimension %" PetscInt_FMT, user->ncoords, user->dim);
7109566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*dm, "Original Mesh"));
7119566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(*dm, NULL, "-orig_dm_view"));
712c4762a1bSJed Brown 
713c4762a1bSJed Brown   if (interpSerial) {
714c4762a1bSJed Brown     DM idm;
715c4762a1bSJed Brown 
7169566063dSJacob Faibussowitsch     if (testHeavy) PetscCall(DMPlexSetOrientInterface_Private(*dm, PETSC_FALSE));
7179566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePush(stage[2]));
7189566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm)); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */
7199566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePop());
7209566063dSJacob Faibussowitsch     if (testHeavy) PetscCall(DMPlexSetOrientInterface_Private(*dm, PETSC_TRUE));
7219566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
722c4762a1bSJed Brown     *dm = idm;
7239566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*dm, "Interpolated Mesh"));
7249566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(*dm, NULL, "-intp_dm_view"));
725c4762a1bSJed Brown   }
726c4762a1bSJed Brown 
727c4762a1bSJed Brown   /* Set partitioner options */
7289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPartitioner(*dm, &part));
729c4762a1bSJed Brown   if (part) {
7309566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetType(part, PETSCPARTITIONERSIMPLE));
7319566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
732c4762a1bSJed Brown   }
733c4762a1bSJed Brown 
7349566063dSJacob Faibussowitsch   if (user->customView) PetscCall(CustomView(*dm, PETSC_VIEWER_STDOUT_(comm)));
735c4762a1bSJed Brown   if (testHeavy) {
736c4762a1bSJed Brown     PetscBool distributed;
737c4762a1bSJed Brown 
7389566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(*dm, &distributed));
739c4762a1bSJed Brown     if (!serialDM && !distributed) {
740c4762a1bSJed Brown       serialDM = *dm;
7419566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)*dm));
742c4762a1bSJed Brown     }
743*48a46eb9SPierre Jolivet     if (serialDM) PetscCall(DMPlexGetExpandedBoundary_Private(serialDM, &boundary));
744c4762a1bSJed Brown     if (boundary) {
745c4762a1bSJed Brown       /* check DM which has been created in parallel and already interpolated */
7469566063dSJacob Faibussowitsch       PetscCall(DMPlexCheckPointSFHeavy(*dm, boundary));
747c4762a1bSJed Brown     }
748c4762a1bSJed Brown     /* Orient interface because it could be deliberately skipped above. It is idempotent. */
7499566063dSJacob Faibussowitsch     PetscCall(DMPlexOrientInterface_Internal(*dm));
750c4762a1bSJed Brown   }
751c4762a1bSJed Brown   if (user->distribute) {
752c4762a1bSJed Brown     DM pdm = NULL;
753c4762a1bSJed Brown 
754c4762a1bSJed Brown     /* Redistribute mesh over processes using that partitioner */
7559566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePush(stage[1]));
7569566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(*dm, 0, NULL, &pdm));
7579566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePop());
758c4762a1bSJed Brown     if (pdm) {
7599566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
760c4762a1bSJed Brown       *dm = pdm;
7619566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)*dm, "Redistributed Mesh"));
7629566063dSJacob Faibussowitsch       PetscCall(DMViewFromOptions(*dm, NULL, "-dist_dm_view"));
763c4762a1bSJed Brown     }
764c4762a1bSJed Brown 
765c4762a1bSJed Brown     if (interpParallel) {
766c4762a1bSJed Brown       DM idm;
767c4762a1bSJed Brown 
7689566063dSJacob Faibussowitsch       if (testHeavy) PetscCall(DMPlexSetOrientInterface_Private(*dm, PETSC_FALSE));
7699566063dSJacob Faibussowitsch       PetscCall(PetscLogStagePush(stage[2]));
7709566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm)); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */
7719566063dSJacob Faibussowitsch       PetscCall(PetscLogStagePop());
7729566063dSJacob Faibussowitsch       if (testHeavy) PetscCall(DMPlexSetOrientInterface_Private(*dm, PETSC_TRUE));
7739566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
774c4762a1bSJed Brown       *dm = idm;
7759566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)*dm, "Interpolated Redistributed Mesh"));
7769566063dSJacob Faibussowitsch       PetscCall(DMViewFromOptions(*dm, NULL, "-intp_dm_view"));
777c4762a1bSJed Brown     }
778c4762a1bSJed Brown   }
779c4762a1bSJed Brown   if (testHeavy) {
7801baa6e33SBarry Smith     if (boundary) PetscCall(DMPlexCheckPointSFHeavy(*dm, boundary));
781c4762a1bSJed Brown     /* Orient interface because it could be deliberately skipped above. It is idempotent. */
7829566063dSJacob Faibussowitsch     PetscCall(DMPlexOrientInterface_Internal(*dm));
783c4762a1bSJed Brown   }
784c4762a1bSJed Brown 
7859566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*dm, "Parallel Mesh"));
7869566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE));
7879566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(*dm));
7889566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view"));
789c4762a1bSJed Brown 
7909566063dSJacob Faibussowitsch   if (user->customView) PetscCall(CustomView(*dm, PETSC_VIEWER_STDOUT_(comm)));
7919566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&serialDM));
7929566063dSJacob Faibussowitsch   PetscCall(PortableBoundaryDestroy(&boundary));
793c4762a1bSJed Brown   PetscFunctionReturn(0);
794c4762a1bSJed Brown }
795c4762a1bSJed Brown 
796d3e1f4ccSVaclav Hapla #define ps2d(number) ((double)PetscRealPart(number))
7979371c9d4SSatish Balay static inline PetscErrorCode coord2str(char buf[], size_t len, PetscInt dim, const PetscScalar coords[], PetscReal tol) {
798c4762a1bSJed Brown   PetscFunctionBegin;
79908401ef6SPierre Jolivet   PetscCheck(dim <= 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "dim must be less than or equal 3");
800c4762a1bSJed Brown   if (tol >= 1e-3) {
801c4762a1bSJed Brown     switch (dim) {
8029566063dSJacob Faibussowitsch     case 1: PetscCall(PetscSNPrintf(buf, len, "(%12.3f)", ps2d(coords[0])));
8039566063dSJacob Faibussowitsch     case 2: PetscCall(PetscSNPrintf(buf, len, "(%12.3f, %12.3f)", ps2d(coords[0]), ps2d(coords[1])));
8049566063dSJacob Faibussowitsch     case 3: PetscCall(PetscSNPrintf(buf, len, "(%12.3f, %12.3f, %12.3f)", ps2d(coords[0]), ps2d(coords[1]), ps2d(coords[2])));
805c4762a1bSJed Brown     }
806c4762a1bSJed Brown   } else {
807c4762a1bSJed Brown     switch (dim) {
8089566063dSJacob Faibussowitsch     case 1: PetscCall(PetscSNPrintf(buf, len, "(%12.6f)", ps2d(coords[0])));
8099566063dSJacob Faibussowitsch     case 2: PetscCall(PetscSNPrintf(buf, len, "(%12.6f, %12.6f)", ps2d(coords[0]), ps2d(coords[1])));
8109566063dSJacob Faibussowitsch     case 3: PetscCall(PetscSNPrintf(buf, len, "(%12.6f, %12.6f, %12.6f)", ps2d(coords[0]), ps2d(coords[1]), ps2d(coords[2])));
811c4762a1bSJed Brown     }
812c4762a1bSJed Brown   }
813c4762a1bSJed Brown   PetscFunctionReturn(0);
814c4762a1bSJed Brown }
815c4762a1bSJed Brown 
8169371c9d4SSatish Balay static PetscErrorCode ViewVerticesFromCoords(DM dm, Vec coordsVec, PetscReal tol, PetscViewer viewer) {
817d3e1f4ccSVaclav Hapla   PetscInt           dim, i, npoints;
818d3e1f4ccSVaclav Hapla   IS                 pointsIS;
819d3e1f4ccSVaclav Hapla   const PetscInt    *points;
820d3e1f4ccSVaclav Hapla   const PetscScalar *coords;
821c4762a1bSJed Brown   char               coordstr[128];
822c4762a1bSJed Brown   MPI_Comm           comm;
823c4762a1bSJed Brown   PetscMPIInt        rank;
824c4762a1bSJed Brown 
825c4762a1bSJed Brown   PetscFunctionBegin;
8269566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8289566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8299566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8309566063dSJacob Faibussowitsch   PetscCall(DMPlexFindVertices(dm, coordsVec, tol, &pointsIS));
8319566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(pointsIS, &points));
8329566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(pointsIS, &npoints));
8339566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordsVec, &coords));
834c4762a1bSJed Brown   for (i = 0; i < npoints; i++) {
8359566063dSJacob Faibussowitsch     PetscCall(coord2str(coordstr, sizeof(coordstr), dim, &coords[i * dim], tol));
8369566063dSJacob Faibussowitsch     if (rank == 0 && i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "-----\n"));
83763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %s --> points[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, coordstr, i, points[i]));
8389566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
839c4762a1bSJed Brown   }
8409566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8419566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordsVec, &coords));
8429566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(pointsIS, &points));
8439566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pointsIS));
844c4762a1bSJed Brown   PetscFunctionReturn(0);
845c4762a1bSJed Brown }
846c4762a1bSJed Brown 
8479371c9d4SSatish Balay static PetscErrorCode TestExpandPoints(DM dm, AppCtx *user) {
848c4762a1bSJed Brown   IS            is;
849c4762a1bSJed Brown   PetscSection *sects;
850c4762a1bSJed Brown   IS           *iss;
851c4762a1bSJed Brown   PetscInt      d, depth;
852c4762a1bSJed Brown   PetscMPIInt   rank;
853c4762a1bSJed Brown   PetscViewer   viewer = PETSC_VIEWER_STDOUT_WORLD, sviewer;
854c4762a1bSJed Brown 
855c4762a1bSJed Brown   PetscFunctionBegin;
8569566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
857dd400576SPatrick Sanan   if (user->testExpandPointsEmpty && rank == 0) {
8589566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, &is));
859c4762a1bSJed Brown   } else {
8609566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, user->nPointsToExpand, user->pointsToExpand, PETSC_USE_POINTER, &is));
861c4762a1bSJed Brown   }
8629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, is, &depth, &iss, &sects));
8639566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
8649566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(sviewer, "[%d] ==========================\n", rank));
865c4762a1bSJed Brown   for (d = depth - 1; d >= 0; d--) {
866c4762a1bSJed Brown     IS        checkIS;
867c4762a1bSJed Brown     PetscBool flg;
868c4762a1bSJed Brown 
86963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(sviewer, "depth %" PetscInt_FMT " ---------------\n", d));
8709566063dSJacob Faibussowitsch     PetscCall(PetscSectionView(sects[d], sviewer));
8719566063dSJacob Faibussowitsch     PetscCall(ISView(iss[d], sviewer));
872c4762a1bSJed Brown     /* check reverse operation */
873c4762a1bSJed Brown     if (d < depth - 1) {
8749566063dSJacob Faibussowitsch       PetscCall(DMPlexExpandedConesToFaces_Private(dm, iss[d], sects[d], &checkIS));
8759566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(checkIS, iss[d + 1], &flg));
87628b400f6SJacob Faibussowitsch       PetscCheck(flg, PetscObjectComm((PetscObject)checkIS), PETSC_ERR_PLIB, "DMPlexExpandedConesToFaces_Private produced wrong IS");
8779566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&checkIS));
878c4762a1bSJed Brown     }
879c4762a1bSJed Brown   }
8809566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
8819566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
8829566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, is, &depth, &iss, &sects));
8839566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
884c4762a1bSJed Brown   PetscFunctionReturn(0);
885c4762a1bSJed Brown }
886c4762a1bSJed Brown 
8879371c9d4SSatish Balay static PetscErrorCode DMPlexExpandedConesToFaces_Private(DM dm, IS is, PetscSection section, IS *newis) {
888c4762a1bSJed Brown   PetscInt        n, n1, ncone, numCoveredPoints, o, p, q, start, end;
889c4762a1bSJed Brown   const PetscInt *coveredPoints;
890c4762a1bSJed Brown   const PetscInt *arr, *cone;
891c4762a1bSJed Brown   PetscInt       *newarr;
892c4762a1bSJed Brown 
893c4762a1bSJed Brown   PetscFunctionBegin;
8949566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
8959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n1));
8969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &start, &end));
89763a3b9bcSJacob Faibussowitsch   PetscCheck(n == n1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "IS size = %" PetscInt_FMT " != %" PetscInt_FMT " = section storage size", n, n1);
8989566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &arr));
8999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(end - start, &newarr));
900c4762a1bSJed Brown   for (q = start; q < end; q++) {
9019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, q, &ncone));
9029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, q, &o));
903c4762a1bSJed Brown     cone = &arr[o];
904c4762a1bSJed Brown     if (ncone == 1) {
905c4762a1bSJed Brown       numCoveredPoints = 1;
906c4762a1bSJed Brown       p                = cone[0];
907c4762a1bSJed Brown     } else {
908c4762a1bSJed Brown       PetscInt i;
909c4762a1bSJed Brown       p = PETSC_MAX_INT;
9109371c9d4SSatish Balay       for (i = 0; i < ncone; i++)
9119371c9d4SSatish Balay         if (cone[i] < 0) {
9129371c9d4SSatish Balay           p = -1;
9139371c9d4SSatish Balay           break;
9149371c9d4SSatish Balay         }
915c4762a1bSJed Brown       if (p >= 0) {
9169566063dSJacob Faibussowitsch         PetscCall(DMPlexGetJoin(dm, ncone, cone, &numCoveredPoints, &coveredPoints));
91763a3b9bcSJacob Faibussowitsch         PetscCheck(numCoveredPoints <= 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "more than one covered points for section point %" PetscInt_FMT, q);
918c4762a1bSJed Brown         if (numCoveredPoints) p = coveredPoints[0];
919c4762a1bSJed Brown         else p = -2;
9209566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(dm, ncone, cone, &numCoveredPoints, &coveredPoints));
921c4762a1bSJed Brown       }
922c4762a1bSJed Brown     }
923c4762a1bSJed Brown     newarr[q - start] = p;
924c4762a1bSJed Brown   }
9259566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &arr));
9269566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, end - start, newarr, PETSC_OWN_POINTER, newis));
927c4762a1bSJed Brown   PetscFunctionReturn(0);
928c4762a1bSJed Brown }
929c4762a1bSJed Brown 
9309371c9d4SSatish Balay static PetscErrorCode DMPlexExpandedVerticesToFaces_Private(DM dm, IS boundary_expanded_is, PetscInt depth, PetscSection sections[], IS *boundary_is) {
931c4762a1bSJed Brown   PetscInt d;
932c4762a1bSJed Brown   IS       is, newis;
933c4762a1bSJed Brown 
934c4762a1bSJed Brown   PetscFunctionBegin;
935c4762a1bSJed Brown   is = boundary_expanded_is;
9369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
937c4762a1bSJed Brown   for (d = 0; d < depth - 1; ++d) {
9389566063dSJacob Faibussowitsch     PetscCall(DMPlexExpandedConesToFaces_Private(dm, is, sections[d], &newis));
9399566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
940c4762a1bSJed Brown     is = newis;
941c4762a1bSJed Brown   }
942c4762a1bSJed Brown   *boundary_is = is;
943c4762a1bSJed Brown   PetscFunctionReturn(0);
944c4762a1bSJed Brown }
945c4762a1bSJed Brown 
9469371c9d4SSatish Balay #define CHKERRQI(incall, ierr) \
9479371c9d4SSatish Balay   if (ierr) { incall = PETSC_FALSE; }
948c4762a1bSJed Brown 
9499371c9d4SSatish Balay static PetscErrorCode DMLabelViewFromOptionsOnComm_Private(DMLabel label, const char optionname[], MPI_Comm comm) {
950c4762a1bSJed Brown   PetscViewer       viewer;
951c4762a1bSJed Brown   PetscBool         flg;
952c4762a1bSJed Brown   static PetscBool  incall = PETSC_FALSE;
953c4762a1bSJed Brown   PetscViewerFormat format;
954c4762a1bSJed Brown 
955c4762a1bSJed Brown   PetscFunctionBegin;
956c4762a1bSJed Brown   if (incall) PetscFunctionReturn(0);
957c4762a1bSJed Brown   incall = PETSC_TRUE;
9585f80ce2aSJacob Faibussowitsch   CHKERRQI(incall, PetscOptionsGetViewer(comm, ((PetscObject)label)->options, ((PetscObject)label)->prefix, optionname, &viewer, &format, &flg));
959c4762a1bSJed Brown   if (flg) {
9605f80ce2aSJacob Faibussowitsch     CHKERRQI(incall, PetscViewerPushFormat(viewer, format));
9615f80ce2aSJacob Faibussowitsch     CHKERRQI(incall, DMLabelView(label, viewer));
9625f80ce2aSJacob Faibussowitsch     CHKERRQI(incall, PetscViewerPopFormat(viewer));
9635f80ce2aSJacob Faibussowitsch     CHKERRQI(incall, PetscViewerDestroy(&viewer));
964c4762a1bSJed Brown   }
965c4762a1bSJed Brown   incall = PETSC_FALSE;
966c4762a1bSJed Brown   PetscFunctionReturn(0);
967c4762a1bSJed Brown }
968c4762a1bSJed Brown 
969c4762a1bSJed Brown /* TODO: this is hotfixing DMLabelGetStratumIS() - it should be fixed systematically instead */
9709371c9d4SSatish Balay static inline PetscErrorCode DMLabelGetStratumISOnComm_Private(DMLabel label, PetscInt value, MPI_Comm comm, IS *is) {
971c4762a1bSJed Brown   IS tmpis;
972c4762a1bSJed Brown 
973c4762a1bSJed Brown   PetscFunctionBegin;
9749566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, &tmpis));
9759566063dSJacob Faibussowitsch   if (!tmpis) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, &tmpis));
9769566063dSJacob Faibussowitsch   PetscCall(ISOnComm(tmpis, comm, PETSC_COPY_VALUES, is));
9779566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&tmpis));
978c4762a1bSJed Brown   PetscFunctionReturn(0);
979c4762a1bSJed Brown }
980c4762a1bSJed Brown 
981c4762a1bSJed Brown /* currently only for simple PetscSection without fields or constraints */
9829371c9d4SSatish Balay static PetscErrorCode PetscSectionReplicate_Private(MPI_Comm comm, PetscMPIInt rootrank, PetscSection sec0, PetscSection *secout) {
983c4762a1bSJed Brown   PetscSection sec;
984c4762a1bSJed Brown   PetscInt     chart[2], p;
985c4762a1bSJed Brown   PetscInt    *dofarr;
986c4762a1bSJed Brown   PetscMPIInt  rank;
987c4762a1bSJed Brown 
988c4762a1bSJed Brown   PetscFunctionBegin;
9899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
990*48a46eb9SPierre Jolivet   if (rank == rootrank) PetscCall(PetscSectionGetChart(sec0, &chart[0], &chart[1]));
9919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(chart, 2, MPIU_INT, rootrank, comm));
9929566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(chart[1] - chart[0], &dofarr));
993c4762a1bSJed Brown   if (rank == rootrank) {
994*48a46eb9SPierre Jolivet     for (p = chart[0]; p < chart[1]; p++) PetscCall(PetscSectionGetDof(sec0, p, &dofarr[p - chart[0]]));
995c4762a1bSJed Brown   }
9969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(dofarr, chart[1] - chart[0], MPIU_INT, rootrank, comm));
9979566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &sec));
9989566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(sec, chart[0], chart[1]));
999*48a46eb9SPierre Jolivet   for (p = chart[0]; p < chart[1]; p++) PetscCall(PetscSectionSetDof(sec, p, dofarr[p - chart[0]]));
10009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(sec));
10019566063dSJacob Faibussowitsch   PetscCall(PetscFree(dofarr));
1002c4762a1bSJed Brown   *secout = sec;
1003c4762a1bSJed Brown   PetscFunctionReturn(0);
1004c4762a1bSJed Brown }
1005c4762a1bSJed Brown 
10069371c9d4SSatish Balay static PetscErrorCode DMPlexExpandedVerticesCoordinatesToFaces_Private(DM ipdm, PortableBoundary bnd, IS *face_is) {
1007c4762a1bSJed Brown   IS faces_expanded_is;
1008c4762a1bSJed Brown 
1009c4762a1bSJed Brown   PetscFunctionBegin;
10109566063dSJacob Faibussowitsch   PetscCall(DMPlexFindVertices(ipdm, bnd->coordinates, 0.0, &faces_expanded_is));
10119566063dSJacob Faibussowitsch   PetscCall(DMPlexExpandedVerticesToFaces_Private(ipdm, faces_expanded_is, bnd->depth, bnd->sections, face_is));
10129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&faces_expanded_is));
1013c4762a1bSJed Brown   PetscFunctionReturn(0);
1014c4762a1bSJed Brown }
1015c4762a1bSJed Brown 
1016c4762a1bSJed Brown /* hack disabling DMPlexOrientInterface() call in DMPlexInterpolate() via -dm_plex_interpolate_orient_interfaces option */
10179371c9d4SSatish Balay static PetscErrorCode DMPlexSetOrientInterface_Private(DM dm, PetscBool enable) {
1018c4762a1bSJed Brown   PetscOptions     options = NULL;
1019c4762a1bSJed Brown   const char      *prefix  = NULL;
1020c4762a1bSJed Brown   const char       opt[]   = "-dm_plex_interpolate_orient_interfaces";
1021c4762a1bSJed Brown   char             prefix_opt[512];
1022c4762a1bSJed Brown   PetscBool        flg, set;
1023c4762a1bSJed Brown   static PetscBool wasSetTrue = PETSC_FALSE;
1024c4762a1bSJed Brown 
1025c4762a1bSJed Brown   PetscFunctionBegin;
1026c4762a1bSJed Brown   if (dm) {
10279566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
1028c4762a1bSJed Brown     options = ((PetscObject)dm)->options;
1029c4762a1bSJed Brown   }
10309566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(prefix_opt, "-"));
10319566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(prefix_opt, prefix, sizeof(prefix_opt)));
10329566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(prefix_opt, &opt[1], sizeof(prefix_opt)));
10339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(options, prefix, opt, &flg, &set));
1034c4762a1bSJed Brown   if (!enable) {
1035c4762a1bSJed Brown     if (set && flg) wasSetTrue = PETSC_TRUE;
10369566063dSJacob Faibussowitsch     PetscCall(PetscOptionsSetValue(options, prefix_opt, "0"));
1037c4762a1bSJed Brown   } else if (set && !flg) {
1038c4762a1bSJed Brown     if (wasSetTrue) {
10399566063dSJacob Faibussowitsch       PetscCall(PetscOptionsSetValue(options, prefix_opt, "1"));
1040c4762a1bSJed Brown     } else {
1041c4762a1bSJed Brown       /* default is PETSC_TRUE */
10429566063dSJacob Faibussowitsch       PetscCall(PetscOptionsClearValue(options, prefix_opt));
1043c4762a1bSJed Brown     }
1044c4762a1bSJed Brown     wasSetTrue = PETSC_FALSE;
1045c4762a1bSJed Brown   }
104676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
10479566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(options, prefix, opt, &flg, &set));
10481dca8a05SBarry Smith     PetscCheck(!set || flg == enable, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "PetscOptionsSetValue did not have the desired effect");
1049c4762a1bSJed Brown   }
1050c4762a1bSJed Brown   PetscFunctionReturn(0);
1051c4762a1bSJed Brown }
1052c4762a1bSJed Brown 
1053c4762a1bSJed Brown /* get coordinate description of the whole-domain boundary */
10549371c9d4SSatish Balay static PetscErrorCode DMPlexGetExpandedBoundary_Private(DM dm, PortableBoundary *boundary) {
1055c4762a1bSJed Brown   PortableBoundary       bnd0, bnd;
1056c4762a1bSJed Brown   MPI_Comm               comm;
1057c4762a1bSJed Brown   DM                     idm;
1058c4762a1bSJed Brown   DMLabel                label;
1059c4762a1bSJed Brown   PetscInt               d;
1060c4762a1bSJed Brown   const char             boundaryName[] = "DMPlexDistributeInterpolateMarkInterface_boundary";
1061c4762a1bSJed Brown   IS                     boundary_is;
1062c4762a1bSJed Brown   IS                    *boundary_expanded_iss;
1063c4762a1bSJed Brown   PetscMPIInt            rootrank = 0;
1064c4762a1bSJed Brown   PetscMPIInt            rank, size;
1065c4762a1bSJed Brown   PetscInt               value = 1;
1066c4762a1bSJed Brown   DMPlexInterpolatedFlag intp;
1067c4762a1bSJed Brown   PetscBool              flg;
1068c4762a1bSJed Brown 
1069c4762a1bSJed Brown   PetscFunctionBegin;
10709566063dSJacob Faibussowitsch   PetscCall(PetscNew(&bnd));
10719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
10729566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
10749566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
107528b400f6SJacob Faibussowitsch   PetscCheck(!flg, comm, PETSC_ERR_ARG_WRONG, "serial DM (all points on one rank) needed");
1076c4762a1bSJed Brown 
1077c4762a1bSJed Brown   /* interpolate serial DM if not yet interpolated */
10789566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(dm, &intp));
1079c4762a1bSJed Brown   if (intp == DMPLEX_INTERPOLATED_FULL) {
1080c4762a1bSJed Brown     idm = dm;
10819566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1082c4762a1bSJed Brown   } else {
10839566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
10849566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(idm, NULL, "-idm_view"));
1085c4762a1bSJed Brown   }
1086c4762a1bSJed Brown 
1087c4762a1bSJed Brown   /* mark whole-domain boundary of the serial DM */
10889566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, boundaryName, &label));
10899566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(idm, label));
10909566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(idm, value, label));
10919566063dSJacob Faibussowitsch   PetscCall(DMLabelViewFromOptionsOnComm_Private(label, "-idm_boundary_view", comm));
10929566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, &boundary_is));
1093c4762a1bSJed Brown 
1094c4762a1bSJed Brown   /* translate to coordinates */
10959566063dSJacob Faibussowitsch   PetscCall(PetscNew(&bnd0));
10969566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocalSetUp(idm));
1097c4762a1bSJed Brown   if (rank == rootrank) {
10989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeRecursive(idm, boundary_is, &bnd0->depth, &boundary_expanded_iss, &bnd0->sections));
10999566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocalTuple(dm, boundary_expanded_iss[0], NULL, &bnd0->coordinates));
1100c4762a1bSJed Brown     /* self-check */
1101c4762a1bSJed Brown     {
1102c4762a1bSJed Brown       IS is0;
11039566063dSJacob Faibussowitsch       PetscCall(DMPlexExpandedVerticesCoordinatesToFaces_Private(idm, bnd0, &is0));
11049566063dSJacob Faibussowitsch       PetscCall(ISEqual(is0, boundary_is, &flg));
110528b400f6SJacob Faibussowitsch       PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DMPlexExpandedVerticesCoordinatesToFaces_Private produced a wrong IS");
11069566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
1107c4762a1bSJed Brown     }
1108c4762a1bSJed Brown   } else {
11099566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, 0, &bnd0->coordinates));
1110c4762a1bSJed Brown   }
1111c4762a1bSJed Brown 
1112c4762a1bSJed Brown   {
1113c4762a1bSJed Brown     Vec        tmp;
1114c4762a1bSJed Brown     VecScatter sc;
1115c4762a1bSJed Brown     IS         xis;
1116c4762a1bSJed Brown     PetscInt   n;
1117c4762a1bSJed Brown 
1118c4762a1bSJed Brown     /* just convert seq vectors to mpi vector */
11199566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(bnd0->coordinates, &n));
11209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(&n, 1, MPIU_INT, rootrank, comm));
1121c4762a1bSJed Brown     if (rank == rootrank) {
11229566063dSJacob Faibussowitsch       PetscCall(VecCreateMPI(comm, n, n, &tmp));
1123c4762a1bSJed Brown     } else {
11249566063dSJacob Faibussowitsch       PetscCall(VecCreateMPI(comm, 0, n, &tmp));
1125c4762a1bSJed Brown     }
11269566063dSJacob Faibussowitsch     PetscCall(VecCopy(bnd0->coordinates, tmp));
11279566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&bnd0->coordinates));
1128c4762a1bSJed Brown     bnd0->coordinates = tmp;
1129c4762a1bSJed Brown 
1130c4762a1bSJed Brown     /* replicate coordinates from root rank to all ranks */
11319566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, n, n * size, &bnd->coordinates));
11329566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, n, 0, 1, &xis));
11339566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(bnd0->coordinates, xis, bnd->coordinates, NULL, &sc));
11349566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sc, bnd0->coordinates, bnd->coordinates, INSERT_VALUES, SCATTER_FORWARD));
11359566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sc, bnd0->coordinates, bnd->coordinates, INSERT_VALUES, SCATTER_FORWARD));
11369566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sc));
11379566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&xis));
1138c4762a1bSJed Brown   }
1139c4762a1bSJed Brown   bnd->depth = bnd0->depth;
11409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&bnd->depth, 1, MPIU_INT, rootrank, comm));
11419566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(bnd->depth, &bnd->sections));
1142*48a46eb9SPierre Jolivet   for (d = 0; d < bnd->depth; d++) PetscCall(PetscSectionReplicate_Private(comm, rootrank, (rank == rootrank) ? bnd0->sections[d] : NULL, &bnd->sections[d]));
1143c4762a1bSJed Brown 
1144*48a46eb9SPierre Jolivet   if (rank == rootrank) PetscCall(DMPlexRestoreConeRecursive(idm, boundary_is, &bnd0->depth, &boundary_expanded_iss, &bnd0->sections));
11459566063dSJacob Faibussowitsch   PetscCall(PortableBoundaryDestroy(&bnd0));
11469566063dSJacob Faibussowitsch   PetscCall(DMRemoveLabelBySelf(idm, &label, PETSC_TRUE));
11479566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
11489566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&boundary_is));
11499566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&idm));
1150c4762a1bSJed Brown   *boundary = bnd;
1151c4762a1bSJed Brown   PetscFunctionReturn(0);
1152c4762a1bSJed Brown }
1153c4762a1bSJed Brown 
1154c4762a1bSJed Brown /* get faces of inter-partition interface */
11559371c9d4SSatish Balay static PetscErrorCode DMPlexGetInterfaceFaces_Private(DM ipdm, IS boundary_faces_is, IS *interface_faces_is) {
1156c4762a1bSJed Brown   MPI_Comm               comm;
1157c4762a1bSJed Brown   DMLabel                label;
1158c4762a1bSJed Brown   IS                     part_boundary_faces_is;
1159c4762a1bSJed Brown   const char             partBoundaryName[] = "DMPlexDistributeInterpolateMarkInterface_partBoundary";
1160c4762a1bSJed Brown   PetscInt               value              = 1;
1161c4762a1bSJed Brown   DMPlexInterpolatedFlag intp;
1162c4762a1bSJed Brown 
1163c4762a1bSJed Brown   PetscFunctionBegin;
11649566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)ipdm, &comm));
11659566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(ipdm, &intp));
116608401ef6SPierre Jolivet   PetscCheck(intp == DMPLEX_INTERPOLATED_FULL, comm, PETSC_ERR_ARG_WRONG, "only for fully interpolated DMPlex");
1167c4762a1bSJed Brown 
1168c4762a1bSJed Brown   /* get ipdm partition boundary (partBoundary) */
11699566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, partBoundaryName, &label));
11709566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(ipdm, label));
11719566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(ipdm, value, label));
11729566063dSJacob Faibussowitsch   PetscCall(DMLabelViewFromOptionsOnComm_Private(label, "-ipdm_part_boundary_view", comm));
11739566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumISOnComm_Private(label, value, comm, &part_boundary_faces_is));
11749566063dSJacob Faibussowitsch   PetscCall(DMRemoveLabelBySelf(ipdm, &label, PETSC_TRUE));
11759566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
1176c4762a1bSJed Brown 
1177c4762a1bSJed Brown   /* remove ipdm whole-domain boundary (boundary_faces_is) from ipdm partition boundary (part_boundary_faces_is), resulting just in inter-partition interface */
11789566063dSJacob Faibussowitsch   PetscCall(ISDifference(part_boundary_faces_is, boundary_faces_is, interface_faces_is));
11799566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&part_boundary_faces_is));
1180c4762a1bSJed Brown   PetscFunctionReturn(0);
1181c4762a1bSJed Brown }
1182c4762a1bSJed Brown 
1183c4762a1bSJed Brown /* compute inter-partition interface including edges and vertices */
11849371c9d4SSatish Balay static PetscErrorCode DMPlexComputeCompleteInterface_Private(DM ipdm, IS interface_faces_is, IS *interface_is) {
1185c4762a1bSJed Brown   DMLabel                label;
1186c4762a1bSJed Brown   PetscInt               value           = 1;
1187c4762a1bSJed Brown   const char             interfaceName[] = "DMPlexDistributeInterpolateMarkInterface_interface";
1188c4762a1bSJed Brown   DMPlexInterpolatedFlag intp;
1189c4762a1bSJed Brown   MPI_Comm               comm;
1190c4762a1bSJed Brown 
1191c4762a1bSJed Brown   PetscFunctionBegin;
11929566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)ipdm, &comm));
11939566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(ipdm, &intp));
119408401ef6SPierre Jolivet   PetscCheck(intp == DMPLEX_INTERPOLATED_FULL, comm, PETSC_ERR_ARG_WRONG, "only for fully interpolated DMPlex");
1195c4762a1bSJed Brown 
11969566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, interfaceName, &label));
11979566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(ipdm, label));
11989566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, interface_faces_is));
11999566063dSJacob Faibussowitsch   PetscCall(DMLabelViewFromOptionsOnComm_Private(label, "-interface_faces_view", comm));
12009566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(ipdm, label));
12019566063dSJacob Faibussowitsch   PetscCall(DMLabelViewFromOptionsOnComm_Private(label, "-interface_view", comm));
12029566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumISOnComm_Private(label, value, comm, interface_is));
12039566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*interface_is, "interface_is"));
12049566063dSJacob Faibussowitsch   PetscCall(ISViewFromOptions(*interface_is, NULL, "-interface_is_view"));
12059566063dSJacob Faibussowitsch   PetscCall(DMRemoveLabelBySelf(ipdm, &label, PETSC_TRUE));
12069566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
1207c4762a1bSJed Brown   PetscFunctionReturn(0);
1208c4762a1bSJed Brown }
1209c4762a1bSJed Brown 
12109371c9d4SSatish Balay static PetscErrorCode PointSFGetOutwardInterfacePoints(PetscSF sf, IS *is) {
1211c4762a1bSJed Brown   PetscInt        n;
1212c4762a1bSJed Brown   const PetscInt *arr;
1213c4762a1bSJed Brown 
1214c4762a1bSJed Brown   PetscFunctionBegin;
12159566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &n, &arr, NULL));
12169566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)sf), n, arr, PETSC_USE_POINTER, is));
1217c4762a1bSJed Brown   PetscFunctionReturn(0);
1218c4762a1bSJed Brown }
1219c4762a1bSJed Brown 
12209371c9d4SSatish Balay static PetscErrorCode PointSFGetInwardInterfacePoints(PetscSF sf, IS *is) {
1221c4762a1bSJed Brown   PetscInt        n;
1222c4762a1bSJed Brown   const PetscInt *rootdegree;
1223c4762a1bSJed Brown   PetscInt       *arr;
1224c4762a1bSJed Brown 
1225c4762a1bSJed Brown   PetscFunctionBegin;
12269566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
12279566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
12289566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
12299566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeMultiRootOriginalNumbering(sf, rootdegree, &n, &arr));
12309566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)sf), n, arr, PETSC_OWN_POINTER, is));
1231c4762a1bSJed Brown   PetscFunctionReturn(0);
1232c4762a1bSJed Brown }
1233c4762a1bSJed Brown 
12349371c9d4SSatish Balay static PetscErrorCode PointSFGetInterfacePoints_Private(PetscSF pointSF, IS *is) {
1235c4762a1bSJed Brown   IS pointSF_out_is, pointSF_in_is;
1236c4762a1bSJed Brown 
1237c4762a1bSJed Brown   PetscFunctionBegin;
12389566063dSJacob Faibussowitsch   PetscCall(PointSFGetOutwardInterfacePoints(pointSF, &pointSF_out_is));
12399566063dSJacob Faibussowitsch   PetscCall(PointSFGetInwardInterfacePoints(pointSF, &pointSF_in_is));
12409566063dSJacob Faibussowitsch   PetscCall(ISExpand(pointSF_out_is, pointSF_in_is, is));
12419566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pointSF_out_is));
12429566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pointSF_in_is));
1243c4762a1bSJed Brown   PetscFunctionReturn(0);
1244c4762a1bSJed Brown }
1245c4762a1bSJed Brown 
12465f80ce2aSJacob Faibussowitsch #define CHKERRMY(ierr) PetscCheck(!ierr, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PointSF is wrong. Unable to show details!")
1247c4762a1bSJed Brown 
12489371c9d4SSatish Balay static PetscErrorCode ViewPointsWithType_Internal(DM dm, IS pointsIS, PetscViewer v) {
1249c4762a1bSJed Brown   DMLabel         label;
1250c4762a1bSJed Brown   PetscSection    coordsSection;
1251c4762a1bSJed Brown   Vec             coordsVec;
1252c4762a1bSJed Brown   PetscScalar    *coordsScalar;
1253c4762a1bSJed Brown   PetscInt        coneSize, depth, dim, i, p, npoints;
1254c4762a1bSJed Brown   const PetscInt *points;
1255c4762a1bSJed Brown 
1256c4762a1bSJed Brown   PetscFunctionBegin;
12579566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
12589566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordsSection));
12599566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsVec));
12609566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordsVec, &coordsScalar));
12619566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(pointsIS, &npoints));
12629566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(pointsIS, &points));
12639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
12649566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(v));
1265c4762a1bSJed Brown   for (i = 0; i < npoints; i++) {
1266c4762a1bSJed Brown     p = points[i];
12679566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &depth));
1268c4762a1bSJed Brown     if (!depth) {
1269d3e1f4ccSVaclav Hapla       PetscInt n, o;
1270c4762a1bSJed Brown       char     coordstr[128];
1271c4762a1bSJed Brown 
12729566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordsSection, p, &n));
12739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordsSection, p, &o));
12749566063dSJacob Faibussowitsch       PetscCall(coord2str(coordstr, sizeof(coordstr), n, &coordsScalar[o], 1.0));
127563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(v, "vertex %" PetscInt_FMT " w/ coordinates %s\n", p, coordstr));
1276c4762a1bSJed Brown     } else {
1277c4762a1bSJed Brown       char entityType[16];
1278c4762a1bSJed Brown 
1279c4762a1bSJed Brown       switch (depth) {
12809566063dSJacob Faibussowitsch       case 1: PetscCall(PetscStrcpy(entityType, "edge")); break;
12819566063dSJacob Faibussowitsch       case 2: PetscCall(PetscStrcpy(entityType, "face")); break;
12829566063dSJacob Faibussowitsch       case 3: PetscCall(PetscStrcpy(entityType, "cell")); break;
12832a27bf02SStefano Zampini       default: SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Only for depth <= 3");
1284c4762a1bSJed Brown       }
1285*48a46eb9SPierre Jolivet       if (depth == dim && dim < 3) PetscCall(PetscStrlcat(entityType, " (cell)", sizeof(entityType)));
128663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(v, "%s %" PetscInt_FMT "\n", entityType, p));
1287c4762a1bSJed Brown     }
12889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1289c4762a1bSJed Brown     if (coneSize) {
1290c4762a1bSJed Brown       const PetscInt *cone;
1291c4762a1bSJed Brown       IS              coneIS;
1292c4762a1bSJed Brown 
12939566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, p, &cone));
12949566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, coneSize, cone, PETSC_USE_POINTER, &coneIS));
12959566063dSJacob Faibussowitsch       PetscCall(ViewPointsWithType_Internal(dm, coneIS, v));
12969566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&coneIS));
1297c4762a1bSJed Brown     }
1298c4762a1bSJed Brown   }
12999566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(v));
13009566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordsVec, &coordsScalar));
13019566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(pointsIS, &points));
1302c4762a1bSJed Brown   PetscFunctionReturn(0);
1303c4762a1bSJed Brown }
1304c4762a1bSJed Brown 
13059371c9d4SSatish Balay static PetscErrorCode ViewPointsWithType(DM dm, IS points, PetscViewer v) {
1306c4762a1bSJed Brown   PetscBool   flg;
1307c4762a1bSJed Brown   PetscInt    npoints;
1308c4762a1bSJed Brown   PetscMPIInt rank;
1309c4762a1bSJed Brown 
1310c4762a1bSJed Brown   PetscFunctionBegin;
13119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &flg));
131228b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Only for ASCII viewer");
13139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank));
13149566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(v));
13159566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &npoints));
1316c4762a1bSJed Brown   if (npoints) {
13179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(v, "[%d] --------\n", rank));
13189566063dSJacob Faibussowitsch     PetscCall(ViewPointsWithType_Internal(dm, points, v));
1319c4762a1bSJed Brown   }
13209566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(v));
13219566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(v));
1322c4762a1bSJed Brown   PetscFunctionReturn(0);
1323c4762a1bSJed Brown }
1324c4762a1bSJed Brown 
13259371c9d4SSatish Balay static PetscErrorCode DMPlexComparePointSFWithInterface_Private(DM ipdm, IS interface_is) {
1326c4762a1bSJed Brown   PetscSF     pointsf;
1327c4762a1bSJed Brown   IS          pointsf_is;
1328c4762a1bSJed Brown   PetscBool   flg;
1329c4762a1bSJed Brown   MPI_Comm    comm;
1330c4762a1bSJed Brown   PetscMPIInt size;
1331c4762a1bSJed Brown 
1332c4762a1bSJed Brown   PetscFunctionBegin;
13339566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)ipdm, &comm));
13349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
13359566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(ipdm, &pointsf));
1336c4762a1bSJed Brown   if (pointsf) {
1337c4762a1bSJed Brown     PetscInt nroots;
13389566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(pointsf, &nroots, NULL, NULL, NULL));
1339c4762a1bSJed Brown     if (nroots < 0) pointsf = NULL; /* uninitialized SF */
1340c4762a1bSJed Brown   }
1341c4762a1bSJed Brown   if (!pointsf) {
1342c4762a1bSJed Brown     PetscInt N = 0;
13439566063dSJacob Faibussowitsch     if (interface_is) PetscCall(ISGetSize(interface_is, &N));
134428b400f6SJacob Faibussowitsch     PetscCheck(!N, comm, PETSC_ERR_PLIB, "interface_is should be NULL or empty for PointSF being NULL");
1345c4762a1bSJed Brown     PetscFunctionReturn(0);
1346c4762a1bSJed Brown   }
1347c4762a1bSJed Brown 
1348c4762a1bSJed Brown   /* get PointSF points as IS pointsf_is */
13499566063dSJacob Faibussowitsch   PetscCall(PointSFGetInterfacePoints_Private(pointsf, &pointsf_is));
1350c4762a1bSJed Brown 
1351c4762a1bSJed Brown   /* compare pointsf_is with interface_is */
13529566063dSJacob Faibussowitsch   PetscCall(ISEqual(interface_is, pointsf_is, &flg));
13539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &flg, 1, MPIU_BOOL, MPI_LAND, comm));
1354c4762a1bSJed Brown   if (!flg) {
1355c4762a1bSJed Brown     IS          pointsf_extra_is, pointsf_missing_is;
1356c4762a1bSJed Brown     PetscViewer errv = PETSC_VIEWER_STDERR_(comm);
13575f80ce2aSJacob Faibussowitsch     CHKERRMY(ISDifference(interface_is, pointsf_is, &pointsf_missing_is));
13585f80ce2aSJacob Faibussowitsch     CHKERRMY(ISDifference(pointsf_is, interface_is, &pointsf_extra_is));
13595f80ce2aSJacob Faibussowitsch     CHKERRMY(PetscViewerASCIIPrintf(errv, "Points missing in PointSF:\n"));
13605f80ce2aSJacob Faibussowitsch     CHKERRMY(ViewPointsWithType(ipdm, pointsf_missing_is, errv));
13615f80ce2aSJacob Faibussowitsch     CHKERRMY(PetscViewerASCIIPrintf(errv, "Extra points in PointSF:\n"));
13625f80ce2aSJacob Faibussowitsch     CHKERRMY(ViewPointsWithType(ipdm, pointsf_extra_is, errv));
13635f80ce2aSJacob Faibussowitsch     CHKERRMY(ISDestroy(&pointsf_extra_is));
13645f80ce2aSJacob Faibussowitsch     CHKERRMY(ISDestroy(&pointsf_missing_is));
1365c4762a1bSJed Brown     SETERRQ(comm, PETSC_ERR_PLIB, "PointSF is wrong! See details above.");
1366c4762a1bSJed Brown   }
13679566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pointsf_is));
1368c4762a1bSJed Brown   PetscFunctionReturn(0);
1369c4762a1bSJed Brown }
1370c4762a1bSJed Brown 
1371c4762a1bSJed Brown /* remove faces & edges from label, leave just vertices */
13729371c9d4SSatish Balay static PetscErrorCode DMPlexISFilterVertices_Private(DM dm, IS points) {
1373c4762a1bSJed Brown   PetscInt vStart, vEnd;
1374c4762a1bSJed Brown   MPI_Comm comm;
1375c4762a1bSJed Brown 
1376c4762a1bSJed Brown   PetscFunctionBegin;
13779566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
13789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
13799566063dSJacob Faibussowitsch   PetscCall(ISGeneralFilter(points, vStart, vEnd));
1380c4762a1bSJed Brown   PetscFunctionReturn(0);
1381c4762a1bSJed Brown }
1382c4762a1bSJed Brown 
1383c4762a1bSJed Brown /*
13842e58f0efSBarry Smith   DMPlexCheckPointSFHeavy - Thoroughly test that the PointSF after parallel DMPlexInterpolate() includes exactly all interface points.
1385c4762a1bSJed Brown 
1386c4762a1bSJed Brown   Collective
1387c4762a1bSJed Brown 
1388c4762a1bSJed Brown   Input Parameters:
1389c4762a1bSJed Brown . dm - The DMPlex object
1390c4762a1bSJed Brown 
1391c4762a1bSJed Brown   Notes:
1392c4762a1bSJed Brown   The input DMPlex must be serial (one partition has all points, the other partitions have no points).
1393c4762a1bSJed Brown   This is a heavy test which involves DMPlexInterpolate() if the input DM is not interpolated yet, and depends on having a representation of the whole-domain boundary (PortableBoundary), which can be obtained only by DMPlexGetExpandedBoundary_Private() (which involves DMPlexInterpolate() of a sequential DM).
1394c4762a1bSJed Brown   This is mainly intended for debugging/testing purposes.
1395c4762a1bSJed Brown 
1396c4762a1bSJed Brown   Algorithm:
1397c4762a1bSJed Brown   1. boundary faces of the serial version of the whole mesh are found using DMPlexMarkBoundaryFaces()
1398c4762a1bSJed Brown   2. boundary faces are translated into vertices using DMPlexGetConeRecursive() and these are translated into coordinates - this description (aka PortableBoundary) is completely independent of partitioning and point numbering
1399c4762a1bSJed Brown   3. the mesh is distributed or loaded in parallel
1400c4762a1bSJed Brown   4. boundary faces of the distributed mesh are reconstructed from PortableBoundary using DMPlexFindVertices()
1401c4762a1bSJed Brown   5. partition boundary faces of the parallel mesh are found using DMPlexMarkBoundaryFaces()
1402c4762a1bSJed Brown   6. partition interfaces are computed as set difference of partition boundary faces minus the reconstructed boundary
1403c4762a1bSJed Brown   7. check that interface covered by PointSF (union of inward and outward points) is equal to the partition interface for each rank, otherwise print the difference and throw an error
1404c4762a1bSJed Brown 
1405c4762a1bSJed Brown   Level: developer
1406c4762a1bSJed Brown 
1407c4762a1bSJed Brown .seealso: DMGetPointSF(), DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces()
1408c4762a1bSJed Brown */
14099371c9d4SSatish Balay static PetscErrorCode DMPlexCheckPointSFHeavy(DM dm, PortableBoundary bnd) {
1410c4762a1bSJed Brown   DM                     ipdm = NULL;
1411c4762a1bSJed Brown   IS                     boundary_faces_is, interface_faces_is, interface_is;
1412c4762a1bSJed Brown   DMPlexInterpolatedFlag intp;
1413c4762a1bSJed Brown   MPI_Comm               comm;
1414c4762a1bSJed Brown 
1415c4762a1bSJed Brown   PetscFunctionBegin;
14169566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
1417c4762a1bSJed Brown 
14189566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(dm, &intp));
1419c4762a1bSJed Brown   if (intp == DMPLEX_INTERPOLATED_FULL) {
1420c4762a1bSJed Brown     ipdm = dm;
1421c4762a1bSJed Brown   } else {
1422c4762a1bSJed Brown     /* create temporary interpolated DM if input DM is not interpolated */
14239566063dSJacob Faibussowitsch     PetscCall(DMPlexSetOrientInterface_Private(dm, PETSC_FALSE));
14249566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &ipdm)); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexComparePointSFWithInterface_Private() below */
14259566063dSJacob Faibussowitsch     PetscCall(DMPlexSetOrientInterface_Private(dm, PETSC_TRUE));
1426c4762a1bSJed Brown   }
14279566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(ipdm, NULL, "-ipdm_view"));
1428c4762a1bSJed Brown 
1429c4762a1bSJed Brown   /* recover ipdm whole-domain boundary faces from the expanded vertices coordinates */
14309566063dSJacob Faibussowitsch   PetscCall(DMPlexExpandedVerticesCoordinatesToFaces_Private(ipdm, bnd, &boundary_faces_is));
1431c4762a1bSJed Brown   /* get inter-partition interface faces (interface_faces_is)*/
14329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetInterfaceFaces_Private(ipdm, boundary_faces_is, &interface_faces_is));
1433c4762a1bSJed Brown   /* compute inter-partition interface including edges and vertices (interface_is) */
14349566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeCompleteInterface_Private(ipdm, interface_faces_is, &interface_is));
1435c4762a1bSJed Brown   /* destroy immediate ISs */
14369566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&boundary_faces_is));
14379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&interface_faces_is));
1438c4762a1bSJed Brown 
1439c4762a1bSJed Brown   /* for uninterpolated case, keep just vertices in interface */
1440c4762a1bSJed Brown   if (!intp) {
14419566063dSJacob Faibussowitsch     PetscCall(DMPlexISFilterVertices_Private(ipdm, interface_is));
14429566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&ipdm));
1443c4762a1bSJed Brown   }
1444c4762a1bSJed Brown 
1445c4762a1bSJed Brown   /* compare PointSF with the boundary reconstructed from coordinates */
14469566063dSJacob Faibussowitsch   PetscCall(DMPlexComparePointSFWithInterface_Private(dm, interface_is));
14479566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(comm, "DMPlexCheckPointSFHeavy PASSED\n"));
14489566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&interface_is));
1449c4762a1bSJed Brown   PetscFunctionReturn(0);
1450c4762a1bSJed Brown }
1451c4762a1bSJed Brown 
14529371c9d4SSatish Balay int main(int argc, char **argv) {
1453c4762a1bSJed Brown   DM     dm;
1454c4762a1bSJed Brown   AppCtx user;
1455c4762a1bSJed Brown 
1456327415f7SBarry Smith   PetscFunctionBeginUser;
14579566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
14589566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("create", &stage[0]));
14599566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("distribute", &stage[1]));
14609566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("interpolate", &stage[2]));
14619566063dSJacob Faibussowitsch   PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user));
14629566063dSJacob Faibussowitsch   PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm));
1463*48a46eb9SPierre Jolivet   if (user.nPointsToExpand) PetscCall(TestExpandPoints(dm, &user));
1464c4762a1bSJed Brown   if (user.ncoords) {
1465d3e1f4ccSVaclav Hapla     Vec coords;
1466d3e1f4ccSVaclav Hapla 
14679566063dSJacob Faibussowitsch     PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, user.ncoords, user.ncoords, user.coords, &coords));
14689566063dSJacob Faibussowitsch     PetscCall(ViewVerticesFromCoords(dm, coords, user.coordsTol, PETSC_VIEWER_STDOUT_WORLD));
14699566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coords));
1470c4762a1bSJed Brown   }
14719566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm));
14729566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
1473b122ec5aSJacob Faibussowitsch   return 0;
1474c4762a1bSJed Brown }
1475c4762a1bSJed Brown 
1476c4762a1bSJed Brown /*TEST
1477c4762a1bSJed Brown 
1478c4762a1bSJed Brown   testset:
1479c4762a1bSJed Brown     nsize: 2
1480c4762a1bSJed Brown     args: -dm_view ascii::ascii_info_detail
1481c4762a1bSJed Brown     args: -dm_plex_check_all
1482c4762a1bSJed Brown     test:
1483c4762a1bSJed Brown       suffix: 1_tri_dist0
1484c4762a1bSJed Brown       args: -distribute 0 -interpolate {{none create}separate output}
1485c4762a1bSJed Brown     test:
1486c4762a1bSJed Brown       suffix: 1_tri_dist1
1487c4762a1bSJed Brown       args: -distribute 1 -interpolate {{none create after_distribute}separate output}
1488c4762a1bSJed Brown     test:
1489c4762a1bSJed Brown       suffix: 1_quad_dist0
1490c4762a1bSJed Brown       args: -cell_simplex 0 -distribute 0 -interpolate {{none create}separate output}
1491c4762a1bSJed Brown     test:
1492c4762a1bSJed Brown       suffix: 1_quad_dist1
1493c4762a1bSJed Brown       args: -cell_simplex 0 -distribute 1 -interpolate {{none create after_distribute}separate output}
1494c4762a1bSJed Brown     test:
1495c4762a1bSJed Brown       suffix: 1_1d_dist1
1496c4762a1bSJed Brown       args: -dim 1 -distribute 1
1497c4762a1bSJed Brown 
1498c4762a1bSJed Brown   testset:
1499c4762a1bSJed Brown     nsize: 3
1500c4762a1bSJed Brown     args: -testnum 1 -interpolate create
1501c4762a1bSJed Brown     args: -dm_plex_check_all
1502c4762a1bSJed Brown     test:
1503c4762a1bSJed Brown       suffix: 2
1504c4762a1bSJed Brown       args: -dm_view ascii::ascii_info_detail
1505c4762a1bSJed Brown     test:
1506c4762a1bSJed Brown       suffix: 2a
1507c4762a1bSJed Brown       args: -dm_plex_check_cones_conform_on_interfaces_verbose
1508c4762a1bSJed Brown     test:
1509c4762a1bSJed Brown       suffix: 2b
1510c4762a1bSJed Brown       args: -test_expand_points 0,1,2,5,6
1511c4762a1bSJed Brown     test:
1512c4762a1bSJed Brown       suffix: 2c
1513c4762a1bSJed Brown       args: -test_expand_points 0,1,2,5,6 -test_expand_points_empty
1514c4762a1bSJed Brown 
1515c4762a1bSJed Brown   testset:
1516c4762a1bSJed Brown     # the same as 1% for 3D
1517c4762a1bSJed Brown     nsize: 2
1518c4762a1bSJed Brown     args: -dim 3 -dm_view ascii::ascii_info_detail
1519c4762a1bSJed Brown     args: -dm_plex_check_all
1520c4762a1bSJed Brown     test:
1521c4762a1bSJed Brown       suffix: 4_tet_dist0
1522c4762a1bSJed Brown       args: -distribute 0 -interpolate {{none create}separate output}
1523c4762a1bSJed Brown     test:
1524c4762a1bSJed Brown       suffix: 4_tet_dist1
1525c4762a1bSJed Brown       args: -distribute 1 -interpolate {{none create after_distribute}separate output}
1526c4762a1bSJed Brown     test:
1527c4762a1bSJed Brown       suffix: 4_hex_dist0
1528c4762a1bSJed Brown       args: -cell_simplex 0 -distribute 0 -interpolate {{none create}separate output}
1529c4762a1bSJed Brown     test:
1530c4762a1bSJed Brown       suffix: 4_hex_dist1
1531c4762a1bSJed Brown       args: -cell_simplex 0 -distribute 1 -interpolate {{none create after_distribute}separate output}
1532c4762a1bSJed Brown 
1533c4762a1bSJed Brown   test:
1534c4762a1bSJed Brown     # the same as 4_tet_dist0 but test different initial orientations
1535c4762a1bSJed Brown     suffix: 4_tet_test_orient
1536c4762a1bSJed Brown     nsize: 2
1537c4762a1bSJed Brown     args: -dim 3 -distribute 0
1538c4762a1bSJed Brown     args: -dm_plex_check_all
1539c4762a1bSJed Brown     args: -rotate_interface_0 {{0 1 2 11 12 13}}
1540c4762a1bSJed Brown     args: -rotate_interface_1 {{0 1 2 11 12 13}}
1541c4762a1bSJed Brown 
1542c4762a1bSJed Brown   testset:
1543c4762a1bSJed Brown     requires: exodusii
1544c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/TwoQuads.exo
1545c4762a1bSJed Brown     args: -dm_view ascii::ascii_info_detail
1546c4762a1bSJed Brown     args: -dm_plex_check_all
1547c4762a1bSJed Brown     args: -custom_view
1548c4762a1bSJed Brown     test:
1549c4762a1bSJed Brown       suffix: 5_seq
1550c4762a1bSJed Brown       nsize: 1
1551c4762a1bSJed Brown       args: -distribute 0 -interpolate {{none create}separate output}
1552c4762a1bSJed Brown     test:
155330602db0SMatthew G. Knepley       # Detail viewing in a non-distributed mesh is broken because the DMLabelView() is collective, but the label is not shared
1554c4762a1bSJed Brown       suffix: 5_dist0
1555c4762a1bSJed Brown       nsize: 2
155630602db0SMatthew G. Knepley       args: -distribute 0 -interpolate {{none create}separate output} -dm_view
1557c4762a1bSJed Brown     test:
1558c4762a1bSJed Brown       suffix: 5_dist1
1559c4762a1bSJed Brown       nsize: 2
1560c4762a1bSJed Brown       args: -distribute 1 -interpolate {{none create after_distribute}separate output}
1561c4762a1bSJed Brown 
1562c4762a1bSJed Brown   testset:
1563c4762a1bSJed Brown     nsize: {{1 2 4}}
1564c4762a1bSJed Brown     args: -use_generator
1565c4762a1bSJed Brown     args: -dm_plex_check_all
1566c4762a1bSJed Brown     args: -distribute -interpolate none
1567c4762a1bSJed Brown     test:
1568c4762a1bSJed Brown       suffix: 6_tri
1569c4762a1bSJed Brown       requires: triangle
1570c0517cd5SMatthew G. Knepley       args: -faces {{2,2  1,3  7,4}} -cell_simplex 1 -dm_generator triangle
1571c4762a1bSJed Brown     test:
1572c4762a1bSJed Brown       suffix: 6_quad
1573c4762a1bSJed Brown       args: -faces {{2,2  1,3  7,4}} -cell_simplex 0
1574c4762a1bSJed Brown     test:
1575c4762a1bSJed Brown       suffix: 6_tet
1576c4762a1bSJed Brown       requires: ctetgen
1577c0517cd5SMatthew G. Knepley       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 1 -dm_generator ctetgen
1578c4762a1bSJed Brown     test:
1579c4762a1bSJed Brown       suffix: 6_hex
1580c4762a1bSJed Brown       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 0
1581c4762a1bSJed Brown   testset:
1582c4762a1bSJed Brown     nsize: {{1 2 4}}
1583c4762a1bSJed Brown     args: -use_generator
1584c4762a1bSJed Brown     args: -dm_plex_check_all
1585c4762a1bSJed Brown     args: -distribute -interpolate create
1586c4762a1bSJed Brown     test:
1587c4762a1bSJed Brown       suffix: 6_int_tri
1588c4762a1bSJed Brown       requires: triangle
1589c0517cd5SMatthew G. Knepley       args: -faces {{2,2  1,3  7,4}} -cell_simplex 1 -dm_generator triangle
1590c4762a1bSJed Brown     test:
1591c4762a1bSJed Brown       suffix: 6_int_quad
1592c4762a1bSJed Brown       args: -faces {{2,2  1,3  7,4}} -cell_simplex 0
1593c4762a1bSJed Brown     test:
1594c4762a1bSJed Brown       suffix: 6_int_tet
1595c4762a1bSJed Brown       requires: ctetgen
1596c0517cd5SMatthew G. Knepley       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 1 -dm_generator ctetgen
1597c4762a1bSJed Brown     test:
1598c4762a1bSJed Brown       suffix: 6_int_hex
1599c4762a1bSJed Brown       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 0
1600c4762a1bSJed Brown   testset:
1601c4762a1bSJed Brown     nsize: {{2 4}}
1602c4762a1bSJed Brown     args: -use_generator
1603c4762a1bSJed Brown     args: -dm_plex_check_all
1604c4762a1bSJed Brown     args: -distribute -interpolate after_distribute
1605c4762a1bSJed Brown     test:
1606c4762a1bSJed Brown       suffix: 6_parint_tri
1607c4762a1bSJed Brown       requires: triangle
1608c0517cd5SMatthew G. Knepley       args: -faces {{2,2  1,3  7,4}} -cell_simplex 1 -dm_generator triangle
1609c4762a1bSJed Brown     test:
1610c4762a1bSJed Brown       suffix: 6_parint_quad
1611c4762a1bSJed Brown       args: -faces {{2,2  1,3  7,4}} -cell_simplex 0
1612c4762a1bSJed Brown     test:
1613c4762a1bSJed Brown       suffix: 6_parint_tet
1614c4762a1bSJed Brown       requires: ctetgen
1615c0517cd5SMatthew G. Knepley       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 1 -dm_generator ctetgen
1616c4762a1bSJed Brown     test:
1617c4762a1bSJed Brown       suffix: 6_parint_hex
1618c4762a1bSJed Brown       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 0
1619c4762a1bSJed Brown 
1620c4762a1bSJed Brown   testset: # 7 EXODUS
1621c4762a1bSJed Brown     requires: exodusii
1622c4762a1bSJed Brown     args: -dm_plex_check_all
1623c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.exo
1624c4762a1bSJed Brown     args: -distribute
1625c4762a1bSJed Brown     test: # seq load, simple partitioner
1626c4762a1bSJed Brown       suffix: 7_exo
1627c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1628c4762a1bSJed Brown       args: -interpolate none
1629c4762a1bSJed Brown     test: # seq load, seq interpolation, simple partitioner
1630c4762a1bSJed Brown       suffix: 7_exo_int_simple
1631c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1632c4762a1bSJed Brown       args: -interpolate create
1633c4762a1bSJed Brown     test: # seq load, seq interpolation, metis partitioner
1634c4762a1bSJed Brown       suffix: 7_exo_int_metis
1635c4762a1bSJed Brown       requires: parmetis
1636c4762a1bSJed Brown       nsize: {{2 4 5}}
1637c4762a1bSJed Brown       args: -interpolate create
1638c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1639c4762a1bSJed Brown     test: # seq load, simple partitioner, par interpolation
1640c4762a1bSJed Brown       suffix: 7_exo_simple_int
1641c4762a1bSJed Brown       nsize: {{2 4 5}}
1642c4762a1bSJed Brown       args: -interpolate after_distribute
1643c4762a1bSJed Brown     test: # seq load, metis partitioner, par interpolation
1644c4762a1bSJed Brown       suffix: 7_exo_metis_int
1645c4762a1bSJed Brown       requires: parmetis
1646c4762a1bSJed Brown       nsize: {{2 4 5}}
1647c4762a1bSJed Brown       args: -interpolate after_distribute
1648c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1649c4762a1bSJed Brown 
1650c4762a1bSJed Brown   testset: # 7 HDF5 SEQUANTIAL LOAD
1651c4762a1bSJed Brown     requires: hdf5 !complex
1652c4762a1bSJed Brown     args: -dm_plex_check_all
1653c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf
1654c4762a1bSJed Brown     args: -dm_plex_hdf5_force_sequential
1655c4762a1bSJed Brown     args: -distribute
1656c4762a1bSJed Brown     test: # seq load, simple partitioner
1657c4762a1bSJed Brown       suffix: 7_seq_hdf5_simple
1658c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1659c4762a1bSJed Brown       args: -interpolate none
1660c4762a1bSJed Brown     test: # seq load, seq interpolation, simple partitioner
1661c4762a1bSJed Brown       suffix: 7_seq_hdf5_int_simple
1662c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1663c4762a1bSJed Brown       args: -interpolate after_create
1664c4762a1bSJed Brown     test: # seq load, seq interpolation, metis partitioner
1665c4762a1bSJed Brown       nsize: {{2 4 5}}
1666c4762a1bSJed Brown       suffix: 7_seq_hdf5_int_metis
1667c4762a1bSJed Brown       requires: parmetis
1668c4762a1bSJed Brown       args: -interpolate after_create
1669c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1670c4762a1bSJed Brown     test: # seq load, simple partitioner, par interpolation
1671c4762a1bSJed Brown       suffix: 7_seq_hdf5_simple_int
1672c4762a1bSJed Brown       nsize: {{2 4 5}}
1673c4762a1bSJed Brown       args: -interpolate after_distribute
1674c4762a1bSJed Brown     test: # seq load, metis partitioner, par interpolation
1675c4762a1bSJed Brown       nsize: {{2 4 5}}
1676c4762a1bSJed Brown       suffix: 7_seq_hdf5_metis_int
1677c4762a1bSJed Brown       requires: parmetis
1678c4762a1bSJed Brown       args: -interpolate after_distribute
1679c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1680c4762a1bSJed Brown 
1681c4762a1bSJed Brown   testset: # 7 HDF5 PARALLEL LOAD
1682c4762a1bSJed Brown     requires: hdf5 !complex
1683c4762a1bSJed Brown     nsize: {{2 4 5}}
1684c4762a1bSJed Brown     args: -dm_plex_check_all
1685c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf
1686c4762a1bSJed Brown     test: # par load
1687c4762a1bSJed Brown       suffix: 7_par_hdf5
1688c4762a1bSJed Brown       args: -interpolate none
1689c4762a1bSJed Brown     test: # par load, par interpolation
1690c4762a1bSJed Brown       suffix: 7_par_hdf5_int
1691c4762a1bSJed Brown       args: -interpolate after_create
1692c4762a1bSJed Brown     test: # par load, parmetis repartitioner
1693c4762a1bSJed Brown       TODO: Parallel partitioning of uninterpolated meshes not supported
1694c4762a1bSJed Brown       suffix: 7_par_hdf5_parmetis
1695c4762a1bSJed Brown       requires: parmetis
1696c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1697c4762a1bSJed Brown       args: -interpolate none
1698c4762a1bSJed Brown     test: # par load, par interpolation, parmetis repartitioner
1699c4762a1bSJed Brown       suffix: 7_par_hdf5_int_parmetis
1700c4762a1bSJed Brown       requires: parmetis
1701c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1702c4762a1bSJed Brown       args: -interpolate after_create
1703c4762a1bSJed Brown     test: # par load, parmetis partitioner, par interpolation
1704c4762a1bSJed Brown       TODO: Parallel partitioning of uninterpolated meshes not supported
1705c4762a1bSJed Brown       suffix: 7_par_hdf5_parmetis_int
1706c4762a1bSJed Brown       requires: parmetis
1707c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1708c4762a1bSJed Brown       args: -interpolate after_distribute
1709c4762a1bSJed Brown 
1710c4762a1bSJed Brown     test:
1711c4762a1bSJed Brown       suffix: 7_hdf5_hierarch
1712c4762a1bSJed Brown       requires: hdf5 ptscotch !complex
1713c4762a1bSJed Brown       nsize: {{2 3 4}separate output}
1714c4762a1bSJed Brown       args: -distribute
1715c4762a1bSJed Brown       args: -interpolate after_create
1716c4762a1bSJed Brown       args: -petscpartitioner_type matpartitioning -petscpartitioner_view ::ascii_info
1717c4762a1bSJed Brown       args: -mat_partitioning_type hierarch -mat_partitioning_hierarchical_nfineparts 2
1718c4762a1bSJed Brown       args: -mat_partitioning_hierarchical_coarseparttype ptscotch -mat_partitioning_hierarchical_fineparttype ptscotch
1719c4762a1bSJed Brown 
1720c4762a1bSJed Brown   test:
1721c4762a1bSJed Brown     suffix: 8
1722c4762a1bSJed Brown     requires: hdf5 !complex
1723c4762a1bSJed Brown     nsize: 4
1724c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf
1725c4762a1bSJed Brown     args: -distribute 0 -interpolate after_create
1726c4762a1bSJed Brown     args: -view_vertices_from_coords 0.,1.,0.,-0.5,1.,0.,0.583,-0.644,0.,-2.,-2.,-2. -view_vertices_from_coords_tol 1e-3
1727c4762a1bSJed Brown     args: -dm_plex_check_all
1728c4762a1bSJed Brown     args: -custom_view
1729c4762a1bSJed Brown 
1730c4762a1bSJed Brown   testset: # 9 HDF5 SEQUANTIAL LOAD
1731c4762a1bSJed Brown     requires: hdf5 !complex datafilespath
1732c4762a1bSJed Brown     args: -dm_plex_check_all
1733c4762a1bSJed Brown     args: -filename ${DATAFILESPATH}/meshes/cube-hexahedra-refined.h5 -dm_plex_create_from_hdf5_xdmf -dm_plex_hdf5_topology_path /cells -dm_plex_hdf5_geometry_path /coordinates
1734c4762a1bSJed Brown     args: -dm_plex_hdf5_force_sequential
1735c4762a1bSJed Brown     args: -distribute
1736c4762a1bSJed Brown     test: # seq load, simple partitioner
1737c4762a1bSJed Brown       suffix: 9_seq_hdf5_simple
1738c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1739c4762a1bSJed Brown       args: -interpolate none
1740c4762a1bSJed Brown     test: # seq load, seq interpolation, simple partitioner
1741c4762a1bSJed Brown       suffix: 9_seq_hdf5_int_simple
1742c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1743c4762a1bSJed Brown       args: -interpolate after_create
1744c4762a1bSJed Brown     test: # seq load, seq interpolation, metis partitioner
1745c4762a1bSJed Brown       nsize: {{2 4 5}}
1746c4762a1bSJed Brown       suffix: 9_seq_hdf5_int_metis
1747c4762a1bSJed Brown       requires: parmetis
1748c4762a1bSJed Brown       args: -interpolate after_create
1749c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1750c4762a1bSJed Brown     test: # seq load, simple partitioner, par interpolation
1751c4762a1bSJed Brown       suffix: 9_seq_hdf5_simple_int
1752c4762a1bSJed Brown       nsize: {{2 4 5}}
1753c4762a1bSJed Brown       args: -interpolate after_distribute
1754c4762a1bSJed Brown     test: # seq load, simple partitioner, par interpolation
1755c4762a1bSJed Brown       # This is like 9_seq_hdf5_simple_int but testing error output of DMPlexCheckPointSFHeavy().
1756c4762a1bSJed Brown       # Once 9_seq_hdf5_simple_int gets fixed, this one gets broken.
1757c4762a1bSJed Brown       # We can then provide an intentionally broken mesh instead.
1758c4762a1bSJed Brown       TODO: This test is broken because PointSF is fixed.
1759c4762a1bSJed Brown       suffix: 9_seq_hdf5_simple_int_err
1760c4762a1bSJed Brown       nsize: 4
1761c4762a1bSJed Brown       args: -interpolate after_distribute
1762c4762a1bSJed Brown       filter: sed -e "/PETSC ERROR/,$$d"
1763c4762a1bSJed Brown     test: # seq load, metis partitioner, par interpolation
1764c4762a1bSJed Brown       nsize: {{2 4 5}}
1765c4762a1bSJed Brown       suffix: 9_seq_hdf5_metis_int
1766c4762a1bSJed Brown       requires: parmetis
1767c4762a1bSJed Brown       args: -interpolate after_distribute
1768c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1769c4762a1bSJed Brown 
1770c4762a1bSJed Brown   testset: # 9 HDF5 PARALLEL LOAD
1771c4762a1bSJed Brown     requires: hdf5 !complex datafilespath
1772c4762a1bSJed Brown     nsize: {{2 4 5}}
1773c4762a1bSJed Brown     args: -dm_plex_check_all
1774c4762a1bSJed Brown     args: -filename ${DATAFILESPATH}/meshes/cube-hexahedra-refined.h5 -dm_plex_create_from_hdf5_xdmf -dm_plex_hdf5_topology_path /cells -dm_plex_hdf5_geometry_path /coordinates
1775c4762a1bSJed Brown     test: # par load
1776c4762a1bSJed Brown       suffix: 9_par_hdf5
1777c4762a1bSJed Brown       args: -interpolate none
1778c4762a1bSJed Brown     test: # par load, par interpolation
1779c4762a1bSJed Brown       suffix: 9_par_hdf5_int
1780c4762a1bSJed Brown       args: -interpolate after_create
1781c4762a1bSJed Brown     test: # par load, parmetis repartitioner
1782c4762a1bSJed Brown       TODO: Parallel partitioning of uninterpolated meshes not supported
1783c4762a1bSJed Brown       suffix: 9_par_hdf5_parmetis
1784c4762a1bSJed Brown       requires: parmetis
1785c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1786c4762a1bSJed Brown       args: -interpolate none
1787c4762a1bSJed Brown     test: # par load, par interpolation, parmetis repartitioner
1788c4762a1bSJed Brown       suffix: 9_par_hdf5_int_parmetis
1789c4762a1bSJed Brown       requires: parmetis
1790c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1791c4762a1bSJed Brown       args: -interpolate after_create
1792c4762a1bSJed Brown     test: # par load, parmetis partitioner, par interpolation
1793c4762a1bSJed Brown       TODO: Parallel partitioning of uninterpolated meshes not supported
1794c4762a1bSJed Brown       suffix: 9_par_hdf5_parmetis_int
1795c4762a1bSJed Brown       requires: parmetis
1796c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1797c4762a1bSJed Brown       args: -interpolate after_distribute
1798c4762a1bSJed Brown 
1799c4762a1bSJed Brown   testset: # 10 HDF5 PARALLEL LOAD
1800c4762a1bSJed Brown     requires: hdf5 !complex datafilespath
1801c4762a1bSJed Brown     nsize: {{2 4 7}}
1802c4762a1bSJed Brown     args: -dm_plex_check_all
1803c4762a1bSJed Brown     args: -filename ${DATAFILESPATH}/meshes/cube-hexahedra-refined2.h5 -dm_plex_create_from_hdf5_xdmf -dm_plex_hdf5_topology_path /topo -dm_plex_hdf5_geometry_path /geom
1804c4762a1bSJed Brown     test: # par load, par interpolation
1805c4762a1bSJed Brown       suffix: 10_par_hdf5_int
1806c4762a1bSJed Brown       args: -interpolate after_create
1807c4762a1bSJed Brown TEST*/
1808