xref: /petsc/src/dm/impls/plex/tests/ex18.c (revision da81f9329be15cc55f054c8a00978087195c9247)
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 
234d71ae5a4SJacob Faibussowitsch static PetscErrorCode PortableBoundaryDestroy(PortableBoundary *bnd)
235d71ae5a4SJacob Faibussowitsch {
236c4762a1bSJed Brown   PetscInt d;
237c4762a1bSJed Brown 
238c4762a1bSJed Brown   PetscFunctionBegin;
239c4762a1bSJed Brown   if (!*bnd) PetscFunctionReturn(0);
2409566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(*bnd)->coordinates));
24148a46eb9SPierre Jolivet   for (d = 0; d < (*bnd)->depth; d++) PetscCall(PetscSectionDestroy(&(*bnd)->sections[d]));
2429566063dSJacob Faibussowitsch   PetscCall(PetscFree((*bnd)->sections));
2439566063dSJacob Faibussowitsch   PetscCall(PetscFree(*bnd));
244c4762a1bSJed Brown   PetscFunctionReturn(0);
245c4762a1bSJed Brown }
246c4762a1bSJed Brown 
247d71ae5a4SJacob Faibussowitsch static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
248d71ae5a4SJacob Faibussowitsch {
249c4762a1bSJed Brown   const char *interpTypes[4] = {"none", "create", "after_create", "after_distribute"};
250c4762a1bSJed Brown   PetscInt    interp         = NONE, dim;
251c4762a1bSJed Brown   PetscBool   flg1, flg2;
252c4762a1bSJed Brown 
253c4762a1bSJed Brown   PetscFunctionBegin;
254c4762a1bSJed Brown   options->debug                 = 0;
255c4762a1bSJed Brown   options->testNum               = 0;
256c4762a1bSJed Brown   options->dim                   = 2;
257c4762a1bSJed Brown   options->cellSimplex           = PETSC_TRUE;
258c4762a1bSJed Brown   options->distribute            = PETSC_FALSE;
259c4762a1bSJed Brown   options->interpolate           = NONE;
260c4762a1bSJed Brown   options->useGenerator          = PETSC_FALSE;
261c4762a1bSJed Brown   options->testOrientIF          = PETSC_FALSE;
262c4762a1bSJed Brown   options->testHeavy             = PETSC_TRUE;
263c4762a1bSJed Brown   options->customView            = PETSC_FALSE;
264c4762a1bSJed Brown   options->testExpandPointsEmpty = PETSC_FALSE;
265c4762a1bSJed Brown   options->ornt[0]               = 0;
266c4762a1bSJed Brown   options->ornt[1]               = 0;
267c4762a1bSJed Brown   options->faces[0]              = 2;
268c4762a1bSJed Brown   options->faces[1]              = 2;
269c4762a1bSJed Brown   options->faces[2]              = 2;
270c4762a1bSJed Brown   options->filename[0]           = '\0';
271c4762a1bSJed Brown   options->coordsTol             = PETSC_DEFAULT;
272c4762a1bSJed Brown 
273d0609cedSBarry Smith   PetscOptionsBegin(comm, "", "Meshing Interpolation Test Options", "DMPLEX");
2749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-debug", "The debugging level", "ex18.c", options->debug, &options->debug, NULL, 0));
2759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-testnum", "The mesh to create", "ex18.c", options->testNum, &options->testNum, NULL, 0));
2769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-cell_simplex", "Generate simplices if true, otherwise hexes", "ex18.c", options->cellSimplex, &options->cellSimplex, NULL));
2779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-distribute", "Distribute the mesh", "ex18.c", options->distribute, &options->distribute, NULL));
2789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-interpolate", "Type of mesh interpolation (none, create, after_create, after_distribute)", "ex18.c", interpTypes, 4, interpTypes[options->interpolate], &interp, NULL));
279c4762a1bSJed Brown   options->interpolate = (InterpType)interp;
2801dca8a05SBarry Smith   PetscCheck(options->distribute || options->interpolate != AFTER_DISTRIBUTE, comm, PETSC_ERR_SUP, "-interpolate after_distribute  needs  -distribute 1");
2819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-use_generator", "Use a mesh generator to build the mesh", "ex18.c", options->useGenerator, &options->useGenerator, NULL));
282c4762a1bSJed Brown   options->ncoords = 128;
2839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsScalarArray("-view_vertices_from_coords", "Print DAG points corresponding to vertices with given coordinates", "ex18.c", options->coords, &options->ncoords, NULL));
2849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-view_vertices_from_coords_tol", "Tolerance for -view_vertices_from_coords", "ex18.c", options->coordsTol, &options->coordsTol, NULL));
285c4762a1bSJed Brown   options->nPointsToExpand = 128;
2869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-test_expand_points", "Expand given array of DAG point using DMPlexGetConeRecursive() and print results", "ex18.c", options->pointsToExpand, &options->nPointsToExpand, NULL));
28748a46eb9SPierre 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));
2889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-test_heavy", "Run the heavy PointSF test", "ex18.c", options->testHeavy, &options->testHeavy, NULL));
2899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-custom_view", "Custom DMPlex view", "ex18.c", options->customView, &options->customView, NULL));
2909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRangeInt("-dim", "The topological mesh dimension", "ex18.c", options->dim, &options->dim, &flg1, 1, 3));
291c4762a1bSJed Brown   dim = 3;
2929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-faces", "Number of faces per dimension", "ex18.c", options->faces, &dim, &flg2));
293c4762a1bSJed Brown   if (flg2) {
2941dca8a05SBarry 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);
295c4762a1bSJed Brown     options->dim = dim;
296c4762a1bSJed Brown   }
2979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-filename", "The mesh file", "ex18.c", options->filename, options->filename, sizeof(options->filename), NULL));
2989566063dSJacob 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));
2999566063dSJacob 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));
30008401ef6SPierre Jolivet   PetscCheck(flg2 == options->testOrientIF, comm, PETSC_ERR_ARG_OUTOFRANGE, "neither or both -rotate_interface_0 -rotate_interface_1 must be set");
301c4762a1bSJed Brown   if (options->testOrientIF) {
302c4762a1bSJed Brown     PetscInt i;
303c4762a1bSJed Brown     for (i = 0; i < 2; i++) {
304c4762a1bSJed Brown       if (options->ornt[i] >= 10) options->ornt[i] = -(options->ornt[i] - 10); /* 11 12 13 become -1 -2 -3 */
305c4762a1bSJed Brown     }
306c4762a1bSJed Brown     options->filename[0]  = 0;
307c4762a1bSJed Brown     options->useGenerator = PETSC_FALSE;
308c4762a1bSJed Brown     options->dim          = 3;
309c4762a1bSJed Brown     options->cellSimplex  = PETSC_TRUE;
310c4762a1bSJed Brown     options->interpolate  = CREATE;
311c4762a1bSJed Brown     options->distribute   = PETSC_FALSE;
312c4762a1bSJed Brown   }
313d0609cedSBarry Smith   PetscOptionsEnd();
314c4762a1bSJed Brown   PetscFunctionReturn(0);
315c4762a1bSJed Brown }
316c4762a1bSJed Brown 
317d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateMesh_1D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm)
318d71ae5a4SJacob Faibussowitsch {
319c4762a1bSJed Brown   PetscInt    testNum = user->testNum;
320c4762a1bSJed Brown   PetscMPIInt rank, size;
321c4762a1bSJed Brown   PetscInt    numCorners = 2, i;
322c4762a1bSJed Brown   PetscInt    numCells, numVertices, network;
323a4a685f2SJacob Faibussowitsch   PetscInt   *cells;
324c4762a1bSJed Brown   PetscReal  *coords;
325c4762a1bSJed Brown 
326c4762a1bSJed Brown   PetscFunctionBegin;
3279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
3289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
32963a3b9bcSJacob Faibussowitsch   PetscCheck(size <= 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for <=2 processes", testNum);
330c4762a1bSJed Brown 
331c4762a1bSJed Brown   numCells = 3;
3329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-ncells", &numCells, NULL));
33363a3b9bcSJacob Faibussowitsch   PetscCheck(numCells >= 3, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test ncells %" PetscInt_FMT " must >=3", numCells);
334c4762a1bSJed Brown 
335c4762a1bSJed Brown   if (size == 1) {
336c4762a1bSJed Brown     numVertices = numCells + 1;
3379566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numVertices, &coords));
338c4762a1bSJed Brown     for (i = 0; i < numCells; i++) {
3399371c9d4SSatish Balay       cells[2 * i]      = i;
3409371c9d4SSatish Balay       cells[2 * i + 1]  = i + 1;
3419371c9d4SSatish Balay       coords[2 * i]     = i;
3429371c9d4SSatish Balay       coords[2 * i + 1] = i + 1;
343c4762a1bSJed Brown     }
344c4762a1bSJed Brown 
3459566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromCellListPetsc(comm, user->dim, numCells, numVertices, numCorners, PETSC_FALSE, cells, user->dim, coords, dm));
3469566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cells, coords));
347c4762a1bSJed Brown     PetscFunctionReturn(0);
348c4762a1bSJed Brown   }
349c4762a1bSJed Brown 
350c4762a1bSJed Brown   network = 0;
3519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-network_case", &network, NULL));
352c4762a1bSJed Brown   if (network == 0) {
353c4762a1bSJed Brown     switch (rank) {
3549371c9d4SSatish Balay     case 0: {
355c4762a1bSJed Brown       numCells    = 2;
356c4762a1bSJed Brown       numVertices = numCells;
3579566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numCells, &coords));
3589371c9d4SSatish Balay       cells[0]  = 0;
3599371c9d4SSatish Balay       cells[1]  = 1;
3609371c9d4SSatish Balay       cells[2]  = 1;
3619371c9d4SSatish Balay       cells[3]  = 2;
3629371c9d4SSatish Balay       coords[0] = 0.;
3639371c9d4SSatish Balay       coords[1] = 1.;
3649371c9d4SSatish Balay       coords[2] = 1.;
3659371c9d4SSatish Balay       coords[3] = 2.;
3669371c9d4SSatish Balay     } break;
3679371c9d4SSatish Balay     case 1: {
368c4762a1bSJed Brown       numCells -= 2;
369c4762a1bSJed Brown       numVertices = numCells + 1;
3709566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numCells, &coords));
371c4762a1bSJed Brown       for (i = 0; i < numCells; i++) {
3729371c9d4SSatish Balay         cells[2 * i]      = 2 + i;
3739371c9d4SSatish Balay         cells[2 * i + 1]  = 2 + i + 1;
3749371c9d4SSatish Balay         coords[2 * i]     = 2 + i;
3759371c9d4SSatish Balay         coords[2 * i + 1] = 2 + i + 1;
376c4762a1bSJed Brown       }
3779371c9d4SSatish Balay     } break;
378d71ae5a4SJacob Faibussowitsch     default:
379d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
380c4762a1bSJed Brown     }
381c4762a1bSJed Brown   } else { /* network_case = 1 */
382c4762a1bSJed Brown     /* ----------------------- */
383c4762a1bSJed Brown     switch (rank) {
3849371c9d4SSatish Balay     case 0: {
385c4762a1bSJed Brown       numCells    = 2;
386c4762a1bSJed Brown       numVertices = 3;
3879566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numCells, &coords));
3889371c9d4SSatish Balay       cells[0] = 0;
3899371c9d4SSatish Balay       cells[1] = 3;
3909371c9d4SSatish Balay       cells[2] = 3;
3919371c9d4SSatish Balay       cells[3] = 1;
3929371c9d4SSatish Balay     } break;
3939371c9d4SSatish Balay     case 1: {
394c4762a1bSJed Brown       numCells    = 1;
395c4762a1bSJed Brown       numVertices = 1;
3969566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(2 * numCells, &cells, 2 * numCells, &coords));
3979371c9d4SSatish Balay       cells[0] = 3;
3989371c9d4SSatish Balay       cells[1] = 2;
3999371c9d4SSatish Balay     } break;
400d71ae5a4SJacob Faibussowitsch     default:
401d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
402c4762a1bSJed Brown     }
403c4762a1bSJed Brown   }
4049566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, PETSC_FALSE, cells, user->dim, coords, NULL, NULL, dm));
4059566063dSJacob Faibussowitsch   PetscCall(PetscFree2(cells, coords));
406c4762a1bSJed Brown   PetscFunctionReturn(0);
407c4762a1bSJed Brown }
408c4762a1bSJed Brown 
409d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateSimplex_2D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm)
410d71ae5a4SJacob Faibussowitsch {
411c4762a1bSJed Brown   PetscInt    testNum = user->testNum, p;
412c4762a1bSJed Brown   PetscMPIInt rank, size;
413c4762a1bSJed Brown 
414c4762a1bSJed Brown   PetscFunctionBegin;
4159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
4169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
417c4762a1bSJed Brown   switch (testNum) {
418c4762a1bSJed Brown   case 0:
41963a3b9bcSJacob Faibussowitsch     PetscCheck(size == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 2 processes", testNum);
420c4762a1bSJed Brown     switch (rank) {
4219371c9d4SSatish Balay     case 0: {
422c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
423a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {0, 1, 2};
424c4762a1bSJed Brown       PetscReal      coords[4]       = {-0.5, 0.5, 0.0, 0.0};
425c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
426c4762a1bSJed Brown 
4279566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4289566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4299371c9d4SSatish Balay     } break;
4309371c9d4SSatish Balay     case 1: {
431c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
432a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {1, 3, 2};
433c4762a1bSJed Brown       PetscReal      coords[4]       = {0.0, 1.0, 0.5, 0.5};
434c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
435c4762a1bSJed Brown 
4369566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4379566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4389371c9d4SSatish Balay     } break;
439d71ae5a4SJacob Faibussowitsch     default:
440d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
441c4762a1bSJed Brown     }
442c4762a1bSJed Brown     break;
443c4762a1bSJed Brown   case 1:
44463a3b9bcSJacob Faibussowitsch     PetscCheck(size == 3, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 3 processes", testNum);
445c4762a1bSJed Brown     switch (rank) {
4469371c9d4SSatish Balay     case 0: {
447c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
448a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {0, 1, 2};
449c4762a1bSJed Brown       PetscReal      coords[4]       = {0.0, 1.0, 0.0, 0.0};
450c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
451c4762a1bSJed Brown 
4529566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4539566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4549371c9d4SSatish Balay     } break;
4559371c9d4SSatish Balay     case 1: {
456c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
457a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {0, 2, 3};
458c4762a1bSJed Brown       PetscReal      coords[4]       = {0.5, 0.5, 1.0, 1.0};
459c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
460c4762a1bSJed Brown 
4619566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4629566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4639371c9d4SSatish Balay     } break;
4649371c9d4SSatish Balay     case 2: {
465c4762a1bSJed Brown       const PetscInt numCells = 2, numVertices = 1, numCorners = 3;
466a4a685f2SJacob Faibussowitsch       const PetscInt cells[6]         = {2, 4, 3, 2, 1, 4};
467c4762a1bSJed Brown       PetscReal      coords[2]        = {1.0, 0.0};
468c4762a1bSJed Brown       PetscInt       markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1};
469c4762a1bSJed Brown 
4709566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4719566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4729371c9d4SSatish Balay     } break;
473d71ae5a4SJacob Faibussowitsch     default:
474d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
475c4762a1bSJed Brown     }
476c4762a1bSJed Brown     break;
477c4762a1bSJed Brown   case 2:
47863a3b9bcSJacob Faibussowitsch     PetscCheck(size == 3, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 3 processes", testNum);
479c4762a1bSJed Brown     switch (rank) {
4809371c9d4SSatish Balay     case 0: {
481c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
482a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {1, 2, 0};
483c4762a1bSJed Brown       PetscReal      coords[4]       = {0.5, 0.5, 0.0, 1.0};
484c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
485c4762a1bSJed Brown 
4869566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4879566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4889371c9d4SSatish Balay     } break;
4899371c9d4SSatish Balay     case 1: {
490c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 3;
491a4a685f2SJacob Faibussowitsch       const PetscInt cells[3]        = {1, 0, 3};
492c4762a1bSJed Brown       PetscReal      coords[4]       = {0.0, 0.0, 1.0, 1.0};
493c4762a1bSJed Brown       PetscInt       markerPoints[6] = {1, 1, 2, 1, 3, 1};
494c4762a1bSJed Brown 
4959566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
4969566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
4979371c9d4SSatish Balay     } break;
4989371c9d4SSatish Balay     case 2: {
499c4762a1bSJed Brown       const PetscInt numCells = 2, numVertices = 1, numCorners = 3;
500a4a685f2SJacob Faibussowitsch       const PetscInt cells[6]         = {0, 4, 3, 0, 2, 4};
501c4762a1bSJed Brown       PetscReal      coords[2]        = {1.0, 0.0};
502c4762a1bSJed Brown       PetscInt       markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1};
503c4762a1bSJed Brown 
5049566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5059566063dSJacob Faibussowitsch       for (p = 0; p < 3; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5069371c9d4SSatish Balay     } break;
507d71ae5a4SJacob Faibussowitsch     default:
508d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
509c4762a1bSJed Brown     }
510c4762a1bSJed Brown     break;
511d71ae5a4SJacob Faibussowitsch   default:
512d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %" PetscInt_FMT, testNum);
513c4762a1bSJed Brown   }
514c4762a1bSJed Brown   PetscFunctionReturn(0);
515c4762a1bSJed Brown }
516c4762a1bSJed Brown 
517d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateSimplex_3D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm)
518d71ae5a4SJacob Faibussowitsch {
519c4762a1bSJed Brown   PetscInt    testNum = user->testNum, p;
520c4762a1bSJed Brown   PetscMPIInt rank, size;
521c4762a1bSJed Brown 
522c4762a1bSJed Brown   PetscFunctionBegin;
5239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
525c4762a1bSJed Brown   switch (testNum) {
526c4762a1bSJed Brown   case 0:
52763a3b9bcSJacob Faibussowitsch     PetscCheck(size == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 2 processes", testNum);
528c4762a1bSJed Brown     switch (rank) {
5299371c9d4SSatish Balay     case 0: {
530c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 2, numCorners = 4;
531a4a685f2SJacob Faibussowitsch       const PetscInt cells[4]        = {0, 2, 1, 3};
532c4762a1bSJed Brown       PetscReal      coords[6]       = {0.0, 0.0, -0.5, 0.0, -0.5, 0.0};
533c4762a1bSJed Brown       PetscInt       markerPoints[8] = {1, 1, 2, 1, 3, 1, 4, 1};
534c4762a1bSJed Brown 
5359566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5369566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5379371c9d4SSatish Balay     } break;
5389371c9d4SSatish Balay     case 1: {
539c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 3, numCorners = 4;
540a4a685f2SJacob Faibussowitsch       const PetscInt cells[4]        = {1, 2, 4, 3};
541c4762a1bSJed Brown       PetscReal      coords[9]       = {1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5};
542c4762a1bSJed Brown       PetscInt       markerPoints[8] = {1, 1, 2, 1, 3, 1, 4, 1};
543c4762a1bSJed Brown 
5449566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5459566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5469371c9d4SSatish Balay     } break;
547d71ae5a4SJacob Faibussowitsch     default:
548d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
549c4762a1bSJed Brown     }
550c4762a1bSJed Brown     break;
551d71ae5a4SJacob Faibussowitsch   default:
552d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %" PetscInt_FMT, testNum);
553c4762a1bSJed Brown   }
554c4762a1bSJed Brown   if (user->testOrientIF) {
555c4762a1bSJed Brown     PetscInt ifp[] = {8, 6};
556c4762a1bSJed Brown 
5579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*dm, "Mesh before orientation"));
5589566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(*dm, NULL, "-before_orientation_dm_view"));
559c4762a1bSJed Brown     /* rotate interface face ifp[rank] by given orientation ornt[rank] */
5609566063dSJacob Faibussowitsch     PetscCall(DMPlexOrientPoint(*dm, ifp[rank], user->ornt[rank]));
5619566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(*dm, NULL, "-before_orientation_dm_view"));
5629566063dSJacob Faibussowitsch     PetscCall(DMPlexCheckFaces(*dm, 0));
5639566063dSJacob Faibussowitsch     PetscCall(DMPlexOrientInterface_Internal(*dm));
5649566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm, "Orientation test PASSED\n"));
565c4762a1bSJed Brown   }
566c4762a1bSJed Brown   PetscFunctionReturn(0);
567c4762a1bSJed Brown }
568c4762a1bSJed Brown 
569d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateQuad_2D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm)
570d71ae5a4SJacob Faibussowitsch {
571c4762a1bSJed Brown   PetscInt    testNum = user->testNum, p;
572c4762a1bSJed Brown   PetscMPIInt rank, size;
573c4762a1bSJed Brown 
574c4762a1bSJed Brown   PetscFunctionBegin;
5759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5769566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
577c4762a1bSJed Brown   switch (testNum) {
578c4762a1bSJed Brown   case 0:
57963a3b9bcSJacob Faibussowitsch     PetscCheck(size == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 2 processes", testNum);
580c4762a1bSJed Brown     switch (rank) {
5819371c9d4SSatish Balay     case 0: {
582c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 3, numCorners = 4;
583a4a685f2SJacob Faibussowitsch       const PetscInt cells[4]            = {0, 1, 2, 3};
584c4762a1bSJed Brown       PetscReal      coords[6]           = {-0.5, 0.0, 0.0, 0.0, 0.0, 1.0};
585c4762a1bSJed Brown       PetscInt       markerPoints[4 * 2] = {1, 1, 2, 1, 3, 1, 4, 1};
586c4762a1bSJed Brown 
5879566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5889566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5899371c9d4SSatish Balay     } break;
5909371c9d4SSatish Balay     case 1: {
591c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 3, numCorners = 4;
592a4a685f2SJacob Faibussowitsch       const PetscInt cells[4]            = {1, 4, 5, 2};
593c4762a1bSJed Brown       PetscReal      coords[6]           = {-0.5, 1.0, 0.5, 0.0, 0.5, 1.0};
594c4762a1bSJed Brown       PetscInt       markerPoints[4 * 2] = {1, 1, 2, 1, 3, 1, 4, 1};
595c4762a1bSJed Brown 
5969566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
5979566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
5989371c9d4SSatish Balay     } break;
599d71ae5a4SJacob Faibussowitsch     default:
600d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
601c4762a1bSJed Brown     }
602c4762a1bSJed Brown     break;
603d71ae5a4SJacob Faibussowitsch   default:
604d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %" PetscInt_FMT, testNum);
605c4762a1bSJed Brown   }
606c4762a1bSJed Brown   PetscFunctionReturn(0);
607c4762a1bSJed Brown }
608c4762a1bSJed Brown 
609d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateHex_3D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm)
610d71ae5a4SJacob Faibussowitsch {
611c4762a1bSJed Brown   PetscInt    testNum = user->testNum, p;
612c4762a1bSJed Brown   PetscMPIInt rank, size;
613c4762a1bSJed Brown 
614c4762a1bSJed Brown   PetscFunctionBegin;
6159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
617c4762a1bSJed Brown   switch (testNum) {
618c4762a1bSJed Brown   case 0:
61963a3b9bcSJacob Faibussowitsch     PetscCheck(size == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %" PetscInt_FMT " only for 2 processes", testNum);
620c4762a1bSJed Brown     switch (rank) {
6219371c9d4SSatish Balay     case 0: {
622c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 6, numCorners = 8;
623a4a685f2SJacob Faibussowitsch       const PetscInt cells[8]            = {0, 3, 2, 1, 4, 5, 6, 7};
624c4762a1bSJed 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};
625c4762a1bSJed Brown       PetscInt       markerPoints[8 * 2] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1};
626c4762a1bSJed Brown 
6279566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
6289566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
6299371c9d4SSatish Balay     } break;
6309371c9d4SSatish Balay     case 1: {
631c4762a1bSJed Brown       const PetscInt numCells = 1, numVertices = 6, numCorners = 8;
632a4a685f2SJacob Faibussowitsch       const PetscInt cells[8]            = {1, 2, 9, 8, 5, 10, 11, 6};
633c4762a1bSJed 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};
634c4762a1bSJed Brown       PetscInt       markerPoints[8 * 2] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1};
635c4762a1bSJed Brown 
6369566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm));
6379566063dSJacob Faibussowitsch       for (p = 0; p < 4; ++p) PetscCall(DMSetLabelValue(*dm, "marker", markerPoints[p * 2], markerPoints[p * 2 + 1]));
6389371c9d4SSatish Balay     } break;
639d71ae5a4SJacob Faibussowitsch     default:
640d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank);
641c4762a1bSJed Brown     }
642c4762a1bSJed Brown     break;
643d71ae5a4SJacob Faibussowitsch   default:
644d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %" PetscInt_FMT, testNum);
645c4762a1bSJed Brown   }
646c4762a1bSJed Brown   PetscFunctionReturn(0);
647c4762a1bSJed Brown }
648c4762a1bSJed Brown 
649d71ae5a4SJacob Faibussowitsch static PetscErrorCode CustomView(DM dm, PetscViewer v)
650d71ae5a4SJacob Faibussowitsch {
651c4762a1bSJed Brown   DMPlexInterpolatedFlag interpolated;
652c4762a1bSJed Brown   PetscBool              distributed;
653c4762a1bSJed Brown 
654c4762a1bSJed Brown   PetscFunctionBegin;
6559566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
6569566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpolated));
6579566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(v, "DMPlexIsDistributed: %s\n", PetscBools[distributed]));
6589566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(v, "DMPlexIsInterpolatedCollective: %s\n", DMPlexInterpolatedFlags[interpolated]));
659c4762a1bSJed Brown   PetscFunctionReturn(0);
660c4762a1bSJed Brown }
661c4762a1bSJed Brown 
662d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateMeshFromFile(MPI_Comm comm, AppCtx *user, DM *dm, DM *serialDM)
663d71ae5a4SJacob Faibussowitsch {
664c4762a1bSJed Brown   const char *filename     = user->filename;
665c4762a1bSJed Brown   PetscBool   testHeavy    = user->testHeavy;
666c4762a1bSJed Brown   PetscBool   interpCreate = user->interpolate == CREATE ? PETSC_TRUE : PETSC_FALSE;
667c4762a1bSJed Brown   PetscBool   distributed  = PETSC_FALSE;
668c4762a1bSJed Brown 
669c4762a1bSJed Brown   PetscFunctionBegin;
670c4762a1bSJed Brown   *serialDM = NULL;
6719566063dSJacob Faibussowitsch   if (testHeavy && interpCreate) PetscCall(DMPlexSetOrientInterface_Private(NULL, PETSC_FALSE));
6729566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePush(stage[0]));
6739566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromFile(comm, filename, "ex18_plex", interpCreate, dm)); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */
6749566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePop());
6759566063dSJacob Faibussowitsch   if (testHeavy && interpCreate) PetscCall(DMPlexSetOrientInterface_Private(NULL, PETSC_TRUE));
6769566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(*dm, &distributed));
6779566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(comm, "DMPlexCreateFromFile produced %s mesh.\n", distributed ? "distributed" : "serial"));
678c4762a1bSJed Brown   if (testHeavy && distributed) {
6799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsSetValue(NULL, "-dm_plex_hdf5_force_sequential", NULL));
6809566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(comm, filename, "ex18_plex", interpCreate, serialDM));
6819566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(*serialDM, &distributed));
68228b400f6SJacob Faibussowitsch     PetscCheck(!distributed, comm, PETSC_ERR_PLIB, "unable to create a serial DM from file");
683c4762a1bSJed Brown   }
6849566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(*dm, &user->dim));
685c4762a1bSJed Brown   PetscFunctionReturn(0);
686c4762a1bSJed Brown }
687c4762a1bSJed Brown 
688d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm)
689d71ae5a4SJacob Faibussowitsch {
690c4762a1bSJed Brown   PetscPartitioner part;
691c4762a1bSJed Brown   PortableBoundary boundary       = NULL;
692c4762a1bSJed Brown   DM               serialDM       = NULL;
693c4762a1bSJed Brown   PetscBool        cellSimplex    = user->cellSimplex;
694c4762a1bSJed Brown   PetscBool        useGenerator   = user->useGenerator;
695c4762a1bSJed Brown   PetscBool        interpCreate   = user->interpolate == CREATE ? PETSC_TRUE : PETSC_FALSE;
696c4762a1bSJed Brown   PetscBool        interpSerial   = user->interpolate == AFTER_CREATE ? PETSC_TRUE : PETSC_FALSE;
697c4762a1bSJed Brown   PetscBool        interpParallel = user->interpolate == AFTER_DISTRIBUTE ? PETSC_TRUE : PETSC_FALSE;
698c4762a1bSJed Brown   PetscBool        testHeavy      = user->testHeavy;
699c4762a1bSJed Brown   PetscMPIInt      rank;
700c4762a1bSJed Brown 
701c4762a1bSJed Brown   PetscFunctionBegin;
7029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
703c4762a1bSJed Brown   if (user->filename[0]) {
7049566063dSJacob Faibussowitsch     PetscCall(CreateMeshFromFile(comm, user, dm, &serialDM));
705c4762a1bSJed Brown   } else if (useGenerator) {
7069566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePush(stage[0]));
7079566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateBoxMesh(comm, user->dim, cellSimplex, user->faces, NULL, NULL, NULL, interpCreate, dm));
7089566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePop());
709c4762a1bSJed Brown   } else {
7109566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePush(stage[0]));
711c4762a1bSJed Brown     switch (user->dim) {
712d71ae5a4SJacob Faibussowitsch     case 1:
713d71ae5a4SJacob Faibussowitsch       PetscCall(CreateMesh_1D(comm, interpCreate, user, dm));
714d71ae5a4SJacob Faibussowitsch       break;
715c4762a1bSJed Brown     case 2:
716c4762a1bSJed Brown       if (cellSimplex) {
7179566063dSJacob Faibussowitsch         PetscCall(CreateSimplex_2D(comm, interpCreate, user, dm));
718c4762a1bSJed Brown       } else {
7199566063dSJacob Faibussowitsch         PetscCall(CreateQuad_2D(comm, interpCreate, user, dm));
720c4762a1bSJed Brown       }
721c4762a1bSJed Brown       break;
722c4762a1bSJed Brown     case 3:
723c4762a1bSJed Brown       if (cellSimplex) {
7249566063dSJacob Faibussowitsch         PetscCall(CreateSimplex_3D(comm, interpCreate, user, dm));
725c4762a1bSJed Brown       } else {
7269566063dSJacob Faibussowitsch         PetscCall(CreateHex_3D(comm, interpCreate, user, dm));
727c4762a1bSJed Brown       }
728c4762a1bSJed Brown       break;
729d71ae5a4SJacob Faibussowitsch     default:
730d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, user->dim);
731c4762a1bSJed Brown     }
7329566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePop());
733c4762a1bSJed Brown   }
734*da81f932SPierre Jolivet   PetscCheck(user->ncoords % user->dim == 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "length of coordinates array %" PetscInt_FMT " must be divisible by spatial dimension %" PetscInt_FMT, user->ncoords, user->dim);
7359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*dm, "Original Mesh"));
7369566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(*dm, NULL, "-orig_dm_view"));
737c4762a1bSJed Brown 
738c4762a1bSJed Brown   if (interpSerial) {
739c4762a1bSJed Brown     DM idm;
740c4762a1bSJed Brown 
7419566063dSJacob Faibussowitsch     if (testHeavy) PetscCall(DMPlexSetOrientInterface_Private(*dm, PETSC_FALSE));
7429566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePush(stage[2]));
7439566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm)); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */
7449566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePop());
7459566063dSJacob Faibussowitsch     if (testHeavy) PetscCall(DMPlexSetOrientInterface_Private(*dm, PETSC_TRUE));
7469566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
747c4762a1bSJed Brown     *dm = idm;
7489566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*dm, "Interpolated Mesh"));
7499566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(*dm, NULL, "-intp_dm_view"));
750c4762a1bSJed Brown   }
751c4762a1bSJed Brown 
752c4762a1bSJed Brown   /* Set partitioner options */
7539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPartitioner(*dm, &part));
754c4762a1bSJed Brown   if (part) {
7559566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetType(part, PETSCPARTITIONERSIMPLE));
7569566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
757c4762a1bSJed Brown   }
758c4762a1bSJed Brown 
7599566063dSJacob Faibussowitsch   if (user->customView) PetscCall(CustomView(*dm, PETSC_VIEWER_STDOUT_(comm)));
760c4762a1bSJed Brown   if (testHeavy) {
761c4762a1bSJed Brown     PetscBool distributed;
762c4762a1bSJed Brown 
7639566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(*dm, &distributed));
764c4762a1bSJed Brown     if (!serialDM && !distributed) {
765c4762a1bSJed Brown       serialDM = *dm;
7669566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)*dm));
767c4762a1bSJed Brown     }
76848a46eb9SPierre Jolivet     if (serialDM) PetscCall(DMPlexGetExpandedBoundary_Private(serialDM, &boundary));
769c4762a1bSJed Brown     if (boundary) {
770c4762a1bSJed Brown       /* check DM which has been created in parallel and already interpolated */
7719566063dSJacob Faibussowitsch       PetscCall(DMPlexCheckPointSFHeavy(*dm, boundary));
772c4762a1bSJed Brown     }
773c4762a1bSJed Brown     /* Orient interface because it could be deliberately skipped above. It is idempotent. */
7749566063dSJacob Faibussowitsch     PetscCall(DMPlexOrientInterface_Internal(*dm));
775c4762a1bSJed Brown   }
776c4762a1bSJed Brown   if (user->distribute) {
777c4762a1bSJed Brown     DM pdm = NULL;
778c4762a1bSJed Brown 
779c4762a1bSJed Brown     /* Redistribute mesh over processes using that partitioner */
7809566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePush(stage[1]));
7819566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(*dm, 0, NULL, &pdm));
7829566063dSJacob Faibussowitsch     PetscCall(PetscLogStagePop());
783c4762a1bSJed Brown     if (pdm) {
7849566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
785c4762a1bSJed Brown       *dm = pdm;
7869566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)*dm, "Redistributed Mesh"));
7879566063dSJacob Faibussowitsch       PetscCall(DMViewFromOptions(*dm, NULL, "-dist_dm_view"));
788c4762a1bSJed Brown     }
789c4762a1bSJed Brown 
790c4762a1bSJed Brown     if (interpParallel) {
791c4762a1bSJed Brown       DM idm;
792c4762a1bSJed Brown 
7939566063dSJacob Faibussowitsch       if (testHeavy) PetscCall(DMPlexSetOrientInterface_Private(*dm, PETSC_FALSE));
7949566063dSJacob Faibussowitsch       PetscCall(PetscLogStagePush(stage[2]));
7959566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm)); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */
7969566063dSJacob Faibussowitsch       PetscCall(PetscLogStagePop());
7979566063dSJacob Faibussowitsch       if (testHeavy) PetscCall(DMPlexSetOrientInterface_Private(*dm, PETSC_TRUE));
7989566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
799c4762a1bSJed Brown       *dm = idm;
8009566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)*dm, "Interpolated Redistributed Mesh"));
8019566063dSJacob Faibussowitsch       PetscCall(DMViewFromOptions(*dm, NULL, "-intp_dm_view"));
802c4762a1bSJed Brown     }
803c4762a1bSJed Brown   }
804c4762a1bSJed Brown   if (testHeavy) {
8051baa6e33SBarry Smith     if (boundary) PetscCall(DMPlexCheckPointSFHeavy(*dm, boundary));
806c4762a1bSJed Brown     /* Orient interface because it could be deliberately skipped above. It is idempotent. */
8079566063dSJacob Faibussowitsch     PetscCall(DMPlexOrientInterface_Internal(*dm));
808c4762a1bSJed Brown   }
809c4762a1bSJed Brown 
8109566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*dm, "Parallel Mesh"));
8119566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE));
8129566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(*dm));
8139566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view"));
814c4762a1bSJed Brown 
8159566063dSJacob Faibussowitsch   if (user->customView) PetscCall(CustomView(*dm, PETSC_VIEWER_STDOUT_(comm)));
8169566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&serialDM));
8179566063dSJacob Faibussowitsch   PetscCall(PortableBoundaryDestroy(&boundary));
818c4762a1bSJed Brown   PetscFunctionReturn(0);
819c4762a1bSJed Brown }
820c4762a1bSJed Brown 
821d3e1f4ccSVaclav Hapla #define ps2d(number) ((double)PetscRealPart(number))
822d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode coord2str(char buf[], size_t len, PetscInt dim, const PetscScalar coords[], PetscReal tol)
823d71ae5a4SJacob Faibussowitsch {
824c4762a1bSJed Brown   PetscFunctionBegin;
82508401ef6SPierre Jolivet   PetscCheck(dim <= 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "dim must be less than or equal 3");
826c4762a1bSJed Brown   if (tol >= 1e-3) {
827c4762a1bSJed Brown     switch (dim) {
828d71ae5a4SJacob Faibussowitsch     case 1:
829d71ae5a4SJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, len, "(%12.3f)", ps2d(coords[0])));
830d71ae5a4SJacob Faibussowitsch     case 2:
831d71ae5a4SJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, len, "(%12.3f, %12.3f)", ps2d(coords[0]), ps2d(coords[1])));
832d71ae5a4SJacob Faibussowitsch     case 3:
833d71ae5a4SJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, len, "(%12.3f, %12.3f, %12.3f)", ps2d(coords[0]), ps2d(coords[1]), ps2d(coords[2])));
834c4762a1bSJed Brown     }
835c4762a1bSJed Brown   } else {
836c4762a1bSJed Brown     switch (dim) {
837d71ae5a4SJacob Faibussowitsch     case 1:
838d71ae5a4SJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, len, "(%12.6f)", ps2d(coords[0])));
839d71ae5a4SJacob Faibussowitsch     case 2:
840d71ae5a4SJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, len, "(%12.6f, %12.6f)", ps2d(coords[0]), ps2d(coords[1])));
841d71ae5a4SJacob Faibussowitsch     case 3:
842d71ae5a4SJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, len, "(%12.6f, %12.6f, %12.6f)", ps2d(coords[0]), ps2d(coords[1]), ps2d(coords[2])));
843c4762a1bSJed Brown     }
844c4762a1bSJed Brown   }
845c4762a1bSJed Brown   PetscFunctionReturn(0);
846c4762a1bSJed Brown }
847c4762a1bSJed Brown 
848d71ae5a4SJacob Faibussowitsch static PetscErrorCode ViewVerticesFromCoords(DM dm, Vec coordsVec, PetscReal tol, PetscViewer viewer)
849d71ae5a4SJacob Faibussowitsch {
850d3e1f4ccSVaclav Hapla   PetscInt           dim, i, npoints;
851d3e1f4ccSVaclav Hapla   IS                 pointsIS;
852d3e1f4ccSVaclav Hapla   const PetscInt    *points;
853d3e1f4ccSVaclav Hapla   const PetscScalar *coords;
854c4762a1bSJed Brown   char               coordstr[128];
855c4762a1bSJed Brown   MPI_Comm           comm;
856c4762a1bSJed Brown   PetscMPIInt        rank;
857c4762a1bSJed Brown 
858c4762a1bSJed Brown   PetscFunctionBegin;
8599566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8609566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8619566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8629566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8639566063dSJacob Faibussowitsch   PetscCall(DMPlexFindVertices(dm, coordsVec, tol, &pointsIS));
8649566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(pointsIS, &points));
8659566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(pointsIS, &npoints));
8669566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordsVec, &coords));
867c4762a1bSJed Brown   for (i = 0; i < npoints; i++) {
8689566063dSJacob Faibussowitsch     PetscCall(coord2str(coordstr, sizeof(coordstr), dim, &coords[i * dim], tol));
8699566063dSJacob Faibussowitsch     if (rank == 0 && i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "-----\n"));
87063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %s --> points[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, coordstr, i, points[i]));
8719566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
872c4762a1bSJed Brown   }
8739566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8749566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordsVec, &coords));
8759566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(pointsIS, &points));
8769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pointsIS));
877c4762a1bSJed Brown   PetscFunctionReturn(0);
878c4762a1bSJed Brown }
879c4762a1bSJed Brown 
880d71ae5a4SJacob Faibussowitsch static PetscErrorCode TestExpandPoints(DM dm, AppCtx *user)
881d71ae5a4SJacob Faibussowitsch {
882c4762a1bSJed Brown   IS            is;
883c4762a1bSJed Brown   PetscSection *sects;
884c4762a1bSJed Brown   IS           *iss;
885c4762a1bSJed Brown   PetscInt      d, depth;
886c4762a1bSJed Brown   PetscMPIInt   rank;
887c4762a1bSJed Brown   PetscViewer   viewer = PETSC_VIEWER_STDOUT_WORLD, sviewer;
888c4762a1bSJed Brown 
889c4762a1bSJed Brown   PetscFunctionBegin;
8909566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
891dd400576SPatrick Sanan   if (user->testExpandPointsEmpty && rank == 0) {
8929566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, &is));
893c4762a1bSJed Brown   } else {
8949566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, user->nPointsToExpand, user->pointsToExpand, PETSC_USE_POINTER, &is));
895c4762a1bSJed Brown   }
8969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, is, &depth, &iss, &sects));
8979566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
8989566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(sviewer, "[%d] ==========================\n", rank));
899c4762a1bSJed Brown   for (d = depth - 1; d >= 0; d--) {
900c4762a1bSJed Brown     IS        checkIS;
901c4762a1bSJed Brown     PetscBool flg;
902c4762a1bSJed Brown 
90363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(sviewer, "depth %" PetscInt_FMT " ---------------\n", d));
9049566063dSJacob Faibussowitsch     PetscCall(PetscSectionView(sects[d], sviewer));
9059566063dSJacob Faibussowitsch     PetscCall(ISView(iss[d], sviewer));
906c4762a1bSJed Brown     /* check reverse operation */
907c4762a1bSJed Brown     if (d < depth - 1) {
9089566063dSJacob Faibussowitsch       PetscCall(DMPlexExpandedConesToFaces_Private(dm, iss[d], sects[d], &checkIS));
9099566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(checkIS, iss[d + 1], &flg));
91028b400f6SJacob Faibussowitsch       PetscCheck(flg, PetscObjectComm((PetscObject)checkIS), PETSC_ERR_PLIB, "DMPlexExpandedConesToFaces_Private produced wrong IS");
9119566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&checkIS));
912c4762a1bSJed Brown     }
913c4762a1bSJed Brown   }
9149566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
9159566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
9169566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, is, &depth, &iss, &sects));
9179566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
918c4762a1bSJed Brown   PetscFunctionReturn(0);
919c4762a1bSJed Brown }
920c4762a1bSJed Brown 
921d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexExpandedConesToFaces_Private(DM dm, IS is, PetscSection section, IS *newis)
922d71ae5a4SJacob Faibussowitsch {
923c4762a1bSJed Brown   PetscInt        n, n1, ncone, numCoveredPoints, o, p, q, start, end;
924c4762a1bSJed Brown   const PetscInt *coveredPoints;
925c4762a1bSJed Brown   const PetscInt *arr, *cone;
926c4762a1bSJed Brown   PetscInt       *newarr;
927c4762a1bSJed Brown 
928c4762a1bSJed Brown   PetscFunctionBegin;
9299566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
9309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n1));
9319566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &start, &end));
93263a3b9bcSJacob Faibussowitsch   PetscCheck(n == n1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "IS size = %" PetscInt_FMT " != %" PetscInt_FMT " = section storage size", n, n1);
9339566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &arr));
9349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(end - start, &newarr));
935c4762a1bSJed Brown   for (q = start; q < end; q++) {
9369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, q, &ncone));
9379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, q, &o));
938c4762a1bSJed Brown     cone = &arr[o];
939c4762a1bSJed Brown     if (ncone == 1) {
940c4762a1bSJed Brown       numCoveredPoints = 1;
941c4762a1bSJed Brown       p                = cone[0];
942c4762a1bSJed Brown     } else {
943c4762a1bSJed Brown       PetscInt i;
944c4762a1bSJed Brown       p = PETSC_MAX_INT;
9459371c9d4SSatish Balay       for (i = 0; i < ncone; i++)
9469371c9d4SSatish Balay         if (cone[i] < 0) {
9479371c9d4SSatish Balay           p = -1;
9489371c9d4SSatish Balay           break;
9499371c9d4SSatish Balay         }
950c4762a1bSJed Brown       if (p >= 0) {
9519566063dSJacob Faibussowitsch         PetscCall(DMPlexGetJoin(dm, ncone, cone, &numCoveredPoints, &coveredPoints));
95263a3b9bcSJacob Faibussowitsch         PetscCheck(numCoveredPoints <= 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "more than one covered points for section point %" PetscInt_FMT, q);
953c4762a1bSJed Brown         if (numCoveredPoints) p = coveredPoints[0];
954c4762a1bSJed Brown         else p = -2;
9559566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(dm, ncone, cone, &numCoveredPoints, &coveredPoints));
956c4762a1bSJed Brown       }
957c4762a1bSJed Brown     }
958c4762a1bSJed Brown     newarr[q - start] = p;
959c4762a1bSJed Brown   }
9609566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &arr));
9619566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, end - start, newarr, PETSC_OWN_POINTER, newis));
962c4762a1bSJed Brown   PetscFunctionReturn(0);
963c4762a1bSJed Brown }
964c4762a1bSJed Brown 
965d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexExpandedVerticesToFaces_Private(DM dm, IS boundary_expanded_is, PetscInt depth, PetscSection sections[], IS *boundary_is)
966d71ae5a4SJacob Faibussowitsch {
967c4762a1bSJed Brown   PetscInt d;
968c4762a1bSJed Brown   IS       is, newis;
969c4762a1bSJed Brown 
970c4762a1bSJed Brown   PetscFunctionBegin;
971c4762a1bSJed Brown   is = boundary_expanded_is;
9729566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
973c4762a1bSJed Brown   for (d = 0; d < depth - 1; ++d) {
9749566063dSJacob Faibussowitsch     PetscCall(DMPlexExpandedConesToFaces_Private(dm, is, sections[d], &newis));
9759566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
976c4762a1bSJed Brown     is = newis;
977c4762a1bSJed Brown   }
978c4762a1bSJed Brown   *boundary_is = is;
979c4762a1bSJed Brown   PetscFunctionReturn(0);
980c4762a1bSJed Brown }
981c4762a1bSJed Brown 
9829371c9d4SSatish Balay #define CHKERRQI(incall, ierr) \
983ad540459SPierre Jolivet   if (ierr) incall = PETSC_FALSE;
984c4762a1bSJed Brown 
985d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelViewFromOptionsOnComm_Private(DMLabel label, const char optionname[], MPI_Comm comm)
986d71ae5a4SJacob Faibussowitsch {
987c4762a1bSJed Brown   PetscViewer       viewer;
988c4762a1bSJed Brown   PetscBool         flg;
989c4762a1bSJed Brown   static PetscBool  incall = PETSC_FALSE;
990c4762a1bSJed Brown   PetscViewerFormat format;
991c4762a1bSJed Brown 
992c4762a1bSJed Brown   PetscFunctionBegin;
993c4762a1bSJed Brown   if (incall) PetscFunctionReturn(0);
994c4762a1bSJed Brown   incall = PETSC_TRUE;
9955f80ce2aSJacob Faibussowitsch   CHKERRQI(incall, PetscOptionsGetViewer(comm, ((PetscObject)label)->options, ((PetscObject)label)->prefix, optionname, &viewer, &format, &flg));
996c4762a1bSJed Brown   if (flg) {
9975f80ce2aSJacob Faibussowitsch     CHKERRQI(incall, PetscViewerPushFormat(viewer, format));
9985f80ce2aSJacob Faibussowitsch     CHKERRQI(incall, DMLabelView(label, viewer));
9995f80ce2aSJacob Faibussowitsch     CHKERRQI(incall, PetscViewerPopFormat(viewer));
10005f80ce2aSJacob Faibussowitsch     CHKERRQI(incall, PetscViewerDestroy(&viewer));
1001c4762a1bSJed Brown   }
1002c4762a1bSJed Brown   incall = PETSC_FALSE;
1003c4762a1bSJed Brown   PetscFunctionReturn(0);
1004c4762a1bSJed Brown }
1005c4762a1bSJed Brown 
1006c4762a1bSJed Brown /* TODO: this is hotfixing DMLabelGetStratumIS() - it should be fixed systematically instead */
1007d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelGetStratumISOnComm_Private(DMLabel label, PetscInt value, MPI_Comm comm, IS *is)
1008d71ae5a4SJacob Faibussowitsch {
1009c4762a1bSJed Brown   IS tmpis;
1010c4762a1bSJed Brown 
1011c4762a1bSJed Brown   PetscFunctionBegin;
10129566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, &tmpis));
10139566063dSJacob Faibussowitsch   if (!tmpis) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, &tmpis));
10149566063dSJacob Faibussowitsch   PetscCall(ISOnComm(tmpis, comm, PETSC_COPY_VALUES, is));
10159566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&tmpis));
1016c4762a1bSJed Brown   PetscFunctionReturn(0);
1017c4762a1bSJed Brown }
1018c4762a1bSJed Brown 
1019c4762a1bSJed Brown /* currently only for simple PetscSection without fields or constraints */
1020d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionReplicate_Private(MPI_Comm comm, PetscMPIInt rootrank, PetscSection sec0, PetscSection *secout)
1021d71ae5a4SJacob Faibussowitsch {
1022c4762a1bSJed Brown   PetscSection sec;
1023c4762a1bSJed Brown   PetscInt     chart[2], p;
1024c4762a1bSJed Brown   PetscInt    *dofarr;
1025c4762a1bSJed Brown   PetscMPIInt  rank;
1026c4762a1bSJed Brown 
1027c4762a1bSJed Brown   PetscFunctionBegin;
10289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
102948a46eb9SPierre Jolivet   if (rank == rootrank) PetscCall(PetscSectionGetChart(sec0, &chart[0], &chart[1]));
10309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(chart, 2, MPIU_INT, rootrank, comm));
10319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(chart[1] - chart[0], &dofarr));
1032c4762a1bSJed Brown   if (rank == rootrank) {
103348a46eb9SPierre Jolivet     for (p = chart[0]; p < chart[1]; p++) PetscCall(PetscSectionGetDof(sec0, p, &dofarr[p - chart[0]]));
1034c4762a1bSJed Brown   }
10359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(dofarr, chart[1] - chart[0], MPIU_INT, rootrank, comm));
10369566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &sec));
10379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(sec, chart[0], chart[1]));
103848a46eb9SPierre Jolivet   for (p = chart[0]; p < chart[1]; p++) PetscCall(PetscSectionSetDof(sec, p, dofarr[p - chart[0]]));
10399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(sec));
10409566063dSJacob Faibussowitsch   PetscCall(PetscFree(dofarr));
1041c4762a1bSJed Brown   *secout = sec;
1042c4762a1bSJed Brown   PetscFunctionReturn(0);
1043c4762a1bSJed Brown }
1044c4762a1bSJed Brown 
1045d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexExpandedVerticesCoordinatesToFaces_Private(DM ipdm, PortableBoundary bnd, IS *face_is)
1046d71ae5a4SJacob Faibussowitsch {
1047c4762a1bSJed Brown   IS faces_expanded_is;
1048c4762a1bSJed Brown 
1049c4762a1bSJed Brown   PetscFunctionBegin;
10509566063dSJacob Faibussowitsch   PetscCall(DMPlexFindVertices(ipdm, bnd->coordinates, 0.0, &faces_expanded_is));
10519566063dSJacob Faibussowitsch   PetscCall(DMPlexExpandedVerticesToFaces_Private(ipdm, faces_expanded_is, bnd->depth, bnd->sections, face_is));
10529566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&faces_expanded_is));
1053c4762a1bSJed Brown   PetscFunctionReturn(0);
1054c4762a1bSJed Brown }
1055c4762a1bSJed Brown 
1056c4762a1bSJed Brown /* hack disabling DMPlexOrientInterface() call in DMPlexInterpolate() via -dm_plex_interpolate_orient_interfaces option */
1057d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSetOrientInterface_Private(DM dm, PetscBool enable)
1058d71ae5a4SJacob Faibussowitsch {
1059c4762a1bSJed Brown   PetscOptions     options = NULL;
1060c4762a1bSJed Brown   const char      *prefix  = NULL;
1061c4762a1bSJed Brown   const char       opt[]   = "-dm_plex_interpolate_orient_interfaces";
1062c4762a1bSJed Brown   char             prefix_opt[512];
1063c4762a1bSJed Brown   PetscBool        flg, set;
1064c4762a1bSJed Brown   static PetscBool wasSetTrue = PETSC_FALSE;
1065c4762a1bSJed Brown 
1066c4762a1bSJed Brown   PetscFunctionBegin;
1067c4762a1bSJed Brown   if (dm) {
10689566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
1069c4762a1bSJed Brown     options = ((PetscObject)dm)->options;
1070c4762a1bSJed Brown   }
10719566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(prefix_opt, "-"));
10729566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(prefix_opt, prefix, sizeof(prefix_opt)));
10739566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(prefix_opt, &opt[1], sizeof(prefix_opt)));
10749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(options, prefix, opt, &flg, &set));
1075c4762a1bSJed Brown   if (!enable) {
1076c4762a1bSJed Brown     if (set && flg) wasSetTrue = PETSC_TRUE;
10779566063dSJacob Faibussowitsch     PetscCall(PetscOptionsSetValue(options, prefix_opt, "0"));
1078c4762a1bSJed Brown   } else if (set && !flg) {
1079c4762a1bSJed Brown     if (wasSetTrue) {
10809566063dSJacob Faibussowitsch       PetscCall(PetscOptionsSetValue(options, prefix_opt, "1"));
1081c4762a1bSJed Brown     } else {
1082c4762a1bSJed Brown       /* default is PETSC_TRUE */
10839566063dSJacob Faibussowitsch       PetscCall(PetscOptionsClearValue(options, prefix_opt));
1084c4762a1bSJed Brown     }
1085c4762a1bSJed Brown     wasSetTrue = PETSC_FALSE;
1086c4762a1bSJed Brown   }
108776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
10889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(options, prefix, opt, &flg, &set));
10891dca8a05SBarry Smith     PetscCheck(!set || flg == enable, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "PetscOptionsSetValue did not have the desired effect");
1090c4762a1bSJed Brown   }
1091c4762a1bSJed Brown   PetscFunctionReturn(0);
1092c4762a1bSJed Brown }
1093c4762a1bSJed Brown 
1094c4762a1bSJed Brown /* get coordinate description of the whole-domain boundary */
1095d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetExpandedBoundary_Private(DM dm, PortableBoundary *boundary)
1096d71ae5a4SJacob Faibussowitsch {
1097c4762a1bSJed Brown   PortableBoundary       bnd0, bnd;
1098c4762a1bSJed Brown   MPI_Comm               comm;
1099c4762a1bSJed Brown   DM                     idm;
1100c4762a1bSJed Brown   DMLabel                label;
1101c4762a1bSJed Brown   PetscInt               d;
1102c4762a1bSJed Brown   const char             boundaryName[] = "DMPlexDistributeInterpolateMarkInterface_boundary";
1103c4762a1bSJed Brown   IS                     boundary_is;
1104c4762a1bSJed Brown   IS                    *boundary_expanded_iss;
1105c4762a1bSJed Brown   PetscMPIInt            rootrank = 0;
1106c4762a1bSJed Brown   PetscMPIInt            rank, size;
1107c4762a1bSJed Brown   PetscInt               value = 1;
1108c4762a1bSJed Brown   DMPlexInterpolatedFlag intp;
1109c4762a1bSJed Brown   PetscBool              flg;
1110c4762a1bSJed Brown 
1111c4762a1bSJed Brown   PetscFunctionBegin;
11129566063dSJacob Faibussowitsch   PetscCall(PetscNew(&bnd));
11139566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
11169566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
111728b400f6SJacob Faibussowitsch   PetscCheck(!flg, comm, PETSC_ERR_ARG_WRONG, "serial DM (all points on one rank) needed");
1118c4762a1bSJed Brown 
1119c4762a1bSJed Brown   /* interpolate serial DM if not yet interpolated */
11209566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(dm, &intp));
1121c4762a1bSJed Brown   if (intp == DMPLEX_INTERPOLATED_FULL) {
1122c4762a1bSJed Brown     idm = dm;
11239566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1124c4762a1bSJed Brown   } else {
11259566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
11269566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(idm, NULL, "-idm_view"));
1127c4762a1bSJed Brown   }
1128c4762a1bSJed Brown 
1129c4762a1bSJed Brown   /* mark whole-domain boundary of the serial DM */
11309566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, boundaryName, &label));
11319566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(idm, label));
11329566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(idm, value, label));
11339566063dSJacob Faibussowitsch   PetscCall(DMLabelViewFromOptionsOnComm_Private(label, "-idm_boundary_view", comm));
11349566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, &boundary_is));
1135c4762a1bSJed Brown 
1136c4762a1bSJed Brown   /* translate to coordinates */
11379566063dSJacob Faibussowitsch   PetscCall(PetscNew(&bnd0));
11389566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocalSetUp(idm));
1139c4762a1bSJed Brown   if (rank == rootrank) {
11409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeRecursive(idm, boundary_is, &bnd0->depth, &boundary_expanded_iss, &bnd0->sections));
11419566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocalTuple(dm, boundary_expanded_iss[0], NULL, &bnd0->coordinates));
1142c4762a1bSJed Brown     /* self-check */
1143c4762a1bSJed Brown     {
1144c4762a1bSJed Brown       IS is0;
11459566063dSJacob Faibussowitsch       PetscCall(DMPlexExpandedVerticesCoordinatesToFaces_Private(idm, bnd0, &is0));
11469566063dSJacob Faibussowitsch       PetscCall(ISEqual(is0, boundary_is, &flg));
114728b400f6SJacob Faibussowitsch       PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DMPlexExpandedVerticesCoordinatesToFaces_Private produced a wrong IS");
11489566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
1149c4762a1bSJed Brown     }
1150c4762a1bSJed Brown   } else {
11519566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, 0, &bnd0->coordinates));
1152c4762a1bSJed Brown   }
1153c4762a1bSJed Brown 
1154c4762a1bSJed Brown   {
1155c4762a1bSJed Brown     Vec        tmp;
1156c4762a1bSJed Brown     VecScatter sc;
1157c4762a1bSJed Brown     IS         xis;
1158c4762a1bSJed Brown     PetscInt   n;
1159c4762a1bSJed Brown 
1160c4762a1bSJed Brown     /* just convert seq vectors to mpi vector */
11619566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(bnd0->coordinates, &n));
11629566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(&n, 1, MPIU_INT, rootrank, comm));
1163c4762a1bSJed Brown     if (rank == rootrank) {
11649566063dSJacob Faibussowitsch       PetscCall(VecCreateMPI(comm, n, n, &tmp));
1165c4762a1bSJed Brown     } else {
11669566063dSJacob Faibussowitsch       PetscCall(VecCreateMPI(comm, 0, n, &tmp));
1167c4762a1bSJed Brown     }
11689566063dSJacob Faibussowitsch     PetscCall(VecCopy(bnd0->coordinates, tmp));
11699566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&bnd0->coordinates));
1170c4762a1bSJed Brown     bnd0->coordinates = tmp;
1171c4762a1bSJed Brown 
1172c4762a1bSJed Brown     /* replicate coordinates from root rank to all ranks */
11739566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, n, n * size, &bnd->coordinates));
11749566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, n, 0, 1, &xis));
11759566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(bnd0->coordinates, xis, bnd->coordinates, NULL, &sc));
11769566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sc, bnd0->coordinates, bnd->coordinates, INSERT_VALUES, SCATTER_FORWARD));
11779566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sc, bnd0->coordinates, bnd->coordinates, INSERT_VALUES, SCATTER_FORWARD));
11789566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sc));
11799566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&xis));
1180c4762a1bSJed Brown   }
1181c4762a1bSJed Brown   bnd->depth = bnd0->depth;
11829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&bnd->depth, 1, MPIU_INT, rootrank, comm));
11839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(bnd->depth, &bnd->sections));
118448a46eb9SPierre Jolivet   for (d = 0; d < bnd->depth; d++) PetscCall(PetscSectionReplicate_Private(comm, rootrank, (rank == rootrank) ? bnd0->sections[d] : NULL, &bnd->sections[d]));
1185c4762a1bSJed Brown 
118648a46eb9SPierre Jolivet   if (rank == rootrank) PetscCall(DMPlexRestoreConeRecursive(idm, boundary_is, &bnd0->depth, &boundary_expanded_iss, &bnd0->sections));
11879566063dSJacob Faibussowitsch   PetscCall(PortableBoundaryDestroy(&bnd0));
11889566063dSJacob Faibussowitsch   PetscCall(DMRemoveLabelBySelf(idm, &label, PETSC_TRUE));
11899566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
11909566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&boundary_is));
11919566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&idm));
1192c4762a1bSJed Brown   *boundary = bnd;
1193c4762a1bSJed Brown   PetscFunctionReturn(0);
1194c4762a1bSJed Brown }
1195c4762a1bSJed Brown 
1196c4762a1bSJed Brown /* get faces of inter-partition interface */
1197d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetInterfaceFaces_Private(DM ipdm, IS boundary_faces_is, IS *interface_faces_is)
1198d71ae5a4SJacob Faibussowitsch {
1199c4762a1bSJed Brown   MPI_Comm               comm;
1200c4762a1bSJed Brown   DMLabel                label;
1201c4762a1bSJed Brown   IS                     part_boundary_faces_is;
1202c4762a1bSJed Brown   const char             partBoundaryName[] = "DMPlexDistributeInterpolateMarkInterface_partBoundary";
1203c4762a1bSJed Brown   PetscInt               value              = 1;
1204c4762a1bSJed Brown   DMPlexInterpolatedFlag intp;
1205c4762a1bSJed Brown 
1206c4762a1bSJed Brown   PetscFunctionBegin;
12079566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)ipdm, &comm));
12089566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(ipdm, &intp));
120908401ef6SPierre Jolivet   PetscCheck(intp == DMPLEX_INTERPOLATED_FULL, comm, PETSC_ERR_ARG_WRONG, "only for fully interpolated DMPlex");
1210c4762a1bSJed Brown 
1211c4762a1bSJed Brown   /* get ipdm partition boundary (partBoundary) */
12129566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, partBoundaryName, &label));
12139566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(ipdm, label));
12149566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(ipdm, value, label));
12159566063dSJacob Faibussowitsch   PetscCall(DMLabelViewFromOptionsOnComm_Private(label, "-ipdm_part_boundary_view", comm));
12169566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumISOnComm_Private(label, value, comm, &part_boundary_faces_is));
12179566063dSJacob Faibussowitsch   PetscCall(DMRemoveLabelBySelf(ipdm, &label, PETSC_TRUE));
12189566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
1219c4762a1bSJed Brown 
1220c4762a1bSJed Brown   /* remove ipdm whole-domain boundary (boundary_faces_is) from ipdm partition boundary (part_boundary_faces_is), resulting just in inter-partition interface */
12219566063dSJacob Faibussowitsch   PetscCall(ISDifference(part_boundary_faces_is, boundary_faces_is, interface_faces_is));
12229566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&part_boundary_faces_is));
1223c4762a1bSJed Brown   PetscFunctionReturn(0);
1224c4762a1bSJed Brown }
1225c4762a1bSJed Brown 
1226c4762a1bSJed Brown /* compute inter-partition interface including edges and vertices */
1227d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeCompleteInterface_Private(DM ipdm, IS interface_faces_is, IS *interface_is)
1228d71ae5a4SJacob Faibussowitsch {
1229c4762a1bSJed Brown   DMLabel                label;
1230c4762a1bSJed Brown   PetscInt               value           = 1;
1231c4762a1bSJed Brown   const char             interfaceName[] = "DMPlexDistributeInterpolateMarkInterface_interface";
1232c4762a1bSJed Brown   DMPlexInterpolatedFlag intp;
1233c4762a1bSJed Brown   MPI_Comm               comm;
1234c4762a1bSJed Brown 
1235c4762a1bSJed Brown   PetscFunctionBegin;
12369566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)ipdm, &comm));
12379566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(ipdm, &intp));
123808401ef6SPierre Jolivet   PetscCheck(intp == DMPLEX_INTERPOLATED_FULL, comm, PETSC_ERR_ARG_WRONG, "only for fully interpolated DMPlex");
1239c4762a1bSJed Brown 
12409566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, interfaceName, &label));
12419566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(ipdm, label));
12429566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, interface_faces_is));
12439566063dSJacob Faibussowitsch   PetscCall(DMLabelViewFromOptionsOnComm_Private(label, "-interface_faces_view", comm));
12449566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(ipdm, label));
12459566063dSJacob Faibussowitsch   PetscCall(DMLabelViewFromOptionsOnComm_Private(label, "-interface_view", comm));
12469566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumISOnComm_Private(label, value, comm, interface_is));
12479566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*interface_is, "interface_is"));
12489566063dSJacob Faibussowitsch   PetscCall(ISViewFromOptions(*interface_is, NULL, "-interface_is_view"));
12499566063dSJacob Faibussowitsch   PetscCall(DMRemoveLabelBySelf(ipdm, &label, PETSC_TRUE));
12509566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
1251c4762a1bSJed Brown   PetscFunctionReturn(0);
1252c4762a1bSJed Brown }
1253c4762a1bSJed Brown 
1254d71ae5a4SJacob Faibussowitsch static PetscErrorCode PointSFGetOutwardInterfacePoints(PetscSF sf, IS *is)
1255d71ae5a4SJacob Faibussowitsch {
1256c4762a1bSJed Brown   PetscInt        n;
1257c4762a1bSJed Brown   const PetscInt *arr;
1258c4762a1bSJed Brown 
1259c4762a1bSJed Brown   PetscFunctionBegin;
12609566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &n, &arr, NULL));
12619566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)sf), n, arr, PETSC_USE_POINTER, is));
1262c4762a1bSJed Brown   PetscFunctionReturn(0);
1263c4762a1bSJed Brown }
1264c4762a1bSJed Brown 
1265d71ae5a4SJacob Faibussowitsch static PetscErrorCode PointSFGetInwardInterfacePoints(PetscSF sf, IS *is)
1266d71ae5a4SJacob Faibussowitsch {
1267c4762a1bSJed Brown   PetscInt        n;
1268c4762a1bSJed Brown   const PetscInt *rootdegree;
1269c4762a1bSJed Brown   PetscInt       *arr;
1270c4762a1bSJed Brown 
1271c4762a1bSJed Brown   PetscFunctionBegin;
12729566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
12739566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
12749566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
12759566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeMultiRootOriginalNumbering(sf, rootdegree, &n, &arr));
12769566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)sf), n, arr, PETSC_OWN_POINTER, is));
1277c4762a1bSJed Brown   PetscFunctionReturn(0);
1278c4762a1bSJed Brown }
1279c4762a1bSJed Brown 
1280d71ae5a4SJacob Faibussowitsch static PetscErrorCode PointSFGetInterfacePoints_Private(PetscSF pointSF, IS *is)
1281d71ae5a4SJacob Faibussowitsch {
1282c4762a1bSJed Brown   IS pointSF_out_is, pointSF_in_is;
1283c4762a1bSJed Brown 
1284c4762a1bSJed Brown   PetscFunctionBegin;
12859566063dSJacob Faibussowitsch   PetscCall(PointSFGetOutwardInterfacePoints(pointSF, &pointSF_out_is));
12869566063dSJacob Faibussowitsch   PetscCall(PointSFGetInwardInterfacePoints(pointSF, &pointSF_in_is));
12879566063dSJacob Faibussowitsch   PetscCall(ISExpand(pointSF_out_is, pointSF_in_is, is));
12889566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pointSF_out_is));
12899566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pointSF_in_is));
1290c4762a1bSJed Brown   PetscFunctionReturn(0);
1291c4762a1bSJed Brown }
1292c4762a1bSJed Brown 
12935f80ce2aSJacob Faibussowitsch #define CHKERRMY(ierr) PetscCheck(!ierr, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PointSF is wrong. Unable to show details!")
1294c4762a1bSJed Brown 
1295d71ae5a4SJacob Faibussowitsch static PetscErrorCode ViewPointsWithType_Internal(DM dm, IS pointsIS, PetscViewer v)
1296d71ae5a4SJacob Faibussowitsch {
1297c4762a1bSJed Brown   DMLabel         label;
1298c4762a1bSJed Brown   PetscSection    coordsSection;
1299c4762a1bSJed Brown   Vec             coordsVec;
1300c4762a1bSJed Brown   PetscScalar    *coordsScalar;
1301c4762a1bSJed Brown   PetscInt        coneSize, depth, dim, i, p, npoints;
1302c4762a1bSJed Brown   const PetscInt *points;
1303c4762a1bSJed Brown 
1304c4762a1bSJed Brown   PetscFunctionBegin;
13059566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
13069566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordsSection));
13079566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsVec));
13089566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordsVec, &coordsScalar));
13099566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(pointsIS, &npoints));
13109566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(pointsIS, &points));
13119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
13129566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(v));
1313c4762a1bSJed Brown   for (i = 0; i < npoints; i++) {
1314c4762a1bSJed Brown     p = points[i];
13159566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &depth));
1316c4762a1bSJed Brown     if (!depth) {
1317d3e1f4ccSVaclav Hapla       PetscInt n, o;
1318c4762a1bSJed Brown       char     coordstr[128];
1319c4762a1bSJed Brown 
13209566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordsSection, p, &n));
13219566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordsSection, p, &o));
13229566063dSJacob Faibussowitsch       PetscCall(coord2str(coordstr, sizeof(coordstr), n, &coordsScalar[o], 1.0));
132363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(v, "vertex %" PetscInt_FMT " w/ coordinates %s\n", p, coordstr));
1324c4762a1bSJed Brown     } else {
1325c4762a1bSJed Brown       char entityType[16];
1326c4762a1bSJed Brown 
1327c4762a1bSJed Brown       switch (depth) {
1328d71ae5a4SJacob Faibussowitsch       case 1:
1329d71ae5a4SJacob Faibussowitsch         PetscCall(PetscStrcpy(entityType, "edge"));
1330d71ae5a4SJacob Faibussowitsch         break;
1331d71ae5a4SJacob Faibussowitsch       case 2:
1332d71ae5a4SJacob Faibussowitsch         PetscCall(PetscStrcpy(entityType, "face"));
1333d71ae5a4SJacob Faibussowitsch         break;
1334d71ae5a4SJacob Faibussowitsch       case 3:
1335d71ae5a4SJacob Faibussowitsch         PetscCall(PetscStrcpy(entityType, "cell"));
1336d71ae5a4SJacob Faibussowitsch         break;
1337d71ae5a4SJacob Faibussowitsch       default:
1338d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Only for depth <= 3");
1339c4762a1bSJed Brown       }
134048a46eb9SPierre Jolivet       if (depth == dim && dim < 3) PetscCall(PetscStrlcat(entityType, " (cell)", sizeof(entityType)));
134163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(v, "%s %" PetscInt_FMT "\n", entityType, p));
1342c4762a1bSJed Brown     }
13439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1344c4762a1bSJed Brown     if (coneSize) {
1345c4762a1bSJed Brown       const PetscInt *cone;
1346c4762a1bSJed Brown       IS              coneIS;
1347c4762a1bSJed Brown 
13489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, p, &cone));
13499566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, coneSize, cone, PETSC_USE_POINTER, &coneIS));
13509566063dSJacob Faibussowitsch       PetscCall(ViewPointsWithType_Internal(dm, coneIS, v));
13519566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&coneIS));
1352c4762a1bSJed Brown     }
1353c4762a1bSJed Brown   }
13549566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(v));
13559566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordsVec, &coordsScalar));
13569566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(pointsIS, &points));
1357c4762a1bSJed Brown   PetscFunctionReturn(0);
1358c4762a1bSJed Brown }
1359c4762a1bSJed Brown 
1360d71ae5a4SJacob Faibussowitsch static PetscErrorCode ViewPointsWithType(DM dm, IS points, PetscViewer v)
1361d71ae5a4SJacob Faibussowitsch {
1362c4762a1bSJed Brown   PetscBool   flg;
1363c4762a1bSJed Brown   PetscInt    npoints;
1364c4762a1bSJed Brown   PetscMPIInt rank;
1365c4762a1bSJed Brown 
1366c4762a1bSJed Brown   PetscFunctionBegin;
13679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &flg));
136828b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Only for ASCII viewer");
13699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank));
13709566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(v));
13719566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &npoints));
1372c4762a1bSJed Brown   if (npoints) {
13739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(v, "[%d] --------\n", rank));
13749566063dSJacob Faibussowitsch     PetscCall(ViewPointsWithType_Internal(dm, points, v));
1375c4762a1bSJed Brown   }
13769566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(v));
13779566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(v));
1378c4762a1bSJed Brown   PetscFunctionReturn(0);
1379c4762a1bSJed Brown }
1380c4762a1bSJed Brown 
1381d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComparePointSFWithInterface_Private(DM ipdm, IS interface_is)
1382d71ae5a4SJacob Faibussowitsch {
1383c4762a1bSJed Brown   PetscSF     pointsf;
1384c4762a1bSJed Brown   IS          pointsf_is;
1385c4762a1bSJed Brown   PetscBool   flg;
1386c4762a1bSJed Brown   MPI_Comm    comm;
1387c4762a1bSJed Brown   PetscMPIInt size;
1388c4762a1bSJed Brown 
1389c4762a1bSJed Brown   PetscFunctionBegin;
13909566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)ipdm, &comm));
13919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
13929566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(ipdm, &pointsf));
1393c4762a1bSJed Brown   if (pointsf) {
1394c4762a1bSJed Brown     PetscInt nroots;
13959566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(pointsf, &nroots, NULL, NULL, NULL));
1396c4762a1bSJed Brown     if (nroots < 0) pointsf = NULL; /* uninitialized SF */
1397c4762a1bSJed Brown   }
1398c4762a1bSJed Brown   if (!pointsf) {
1399c4762a1bSJed Brown     PetscInt N = 0;
14009566063dSJacob Faibussowitsch     if (interface_is) PetscCall(ISGetSize(interface_is, &N));
140128b400f6SJacob Faibussowitsch     PetscCheck(!N, comm, PETSC_ERR_PLIB, "interface_is should be NULL or empty for PointSF being NULL");
1402c4762a1bSJed Brown     PetscFunctionReturn(0);
1403c4762a1bSJed Brown   }
1404c4762a1bSJed Brown 
1405c4762a1bSJed Brown   /* get PointSF points as IS pointsf_is */
14069566063dSJacob Faibussowitsch   PetscCall(PointSFGetInterfacePoints_Private(pointsf, &pointsf_is));
1407c4762a1bSJed Brown 
1408c4762a1bSJed Brown   /* compare pointsf_is with interface_is */
14099566063dSJacob Faibussowitsch   PetscCall(ISEqual(interface_is, pointsf_is, &flg));
14109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &flg, 1, MPIU_BOOL, MPI_LAND, comm));
1411c4762a1bSJed Brown   if (!flg) {
1412c4762a1bSJed Brown     IS          pointsf_extra_is, pointsf_missing_is;
1413c4762a1bSJed Brown     PetscViewer errv = PETSC_VIEWER_STDERR_(comm);
14145f80ce2aSJacob Faibussowitsch     CHKERRMY(ISDifference(interface_is, pointsf_is, &pointsf_missing_is));
14155f80ce2aSJacob Faibussowitsch     CHKERRMY(ISDifference(pointsf_is, interface_is, &pointsf_extra_is));
14165f80ce2aSJacob Faibussowitsch     CHKERRMY(PetscViewerASCIIPrintf(errv, "Points missing in PointSF:\n"));
14175f80ce2aSJacob Faibussowitsch     CHKERRMY(ViewPointsWithType(ipdm, pointsf_missing_is, errv));
14185f80ce2aSJacob Faibussowitsch     CHKERRMY(PetscViewerASCIIPrintf(errv, "Extra points in PointSF:\n"));
14195f80ce2aSJacob Faibussowitsch     CHKERRMY(ViewPointsWithType(ipdm, pointsf_extra_is, errv));
14205f80ce2aSJacob Faibussowitsch     CHKERRMY(ISDestroy(&pointsf_extra_is));
14215f80ce2aSJacob Faibussowitsch     CHKERRMY(ISDestroy(&pointsf_missing_is));
1422c4762a1bSJed Brown     SETERRQ(comm, PETSC_ERR_PLIB, "PointSF is wrong! See details above.");
1423c4762a1bSJed Brown   }
14249566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pointsf_is));
1425c4762a1bSJed Brown   PetscFunctionReturn(0);
1426c4762a1bSJed Brown }
1427c4762a1bSJed Brown 
1428c4762a1bSJed Brown /* remove faces & edges from label, leave just vertices */
1429d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexISFilterVertices_Private(DM dm, IS points)
1430d71ae5a4SJacob Faibussowitsch {
1431c4762a1bSJed Brown   PetscInt vStart, vEnd;
1432c4762a1bSJed Brown   MPI_Comm comm;
1433c4762a1bSJed Brown 
1434c4762a1bSJed Brown   PetscFunctionBegin;
14359566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
14379566063dSJacob Faibussowitsch   PetscCall(ISGeneralFilter(points, vStart, vEnd));
1438c4762a1bSJed Brown   PetscFunctionReturn(0);
1439c4762a1bSJed Brown }
1440c4762a1bSJed Brown 
1441c4762a1bSJed Brown /*
14422e58f0efSBarry Smith   DMPlexCheckPointSFHeavy - Thoroughly test that the PointSF after parallel DMPlexInterpolate() includes exactly all interface points.
1443c4762a1bSJed Brown 
1444c4762a1bSJed Brown   Collective
1445c4762a1bSJed Brown 
1446c4762a1bSJed Brown   Input Parameters:
1447c4762a1bSJed Brown . dm - The DMPlex object
1448c4762a1bSJed Brown 
1449c4762a1bSJed Brown   Notes:
1450c4762a1bSJed Brown   The input DMPlex must be serial (one partition has all points, the other partitions have no points).
1451c4762a1bSJed 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).
1452c4762a1bSJed Brown   This is mainly intended for debugging/testing purposes.
1453c4762a1bSJed Brown 
1454c4762a1bSJed Brown   Algorithm:
1455c4762a1bSJed Brown   1. boundary faces of the serial version of the whole mesh are found using DMPlexMarkBoundaryFaces()
1456c4762a1bSJed 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
1457c4762a1bSJed Brown   3. the mesh is distributed or loaded in parallel
1458c4762a1bSJed Brown   4. boundary faces of the distributed mesh are reconstructed from PortableBoundary using DMPlexFindVertices()
1459c4762a1bSJed Brown   5. partition boundary faces of the parallel mesh are found using DMPlexMarkBoundaryFaces()
1460c4762a1bSJed Brown   6. partition interfaces are computed as set difference of partition boundary faces minus the reconstructed boundary
1461c4762a1bSJed 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
1462c4762a1bSJed Brown 
1463c4762a1bSJed Brown   Level: developer
1464c4762a1bSJed Brown 
1465c4762a1bSJed Brown .seealso: DMGetPointSF(), DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces()
1466c4762a1bSJed Brown */
1467d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCheckPointSFHeavy(DM dm, PortableBoundary bnd)
1468d71ae5a4SJacob Faibussowitsch {
1469c4762a1bSJed Brown   DM                     ipdm = NULL;
1470c4762a1bSJed Brown   IS                     boundary_faces_is, interface_faces_is, interface_is;
1471c4762a1bSJed Brown   DMPlexInterpolatedFlag intp;
1472c4762a1bSJed Brown   MPI_Comm               comm;
1473c4762a1bSJed Brown 
1474c4762a1bSJed Brown   PetscFunctionBegin;
14759566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
1476c4762a1bSJed Brown 
14779566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolatedCollective(dm, &intp));
1478c4762a1bSJed Brown   if (intp == DMPLEX_INTERPOLATED_FULL) {
1479c4762a1bSJed Brown     ipdm = dm;
1480c4762a1bSJed Brown   } else {
1481c4762a1bSJed Brown     /* create temporary interpolated DM if input DM is not interpolated */
14829566063dSJacob Faibussowitsch     PetscCall(DMPlexSetOrientInterface_Private(dm, PETSC_FALSE));
14839566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &ipdm)); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexComparePointSFWithInterface_Private() below */
14849566063dSJacob Faibussowitsch     PetscCall(DMPlexSetOrientInterface_Private(dm, PETSC_TRUE));
1485c4762a1bSJed Brown   }
14869566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(ipdm, NULL, "-ipdm_view"));
1487c4762a1bSJed Brown 
1488c4762a1bSJed Brown   /* recover ipdm whole-domain boundary faces from the expanded vertices coordinates */
14899566063dSJacob Faibussowitsch   PetscCall(DMPlexExpandedVerticesCoordinatesToFaces_Private(ipdm, bnd, &boundary_faces_is));
1490c4762a1bSJed Brown   /* get inter-partition interface faces (interface_faces_is)*/
14919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetInterfaceFaces_Private(ipdm, boundary_faces_is, &interface_faces_is));
1492c4762a1bSJed Brown   /* compute inter-partition interface including edges and vertices (interface_is) */
14939566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeCompleteInterface_Private(ipdm, interface_faces_is, &interface_is));
1494c4762a1bSJed Brown   /* destroy immediate ISs */
14959566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&boundary_faces_is));
14969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&interface_faces_is));
1497c4762a1bSJed Brown 
1498c4762a1bSJed Brown   /* for uninterpolated case, keep just vertices in interface */
1499c4762a1bSJed Brown   if (!intp) {
15009566063dSJacob Faibussowitsch     PetscCall(DMPlexISFilterVertices_Private(ipdm, interface_is));
15019566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&ipdm));
1502c4762a1bSJed Brown   }
1503c4762a1bSJed Brown 
1504c4762a1bSJed Brown   /* compare PointSF with the boundary reconstructed from coordinates */
15059566063dSJacob Faibussowitsch   PetscCall(DMPlexComparePointSFWithInterface_Private(dm, interface_is));
15069566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(comm, "DMPlexCheckPointSFHeavy PASSED\n"));
15079566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&interface_is));
1508c4762a1bSJed Brown   PetscFunctionReturn(0);
1509c4762a1bSJed Brown }
1510c4762a1bSJed Brown 
1511d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
1512d71ae5a4SJacob Faibussowitsch {
1513c4762a1bSJed Brown   DM     dm;
1514c4762a1bSJed Brown   AppCtx user;
1515c4762a1bSJed Brown 
1516327415f7SBarry Smith   PetscFunctionBeginUser;
15179566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
15189566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("create", &stage[0]));
15199566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("distribute", &stage[1]));
15209566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("interpolate", &stage[2]));
15219566063dSJacob Faibussowitsch   PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user));
15229566063dSJacob Faibussowitsch   PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm));
152348a46eb9SPierre Jolivet   if (user.nPointsToExpand) PetscCall(TestExpandPoints(dm, &user));
1524c4762a1bSJed Brown   if (user.ncoords) {
1525d3e1f4ccSVaclav Hapla     Vec coords;
1526d3e1f4ccSVaclav Hapla 
15279566063dSJacob Faibussowitsch     PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, user.ncoords, user.ncoords, user.coords, &coords));
15289566063dSJacob Faibussowitsch     PetscCall(ViewVerticesFromCoords(dm, coords, user.coordsTol, PETSC_VIEWER_STDOUT_WORLD));
15299566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coords));
1530c4762a1bSJed Brown   }
15319566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm));
15329566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
1533b122ec5aSJacob Faibussowitsch   return 0;
1534c4762a1bSJed Brown }
1535c4762a1bSJed Brown 
1536c4762a1bSJed Brown /*TEST
1537c4762a1bSJed Brown 
1538c4762a1bSJed Brown   testset:
1539c4762a1bSJed Brown     nsize: 2
1540c4762a1bSJed Brown     args: -dm_view ascii::ascii_info_detail
1541c4762a1bSJed Brown     args: -dm_plex_check_all
1542c4762a1bSJed Brown     test:
1543c4762a1bSJed Brown       suffix: 1_tri_dist0
1544c4762a1bSJed Brown       args: -distribute 0 -interpolate {{none create}separate output}
1545c4762a1bSJed Brown     test:
1546c4762a1bSJed Brown       suffix: 1_tri_dist1
1547c4762a1bSJed Brown       args: -distribute 1 -interpolate {{none create after_distribute}separate output}
1548c4762a1bSJed Brown     test:
1549c4762a1bSJed Brown       suffix: 1_quad_dist0
1550c4762a1bSJed Brown       args: -cell_simplex 0 -distribute 0 -interpolate {{none create}separate output}
1551c4762a1bSJed Brown     test:
1552c4762a1bSJed Brown       suffix: 1_quad_dist1
1553c4762a1bSJed Brown       args: -cell_simplex 0 -distribute 1 -interpolate {{none create after_distribute}separate output}
1554c4762a1bSJed Brown     test:
1555c4762a1bSJed Brown       suffix: 1_1d_dist1
1556c4762a1bSJed Brown       args: -dim 1 -distribute 1
1557c4762a1bSJed Brown 
1558c4762a1bSJed Brown   testset:
1559c4762a1bSJed Brown     nsize: 3
1560c4762a1bSJed Brown     args: -testnum 1 -interpolate create
1561c4762a1bSJed Brown     args: -dm_plex_check_all
1562c4762a1bSJed Brown     test:
1563c4762a1bSJed Brown       suffix: 2
1564c4762a1bSJed Brown       args: -dm_view ascii::ascii_info_detail
1565c4762a1bSJed Brown     test:
1566c4762a1bSJed Brown       suffix: 2a
1567c4762a1bSJed Brown       args: -dm_plex_check_cones_conform_on_interfaces_verbose
1568c4762a1bSJed Brown     test:
1569c4762a1bSJed Brown       suffix: 2b
1570c4762a1bSJed Brown       args: -test_expand_points 0,1,2,5,6
1571c4762a1bSJed Brown     test:
1572c4762a1bSJed Brown       suffix: 2c
1573c4762a1bSJed Brown       args: -test_expand_points 0,1,2,5,6 -test_expand_points_empty
1574c4762a1bSJed Brown 
1575c4762a1bSJed Brown   testset:
1576c4762a1bSJed Brown     # the same as 1% for 3D
1577c4762a1bSJed Brown     nsize: 2
1578c4762a1bSJed Brown     args: -dim 3 -dm_view ascii::ascii_info_detail
1579c4762a1bSJed Brown     args: -dm_plex_check_all
1580c4762a1bSJed Brown     test:
1581c4762a1bSJed Brown       suffix: 4_tet_dist0
1582c4762a1bSJed Brown       args: -distribute 0 -interpolate {{none create}separate output}
1583c4762a1bSJed Brown     test:
1584c4762a1bSJed Brown       suffix: 4_tet_dist1
1585c4762a1bSJed Brown       args: -distribute 1 -interpolate {{none create after_distribute}separate output}
1586c4762a1bSJed Brown     test:
1587c4762a1bSJed Brown       suffix: 4_hex_dist0
1588c4762a1bSJed Brown       args: -cell_simplex 0 -distribute 0 -interpolate {{none create}separate output}
1589c4762a1bSJed Brown     test:
1590c4762a1bSJed Brown       suffix: 4_hex_dist1
1591c4762a1bSJed Brown       args: -cell_simplex 0 -distribute 1 -interpolate {{none create after_distribute}separate output}
1592c4762a1bSJed Brown 
1593c4762a1bSJed Brown   test:
1594c4762a1bSJed Brown     # the same as 4_tet_dist0 but test different initial orientations
1595c4762a1bSJed Brown     suffix: 4_tet_test_orient
1596c4762a1bSJed Brown     nsize: 2
1597c4762a1bSJed Brown     args: -dim 3 -distribute 0
1598c4762a1bSJed Brown     args: -dm_plex_check_all
1599c4762a1bSJed Brown     args: -rotate_interface_0 {{0 1 2 11 12 13}}
1600c4762a1bSJed Brown     args: -rotate_interface_1 {{0 1 2 11 12 13}}
1601c4762a1bSJed Brown 
1602c4762a1bSJed Brown   testset:
1603c4762a1bSJed Brown     requires: exodusii
1604c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/TwoQuads.exo
1605c4762a1bSJed Brown     args: -dm_view ascii::ascii_info_detail
1606c4762a1bSJed Brown     args: -dm_plex_check_all
1607c4762a1bSJed Brown     args: -custom_view
1608c4762a1bSJed Brown     test:
1609c4762a1bSJed Brown       suffix: 5_seq
1610c4762a1bSJed Brown       nsize: 1
1611c4762a1bSJed Brown       args: -distribute 0 -interpolate {{none create}separate output}
1612c4762a1bSJed Brown     test:
161330602db0SMatthew G. Knepley       # Detail viewing in a non-distributed mesh is broken because the DMLabelView() is collective, but the label is not shared
1614c4762a1bSJed Brown       suffix: 5_dist0
1615c4762a1bSJed Brown       nsize: 2
161630602db0SMatthew G. Knepley       args: -distribute 0 -interpolate {{none create}separate output} -dm_view
1617c4762a1bSJed Brown     test:
1618c4762a1bSJed Brown       suffix: 5_dist1
1619c4762a1bSJed Brown       nsize: 2
1620c4762a1bSJed Brown       args: -distribute 1 -interpolate {{none create after_distribute}separate output}
1621c4762a1bSJed Brown 
1622c4762a1bSJed Brown   testset:
1623c4762a1bSJed Brown     nsize: {{1 2 4}}
1624c4762a1bSJed Brown     args: -use_generator
1625c4762a1bSJed Brown     args: -dm_plex_check_all
1626c4762a1bSJed Brown     args: -distribute -interpolate none
1627c4762a1bSJed Brown     test:
1628c4762a1bSJed Brown       suffix: 6_tri
1629c4762a1bSJed Brown       requires: triangle
1630c0517cd5SMatthew G. Knepley       args: -faces {{2,2  1,3  7,4}} -cell_simplex 1 -dm_generator triangle
1631c4762a1bSJed Brown     test:
1632c4762a1bSJed Brown       suffix: 6_quad
1633c4762a1bSJed Brown       args: -faces {{2,2  1,3  7,4}} -cell_simplex 0
1634c4762a1bSJed Brown     test:
1635c4762a1bSJed Brown       suffix: 6_tet
1636c4762a1bSJed Brown       requires: ctetgen
1637c0517cd5SMatthew G. Knepley       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 1 -dm_generator ctetgen
1638c4762a1bSJed Brown     test:
1639c4762a1bSJed Brown       suffix: 6_hex
1640c4762a1bSJed Brown       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 0
1641c4762a1bSJed Brown   testset:
1642c4762a1bSJed Brown     nsize: {{1 2 4}}
1643c4762a1bSJed Brown     args: -use_generator
1644c4762a1bSJed Brown     args: -dm_plex_check_all
1645c4762a1bSJed Brown     args: -distribute -interpolate create
1646c4762a1bSJed Brown     test:
1647c4762a1bSJed Brown       suffix: 6_int_tri
1648c4762a1bSJed Brown       requires: triangle
1649c0517cd5SMatthew G. Knepley       args: -faces {{2,2  1,3  7,4}} -cell_simplex 1 -dm_generator triangle
1650c4762a1bSJed Brown     test:
1651c4762a1bSJed Brown       suffix: 6_int_quad
1652c4762a1bSJed Brown       args: -faces {{2,2  1,3  7,4}} -cell_simplex 0
1653c4762a1bSJed Brown     test:
1654c4762a1bSJed Brown       suffix: 6_int_tet
1655c4762a1bSJed Brown       requires: ctetgen
1656c0517cd5SMatthew G. Knepley       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 1 -dm_generator ctetgen
1657c4762a1bSJed Brown     test:
1658c4762a1bSJed Brown       suffix: 6_int_hex
1659c4762a1bSJed Brown       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 0
1660c4762a1bSJed Brown   testset:
1661c4762a1bSJed Brown     nsize: {{2 4}}
1662c4762a1bSJed Brown     args: -use_generator
1663c4762a1bSJed Brown     args: -dm_plex_check_all
1664c4762a1bSJed Brown     args: -distribute -interpolate after_distribute
1665c4762a1bSJed Brown     test:
1666c4762a1bSJed Brown       suffix: 6_parint_tri
1667c4762a1bSJed Brown       requires: triangle
1668c0517cd5SMatthew G. Knepley       args: -faces {{2,2  1,3  7,4}} -cell_simplex 1 -dm_generator triangle
1669c4762a1bSJed Brown     test:
1670c4762a1bSJed Brown       suffix: 6_parint_quad
1671c4762a1bSJed Brown       args: -faces {{2,2  1,3  7,4}} -cell_simplex 0
1672c4762a1bSJed Brown     test:
1673c4762a1bSJed Brown       suffix: 6_parint_tet
1674c4762a1bSJed Brown       requires: ctetgen
1675c0517cd5SMatthew G. Knepley       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 1 -dm_generator ctetgen
1676c4762a1bSJed Brown     test:
1677c4762a1bSJed Brown       suffix: 6_parint_hex
1678c4762a1bSJed Brown       args: -faces {{2,2,2  1,3,5  3,4,7}} -cell_simplex 0
1679c4762a1bSJed Brown 
1680c4762a1bSJed Brown   testset: # 7 EXODUS
1681c4762a1bSJed Brown     requires: exodusii
1682c4762a1bSJed Brown     args: -dm_plex_check_all
1683c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.exo
1684c4762a1bSJed Brown     args: -distribute
1685c4762a1bSJed Brown     test: # seq load, simple partitioner
1686c4762a1bSJed Brown       suffix: 7_exo
1687c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1688c4762a1bSJed Brown       args: -interpolate none
1689c4762a1bSJed Brown     test: # seq load, seq interpolation, simple partitioner
1690c4762a1bSJed Brown       suffix: 7_exo_int_simple
1691c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1692c4762a1bSJed Brown       args: -interpolate create
1693c4762a1bSJed Brown     test: # seq load, seq interpolation, metis partitioner
1694c4762a1bSJed Brown       suffix: 7_exo_int_metis
1695c4762a1bSJed Brown       requires: parmetis
1696c4762a1bSJed Brown       nsize: {{2 4 5}}
1697c4762a1bSJed Brown       args: -interpolate create
1698c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1699c4762a1bSJed Brown     test: # seq load, simple partitioner, par interpolation
1700c4762a1bSJed Brown       suffix: 7_exo_simple_int
1701c4762a1bSJed Brown       nsize: {{2 4 5}}
1702c4762a1bSJed Brown       args: -interpolate after_distribute
1703c4762a1bSJed Brown     test: # seq load, metis partitioner, par interpolation
1704c4762a1bSJed Brown       suffix: 7_exo_metis_int
1705c4762a1bSJed Brown       requires: parmetis
1706c4762a1bSJed Brown       nsize: {{2 4 5}}
1707c4762a1bSJed Brown       args: -interpolate after_distribute
1708c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1709c4762a1bSJed Brown 
1710c4762a1bSJed Brown   testset: # 7 HDF5 SEQUANTIAL LOAD
1711c4762a1bSJed Brown     requires: hdf5 !complex
1712c4762a1bSJed Brown     args: -dm_plex_check_all
1713c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf
1714c4762a1bSJed Brown     args: -dm_plex_hdf5_force_sequential
1715c4762a1bSJed Brown     args: -distribute
1716c4762a1bSJed Brown     test: # seq load, simple partitioner
1717c4762a1bSJed Brown       suffix: 7_seq_hdf5_simple
1718c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1719c4762a1bSJed Brown       args: -interpolate none
1720c4762a1bSJed Brown     test: # seq load, seq interpolation, simple partitioner
1721c4762a1bSJed Brown       suffix: 7_seq_hdf5_int_simple
1722c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1723c4762a1bSJed Brown       args: -interpolate after_create
1724c4762a1bSJed Brown     test: # seq load, seq interpolation, metis partitioner
1725c4762a1bSJed Brown       nsize: {{2 4 5}}
1726c4762a1bSJed Brown       suffix: 7_seq_hdf5_int_metis
1727c4762a1bSJed Brown       requires: parmetis
1728c4762a1bSJed Brown       args: -interpolate after_create
1729c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1730c4762a1bSJed Brown     test: # seq load, simple partitioner, par interpolation
1731c4762a1bSJed Brown       suffix: 7_seq_hdf5_simple_int
1732c4762a1bSJed Brown       nsize: {{2 4 5}}
1733c4762a1bSJed Brown       args: -interpolate after_distribute
1734c4762a1bSJed Brown     test: # seq load, metis partitioner, par interpolation
1735c4762a1bSJed Brown       nsize: {{2 4 5}}
1736c4762a1bSJed Brown       suffix: 7_seq_hdf5_metis_int
1737c4762a1bSJed Brown       requires: parmetis
1738c4762a1bSJed Brown       args: -interpolate after_distribute
1739c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1740c4762a1bSJed Brown 
1741c4762a1bSJed Brown   testset: # 7 HDF5 PARALLEL LOAD
1742c4762a1bSJed Brown     requires: hdf5 !complex
1743c4762a1bSJed Brown     nsize: {{2 4 5}}
1744c4762a1bSJed Brown     args: -dm_plex_check_all
1745c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf
1746c4762a1bSJed Brown     test: # par load
1747c4762a1bSJed Brown       suffix: 7_par_hdf5
1748c4762a1bSJed Brown       args: -interpolate none
1749c4762a1bSJed Brown     test: # par load, par interpolation
1750c4762a1bSJed Brown       suffix: 7_par_hdf5_int
1751c4762a1bSJed Brown       args: -interpolate after_create
1752c4762a1bSJed Brown     test: # par load, parmetis repartitioner
1753c4762a1bSJed Brown       TODO: Parallel partitioning of uninterpolated meshes not supported
1754c4762a1bSJed Brown       suffix: 7_par_hdf5_parmetis
1755c4762a1bSJed Brown       requires: parmetis
1756c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1757c4762a1bSJed Brown       args: -interpolate none
1758c4762a1bSJed Brown     test: # par load, par interpolation, parmetis repartitioner
1759c4762a1bSJed Brown       suffix: 7_par_hdf5_int_parmetis
1760c4762a1bSJed Brown       requires: parmetis
1761c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1762c4762a1bSJed Brown       args: -interpolate after_create
1763c4762a1bSJed Brown     test: # par load, parmetis partitioner, par interpolation
1764c4762a1bSJed Brown       TODO: Parallel partitioning of uninterpolated meshes not supported
1765c4762a1bSJed Brown       suffix: 7_par_hdf5_parmetis_int
1766c4762a1bSJed Brown       requires: parmetis
1767c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1768c4762a1bSJed Brown       args: -interpolate after_distribute
1769c4762a1bSJed Brown 
1770c4762a1bSJed Brown     test:
1771c4762a1bSJed Brown       suffix: 7_hdf5_hierarch
1772c4762a1bSJed Brown       requires: hdf5 ptscotch !complex
1773c4762a1bSJed Brown       nsize: {{2 3 4}separate output}
1774c4762a1bSJed Brown       args: -distribute
1775c4762a1bSJed Brown       args: -interpolate after_create
1776c4762a1bSJed Brown       args: -petscpartitioner_type matpartitioning -petscpartitioner_view ::ascii_info
1777c4762a1bSJed Brown       args: -mat_partitioning_type hierarch -mat_partitioning_hierarchical_nfineparts 2
1778c4762a1bSJed Brown       args: -mat_partitioning_hierarchical_coarseparttype ptscotch -mat_partitioning_hierarchical_fineparttype ptscotch
1779c4762a1bSJed Brown 
1780c4762a1bSJed Brown   test:
1781c4762a1bSJed Brown     suffix: 8
1782c4762a1bSJed Brown     requires: hdf5 !complex
1783c4762a1bSJed Brown     nsize: 4
1784c4762a1bSJed Brown     args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf
1785c4762a1bSJed Brown     args: -distribute 0 -interpolate after_create
1786c4762a1bSJed 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
1787c4762a1bSJed Brown     args: -dm_plex_check_all
1788c4762a1bSJed Brown     args: -custom_view
1789c4762a1bSJed Brown 
1790c4762a1bSJed Brown   testset: # 9 HDF5 SEQUANTIAL LOAD
1791c4762a1bSJed Brown     requires: hdf5 !complex datafilespath
1792c4762a1bSJed Brown     args: -dm_plex_check_all
1793c4762a1bSJed 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
1794c4762a1bSJed Brown     args: -dm_plex_hdf5_force_sequential
1795c4762a1bSJed Brown     args: -distribute
1796c4762a1bSJed Brown     test: # seq load, simple partitioner
1797c4762a1bSJed Brown       suffix: 9_seq_hdf5_simple
1798c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1799c4762a1bSJed Brown       args: -interpolate none
1800c4762a1bSJed Brown     test: # seq load, seq interpolation, simple partitioner
1801c4762a1bSJed Brown       suffix: 9_seq_hdf5_int_simple
1802c4762a1bSJed Brown       nsize: {{1 2 4 5}}
1803c4762a1bSJed Brown       args: -interpolate after_create
1804c4762a1bSJed Brown     test: # seq load, seq interpolation, metis partitioner
1805c4762a1bSJed Brown       nsize: {{2 4 5}}
1806c4762a1bSJed Brown       suffix: 9_seq_hdf5_int_metis
1807c4762a1bSJed Brown       requires: parmetis
1808c4762a1bSJed Brown       args: -interpolate after_create
1809c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1810c4762a1bSJed Brown     test: # seq load, simple partitioner, par interpolation
1811c4762a1bSJed Brown       suffix: 9_seq_hdf5_simple_int
1812c4762a1bSJed Brown       nsize: {{2 4 5}}
1813c4762a1bSJed Brown       args: -interpolate after_distribute
1814c4762a1bSJed Brown     test: # seq load, simple partitioner, par interpolation
1815c4762a1bSJed Brown       # This is like 9_seq_hdf5_simple_int but testing error output of DMPlexCheckPointSFHeavy().
1816c4762a1bSJed Brown       # Once 9_seq_hdf5_simple_int gets fixed, this one gets broken.
1817c4762a1bSJed Brown       # We can then provide an intentionally broken mesh instead.
1818c4762a1bSJed Brown       TODO: This test is broken because PointSF is fixed.
1819c4762a1bSJed Brown       suffix: 9_seq_hdf5_simple_int_err
1820c4762a1bSJed Brown       nsize: 4
1821c4762a1bSJed Brown       args: -interpolate after_distribute
1822c4762a1bSJed Brown       filter: sed -e "/PETSC ERROR/,$$d"
1823c4762a1bSJed Brown     test: # seq load, metis partitioner, par interpolation
1824c4762a1bSJed Brown       nsize: {{2 4 5}}
1825c4762a1bSJed Brown       suffix: 9_seq_hdf5_metis_int
1826c4762a1bSJed Brown       requires: parmetis
1827c4762a1bSJed Brown       args: -interpolate after_distribute
1828c4762a1bSJed Brown       args: -petscpartitioner_type parmetis
1829c4762a1bSJed Brown 
1830c4762a1bSJed Brown   testset: # 9 HDF5 PARALLEL LOAD
1831c4762a1bSJed Brown     requires: hdf5 !complex datafilespath
1832c4762a1bSJed Brown     nsize: {{2 4 5}}
1833c4762a1bSJed Brown     args: -dm_plex_check_all
1834c4762a1bSJed 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
1835c4762a1bSJed Brown     test: # par load
1836c4762a1bSJed Brown       suffix: 9_par_hdf5
1837c4762a1bSJed Brown       args: -interpolate none
1838c4762a1bSJed Brown     test: # par load, par interpolation
1839c4762a1bSJed Brown       suffix: 9_par_hdf5_int
1840c4762a1bSJed Brown       args: -interpolate after_create
1841c4762a1bSJed Brown     test: # par load, parmetis repartitioner
1842c4762a1bSJed Brown       TODO: Parallel partitioning of uninterpolated meshes not supported
1843c4762a1bSJed Brown       suffix: 9_par_hdf5_parmetis
1844c4762a1bSJed Brown       requires: parmetis
1845c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1846c4762a1bSJed Brown       args: -interpolate none
1847c4762a1bSJed Brown     test: # par load, par interpolation, parmetis repartitioner
1848c4762a1bSJed Brown       suffix: 9_par_hdf5_int_parmetis
1849c4762a1bSJed Brown       requires: parmetis
1850c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1851c4762a1bSJed Brown       args: -interpolate after_create
1852c4762a1bSJed Brown     test: # par load, parmetis partitioner, par interpolation
1853c4762a1bSJed Brown       TODO: Parallel partitioning of uninterpolated meshes not supported
1854c4762a1bSJed Brown       suffix: 9_par_hdf5_parmetis_int
1855c4762a1bSJed Brown       requires: parmetis
1856c4762a1bSJed Brown       args: -distribute -petscpartitioner_type parmetis
1857c4762a1bSJed Brown       args: -interpolate after_distribute
1858c4762a1bSJed Brown 
1859c4762a1bSJed Brown   testset: # 10 HDF5 PARALLEL LOAD
1860c4762a1bSJed Brown     requires: hdf5 !complex datafilespath
1861c4762a1bSJed Brown     nsize: {{2 4 7}}
1862c4762a1bSJed Brown     args: -dm_plex_check_all
1863c4762a1bSJed 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
1864c4762a1bSJed Brown     test: # par load, par interpolation
1865c4762a1bSJed Brown       suffix: 10_par_hdf5_int
1866c4762a1bSJed Brown       args: -interpolate after_create
1867c4762a1bSJed Brown TEST*/
1868