xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I      "petscdmplex.h"   I*/
2e8f14785SLisandro Dalcin #include <petsc/private/hashmapi.h>
3e8f14785SLisandro Dalcin #include <petsc/private/hashmapij.h>
4e8f14785SLisandro Dalcin 
5ea78f98cSLisandro Dalcin const char *const DMPlexInterpolatedFlags[] = {"none", "partial", "mixed", "full", "DMPlexInterpolatedFlag", "DMPLEX_INTERPOLATED_", NULL};
6a7748839SVaclav Hapla 
7e8f14785SLisandro Dalcin /* HashIJKL */
8e8f14785SLisandro Dalcin 
9e8f14785SLisandro Dalcin #include <petsc/private/hashmap.h>
10e8f14785SLisandro Dalcin 
119371c9d4SSatish Balay typedef struct _PetscHashIJKLKey {
129371c9d4SSatish Balay   PetscInt i, j, k, l;
139371c9d4SSatish Balay } PetscHashIJKLKey;
14e8f14785SLisandro Dalcin 
159371c9d4SSatish Balay #define PetscHashIJKLKeyHash(key) PetscHashCombine(PetscHashCombine(PetscHashInt((key).i), PetscHashInt((key).j)), PetscHashCombine(PetscHashInt((key).k), PetscHashInt((key).l)))
16e8f14785SLisandro Dalcin 
179371c9d4SSatish Balay #define PetscHashIJKLKeyEqual(k1, k2) (((k1).i == (k2).i) ? ((k1).j == (k2).j) ? ((k1).k == (k2).k) ? ((k1).l == (k2).l) : 0 : 0 : 0)
18e8f14785SLisandro Dalcin 
19999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKL, PetscHashIJKLKey, PetscInt, PetscHashIJKLKeyHash, PetscHashIJKLKeyEqual, -1))
20e8f14785SLisandro Dalcin 
213be36e83SMatthew G. Knepley   static PetscSFNode _PetscInvalidSFNode = {-1, -1};
223be36e83SMatthew G. Knepley 
239371c9d4SSatish Balay typedef struct _PetscHashIJKLRemoteKey {
249371c9d4SSatish Balay   PetscSFNode i, j, k, l;
259371c9d4SSatish Balay } PetscHashIJKLRemoteKey;
263be36e83SMatthew G. Knepley 
273be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \
289371c9d4SSatish Balay   PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index), PetscHashInt((key).j.rank + (key).j.index)), PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index), PetscHashInt((key).l.rank + (key).l.index)))
293be36e83SMatthew G. Knepley 
303be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyEqual(k1, k2) \
313be36e83SMatthew G. Knepley   (((k1).i.rank == (k2).i.rank) ? ((k1).i.index == (k2).i.index) ? ((k1).j.rank == (k2).j.rank) ? ((k1).j.index == (k2).j.index) ? ((k1).k.rank == (k2).k.rank) ? ((k1).k.index == (k2).k.index) ? ((k1).l.rank == (k2).l.rank) ? ((k1).l.index == (k2).l.index) : 0 : 0 : 0 : 0 : 0 : 0 : 0)
323be36e83SMatthew G. Knepley 
33999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode))
343be36e83SMatthew G. Knepley 
35d71ae5a4SJacob Faibussowitsch   static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[])
36d71ae5a4SJacob Faibussowitsch {
373be36e83SMatthew G. Knepley   PetscInt i;
383be36e83SMatthew G. Knepley 
393be36e83SMatthew G. Knepley   PetscFunctionBegin;
403be36e83SMatthew G. Knepley   for (i = 1; i < n; ++i) {
413be36e83SMatthew G. Knepley     PetscSFNode x = A[i];
423be36e83SMatthew G. Knepley     PetscInt    j;
433be36e83SMatthew G. Knepley 
443be36e83SMatthew G. Knepley     for (j = i - 1; j >= 0; --j) {
453be36e83SMatthew G. Knepley       if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break;
463be36e83SMatthew G. Knepley       A[j + 1] = A[j];
473be36e83SMatthew G. Knepley     }
483be36e83SMatthew G. Knepley     A[j + 1] = x;
493be36e83SMatthew G. Knepley   }
50*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
513be36e83SMatthew G. Knepley }
529f074e33SMatthew G Knepley 
539f074e33SMatthew G Knepley /*
54439ece16SMatthew G. Knepley   DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone
55439ece16SMatthew G. Knepley */
56d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
57d71ae5a4SJacob Faibussowitsch {
58412e9a14SMatthew G. Knepley   DMPolytopeType *typesTmp;
59412e9a14SMatthew G. Knepley   PetscInt       *sizesTmp, *facesTmp;
60439ece16SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize;
61439ece16SMatthew G. Knepley 
62439ece16SMatthew G. Knepley   PetscFunctionBegin;
63439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(cone, 3);
659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
669566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &typesTmp));
679566063dSJacob Faibussowitsch   if (faceSizes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &sizesTmp));
689566063dSJacob Faibussowitsch   if (faces) PetscCall(DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp));
69ba2698f1SMatthew G. Knepley   switch (ct) {
70ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_POINT:
71ba2698f1SMatthew G. Knepley     if (numFaces) *numFaces = 0;
72ba2698f1SMatthew G. Knepley     break;
73ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
74412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 2;
75412e9a14SMatthew G. Knepley     if (faceTypes) {
769371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
779371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
78412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
79412e9a14SMatthew G. Knepley     }
80412e9a14SMatthew G. Knepley     if (faceSizes) {
819371c9d4SSatish Balay       sizesTmp[0] = 1;
829371c9d4SSatish Balay       sizesTmp[1] = 1;
83412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
84412e9a14SMatthew G. Knepley     }
85c49d9212SMatthew G. Knepley     if (faces) {
869371c9d4SSatish Balay       facesTmp[0] = cone[0];
879371c9d4SSatish Balay       facesTmp[1] = cone[1];
88c49d9212SMatthew G. Knepley       *faces      = facesTmp;
89c49d9212SMatthew G. Knepley     }
90412e9a14SMatthew G. Knepley     break;
91412e9a14SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
92c49d9212SMatthew G. Knepley     if (numFaces) *numFaces = 2;
93412e9a14SMatthew G. Knepley     if (faceTypes) {
949371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
959371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
96412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
97412e9a14SMatthew G. Knepley     }
98412e9a14SMatthew G. Knepley     if (faceSizes) {
999371c9d4SSatish Balay       sizesTmp[0] = 1;
1009371c9d4SSatish Balay       sizesTmp[1] = 1;
101412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
102412e9a14SMatthew G. Knepley     }
103412e9a14SMatthew G. Knepley     if (faces) {
1049371c9d4SSatish Balay       facesTmp[0] = cone[0];
1059371c9d4SSatish Balay       facesTmp[1] = cone[1];
106412e9a14SMatthew G. Knepley       *faces      = facesTmp;
107412e9a14SMatthew G. Knepley     }
108c49d9212SMatthew G. Knepley     break;
109ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
110412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 3;
111412e9a14SMatthew G. Knepley     if (faceTypes) {
1129371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1139371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1149371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
115412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
116412e9a14SMatthew G. Knepley     }
117412e9a14SMatthew G. Knepley     if (faceSizes) {
1189371c9d4SSatish Balay       sizesTmp[0] = 2;
1199371c9d4SSatish Balay       sizesTmp[1] = 2;
1209371c9d4SSatish Balay       sizesTmp[2] = 2;
121412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
122412e9a14SMatthew G. Knepley     }
1239a5b13a2SMatthew G Knepley     if (faces) {
1249371c9d4SSatish Balay       facesTmp[0] = cone[0];
1259371c9d4SSatish Balay       facesTmp[1] = cone[1];
1269371c9d4SSatish Balay       facesTmp[2] = cone[1];
1279371c9d4SSatish Balay       facesTmp[3] = cone[2];
1289371c9d4SSatish Balay       facesTmp[4] = cone[2];
1299371c9d4SSatish Balay       facesTmp[5] = cone[0];
1309a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1319a5b13a2SMatthew G Knepley     }
1329f074e33SMatthew G Knepley     break;
133ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
1349a5b13a2SMatthew G Knepley     /* Vertices follow right hand rule */
135412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
136412e9a14SMatthew G. Knepley     if (faceTypes) {
1379371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1389371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1399371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
1409371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEGMENT;
141412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
142412e9a14SMatthew G. Knepley     }
143412e9a14SMatthew G. Knepley     if (faceSizes) {
1449371c9d4SSatish Balay       sizesTmp[0] = 2;
1459371c9d4SSatish Balay       sizesTmp[1] = 2;
1469371c9d4SSatish Balay       sizesTmp[2] = 2;
1479371c9d4SSatish Balay       sizesTmp[3] = 2;
148412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
149412e9a14SMatthew G. Knepley     }
1509a5b13a2SMatthew G Knepley     if (faces) {
1519371c9d4SSatish Balay       facesTmp[0] = cone[0];
1529371c9d4SSatish Balay       facesTmp[1] = cone[1];
1539371c9d4SSatish Balay       facesTmp[2] = cone[1];
1549371c9d4SSatish Balay       facesTmp[3] = cone[2];
1559371c9d4SSatish Balay       facesTmp[4] = cone[2];
1569371c9d4SSatish Balay       facesTmp[5] = cone[3];
1579371c9d4SSatish Balay       facesTmp[6] = cone[3];
1589371c9d4SSatish Balay       facesTmp[7] = cone[0];
1599a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1609a5b13a2SMatthew G Knepley     }
161412e9a14SMatthew G. Knepley     break;
162412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
1639a5b13a2SMatthew G Knepley     if (numFaces) *numFaces = 4;
164412e9a14SMatthew G. Knepley     if (faceTypes) {
1659371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1669371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1679371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1689371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
169412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
170412e9a14SMatthew G. Knepley     }
171412e9a14SMatthew G. Knepley     if (faceSizes) {
1729371c9d4SSatish Balay       sizesTmp[0] = 2;
1739371c9d4SSatish Balay       sizesTmp[1] = 2;
1749371c9d4SSatish Balay       sizesTmp[2] = 2;
1759371c9d4SSatish Balay       sizesTmp[3] = 2;
176412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
177412e9a14SMatthew G. Knepley     }
178412e9a14SMatthew G. Knepley     if (faces) {
1799371c9d4SSatish Balay       facesTmp[0] = cone[0];
1809371c9d4SSatish Balay       facesTmp[1] = cone[1];
1819371c9d4SSatish Balay       facesTmp[2] = cone[2];
1829371c9d4SSatish Balay       facesTmp[3] = cone[3];
1839371c9d4SSatish Balay       facesTmp[4] = cone[0];
1849371c9d4SSatish Balay       facesTmp[5] = cone[2];
1859371c9d4SSatish Balay       facesTmp[6] = cone[1];
1869371c9d4SSatish Balay       facesTmp[7] = cone[3];
187412e9a14SMatthew G. Knepley       *faces      = facesTmp;
188412e9a14SMatthew G. Knepley     }
1899f074e33SMatthew G Knepley     break;
190ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
1912e1b13c2SMatthew G. Knepley     /* Vertices of first face follow right hand rule and normal points away from last vertex */
192412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
193412e9a14SMatthew G. Knepley     if (faceTypes) {
1949371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
1959371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
1969371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
1979371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
198412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
199412e9a14SMatthew G. Knepley     }
200412e9a14SMatthew G. Knepley     if (faceSizes) {
2019371c9d4SSatish Balay       sizesTmp[0] = 3;
2029371c9d4SSatish Balay       sizesTmp[1] = 3;
2039371c9d4SSatish Balay       sizesTmp[2] = 3;
2049371c9d4SSatish Balay       sizesTmp[3] = 3;
205412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
206412e9a14SMatthew G. Knepley     }
2079a5b13a2SMatthew G Knepley     if (faces) {
2089371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2099371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2109371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2119371c9d4SSatish Balay       facesTmp[3]  = cone[0];
2129371c9d4SSatish Balay       facesTmp[4]  = cone[3];
2139371c9d4SSatish Balay       facesTmp[5]  = cone[1];
2149371c9d4SSatish Balay       facesTmp[6]  = cone[0];
2159371c9d4SSatish Balay       facesTmp[7]  = cone[2];
2169371c9d4SSatish Balay       facesTmp[8]  = cone[3];
2179371c9d4SSatish Balay       facesTmp[9]  = cone[2];
2189371c9d4SSatish Balay       facesTmp[10] = cone[1];
2199371c9d4SSatish Balay       facesTmp[11] = cone[3];
2209a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2219a5b13a2SMatthew G Knepley     }
2229a5b13a2SMatthew G Knepley     break;
223ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
224e368ef20SMatthew G. Knepley     /*  7--------6
225e368ef20SMatthew G. Knepley          /|       /|
226e368ef20SMatthew G. Knepley         / |      / |
227e368ef20SMatthew G. Knepley        4--------5  |
228e368ef20SMatthew G. Knepley        |  |     |  |
229e368ef20SMatthew G. Knepley        |  |     |  |
230e368ef20SMatthew G. Knepley        |  1--------2
231e368ef20SMatthew G. Knepley        | /      | /
232e368ef20SMatthew G. Knepley        |/       |/
233e368ef20SMatthew G. Knepley        0--------3
234e368ef20SMatthew G. Knepley        */
235412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
236412e9a14SMatthew G. Knepley     if (faceTypes) {
2379371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
2389371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
2399371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2409371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2419371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
2429371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
243412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
244412e9a14SMatthew G. Knepley     }
245412e9a14SMatthew G. Knepley     if (faceSizes) {
2469371c9d4SSatish Balay       sizesTmp[0] = 4;
2479371c9d4SSatish Balay       sizesTmp[1] = 4;
2489371c9d4SSatish Balay       sizesTmp[2] = 4;
2499371c9d4SSatish Balay       sizesTmp[3] = 4;
2509371c9d4SSatish Balay       sizesTmp[4] = 4;
2519371c9d4SSatish Balay       sizesTmp[5] = 4;
252412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
253412e9a14SMatthew G. Knepley     }
2549a5b13a2SMatthew G Knepley     if (faces) {
2559371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2569371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2579371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2589371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
2599371c9d4SSatish Balay       facesTmp[4]  = cone[4];
2609371c9d4SSatish Balay       facesTmp[5]  = cone[5];
2619371c9d4SSatish Balay       facesTmp[6]  = cone[6];
2629371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
2639371c9d4SSatish Balay       facesTmp[8]  = cone[0];
2649371c9d4SSatish Balay       facesTmp[9]  = cone[3];
2659371c9d4SSatish Balay       facesTmp[10] = cone[5];
2669371c9d4SSatish Balay       facesTmp[11] = cone[4]; /* Front */
2679371c9d4SSatish Balay       facesTmp[12] = cone[2];
2689371c9d4SSatish Balay       facesTmp[13] = cone[1];
2699371c9d4SSatish Balay       facesTmp[14] = cone[7];
2709371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Back */
2719371c9d4SSatish Balay       facesTmp[16] = cone[3];
2729371c9d4SSatish Balay       facesTmp[17] = cone[2];
2739371c9d4SSatish Balay       facesTmp[18] = cone[6];
2749371c9d4SSatish Balay       facesTmp[19] = cone[5]; /* Right */
2759371c9d4SSatish Balay       facesTmp[20] = cone[0];
2769371c9d4SSatish Balay       facesTmp[21] = cone[4];
2779371c9d4SSatish Balay       facesTmp[22] = cone[7];
2789371c9d4SSatish Balay       facesTmp[23] = cone[1]; /* Left */
2799a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2809a5b13a2SMatthew G Knepley     }
28199836e0eSStefano Zampini     break;
282ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM:
283412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
284412e9a14SMatthew G. Knepley     if (faceTypes) {
2859371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2869371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2879371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2889371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2899371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
290412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
291412e9a14SMatthew G. Knepley     }
292412e9a14SMatthew G. Knepley     if (faceSizes) {
2939371c9d4SSatish Balay       sizesTmp[0] = 3;
2949371c9d4SSatish Balay       sizesTmp[1] = 3;
2959371c9d4SSatish Balay       sizesTmp[2] = 4;
2969371c9d4SSatish Balay       sizesTmp[3] = 4;
2979371c9d4SSatish Balay       sizesTmp[4] = 4;
298412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
299412e9a14SMatthew G. Knepley     }
300ba2698f1SMatthew G. Knepley     if (faces) {
3019371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3029371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3039371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3049371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3059371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3069371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3079371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3089371c9d4SSatish Balay       facesTmp[7]  = cone[2];
3099371c9d4SSatish Balay       facesTmp[8]  = cone[4];
3109371c9d4SSatish Balay       facesTmp[9]  = cone[3]; /* Back left */
3119371c9d4SSatish Balay       facesTmp[10] = cone[2];
3129371c9d4SSatish Balay       facesTmp[11] = cone[1];
3139371c9d4SSatish Balay       facesTmp[12] = cone[5];
3149371c9d4SSatish Balay       facesTmp[13] = cone[4]; /* Front */
3159371c9d4SSatish Balay       facesTmp[14] = cone[1];
3169371c9d4SSatish Balay       facesTmp[15] = cone[0];
3179371c9d4SSatish Balay       facesTmp[16] = cone[3];
3189371c9d4SSatish Balay       facesTmp[17] = cone[5]; /* Back right */
319ba2698f1SMatthew G. Knepley       *faces       = facesTmp;
32099836e0eSStefano Zampini     }
32199836e0eSStefano Zampini     break;
322ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
323412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
324412e9a14SMatthew G. Knepley     if (faceTypes) {
3259371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
3269371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
3279371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3289371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3299371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
330412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
331412e9a14SMatthew G. Knepley     }
332412e9a14SMatthew G. Knepley     if (faceSizes) {
3339371c9d4SSatish Balay       sizesTmp[0] = 3;
3349371c9d4SSatish Balay       sizesTmp[1] = 3;
3359371c9d4SSatish Balay       sizesTmp[2] = 4;
3369371c9d4SSatish Balay       sizesTmp[3] = 4;
3379371c9d4SSatish Balay       sizesTmp[4] = 4;
338412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
339412e9a14SMatthew G. Knepley     }
34099836e0eSStefano Zampini     if (faces) {
3419371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3429371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3439371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3449371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3459371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3469371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3479371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3489371c9d4SSatish Balay       facesTmp[7]  = cone[1];
3499371c9d4SSatish Balay       facesTmp[8]  = cone[3];
3509371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Back left */
3519371c9d4SSatish Balay       facesTmp[10] = cone[1];
3529371c9d4SSatish Balay       facesTmp[11] = cone[2];
3539371c9d4SSatish Balay       facesTmp[12] = cone[4];
3549371c9d4SSatish Balay       facesTmp[13] = cone[5]; /* Back right */
3559371c9d4SSatish Balay       facesTmp[14] = cone[2];
3569371c9d4SSatish Balay       facesTmp[15] = cone[0];
3579371c9d4SSatish Balay       facesTmp[16] = cone[5];
3589371c9d4SSatish Balay       facesTmp[17] = cone[3]; /* Front */
35999836e0eSStefano Zampini       *faces       = facesTmp;
36099836e0eSStefano Zampini     }
361412e9a14SMatthew G. Knepley     break;
362412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
363412e9a14SMatthew G. Knepley     /*  7--------6
364412e9a14SMatthew G. Knepley          /|       /|
365412e9a14SMatthew G. Knepley         / |      / |
366412e9a14SMatthew G. Knepley        4--------5  |
367412e9a14SMatthew G. Knepley        |  |     |  |
368412e9a14SMatthew G. Knepley        |  |     |  |
369412e9a14SMatthew G. Knepley        |  3--------2
370412e9a14SMatthew G. Knepley        | /      | /
371412e9a14SMatthew G. Knepley        |/       |/
372412e9a14SMatthew G. Knepley        0--------1
373412e9a14SMatthew G. Knepley        */
374412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
375412e9a14SMatthew G. Knepley     if (faceTypes) {
3769371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
3779371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
3789371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3799371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3809371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3819371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
382412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
383412e9a14SMatthew G. Knepley     }
384412e9a14SMatthew G. Knepley     if (faceSizes) {
3859371c9d4SSatish Balay       sizesTmp[0] = 4;
3869371c9d4SSatish Balay       sizesTmp[1] = 4;
3879371c9d4SSatish Balay       sizesTmp[2] = 4;
3889371c9d4SSatish Balay       sizesTmp[3] = 4;
3899371c9d4SSatish Balay       sizesTmp[4] = 4;
3909371c9d4SSatish Balay       sizesTmp[5] = 4;
391412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
392412e9a14SMatthew G. Knepley     }
393412e9a14SMatthew G. Knepley     if (faces) {
3949371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3959371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3969371c9d4SSatish Balay       facesTmp[2]  = cone[2];
3979371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
3989371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3999371c9d4SSatish Balay       facesTmp[5]  = cone[5];
4009371c9d4SSatish Balay       facesTmp[6]  = cone[6];
4019371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
4029371c9d4SSatish Balay       facesTmp[8]  = cone[0];
4039371c9d4SSatish Balay       facesTmp[9]  = cone[1];
4049371c9d4SSatish Balay       facesTmp[10] = cone[4];
4059371c9d4SSatish Balay       facesTmp[11] = cone[5]; /* Front */
4069371c9d4SSatish Balay       facesTmp[12] = cone[1];
4079371c9d4SSatish Balay       facesTmp[13] = cone[2];
4089371c9d4SSatish Balay       facesTmp[14] = cone[5];
4099371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Right */
4109371c9d4SSatish Balay       facesTmp[16] = cone[2];
4119371c9d4SSatish Balay       facesTmp[17] = cone[3];
4129371c9d4SSatish Balay       facesTmp[18] = cone[6];
4139371c9d4SSatish Balay       facesTmp[19] = cone[7]; /* Back */
4149371c9d4SSatish Balay       facesTmp[20] = cone[3];
4159371c9d4SSatish Balay       facesTmp[21] = cone[0];
4169371c9d4SSatish Balay       facesTmp[22] = cone[7];
4179371c9d4SSatish Balay       facesTmp[23] = cone[4]; /* Left */
418412e9a14SMatthew G. Knepley       *faces       = facesTmp;
419412e9a14SMatthew G. Knepley     }
42099836e0eSStefano Zampini     break;
421da9060c4SMatthew G. Knepley   case DM_POLYTOPE_PYRAMID:
422da9060c4SMatthew G. Knepley     /*
423da9060c4SMatthew G. Knepley        4----
424da9060c4SMatthew G. Knepley        |\-\ \-----
425da9060c4SMatthew G. Knepley        | \ -\     \
426da9060c4SMatthew G. Knepley        |  1--\-----2
427da9060c4SMatthew G. Knepley        | /    \   /
428da9060c4SMatthew G. Knepley        |/      \ /
429da9060c4SMatthew G. Knepley        0--------3
430da9060c4SMatthew G. Knepley        */
431da9060c4SMatthew G. Knepley     if (numFaces) *numFaces = 5;
432da9060c4SMatthew G. Knepley     if (faceTypes) {
433da9060c4SMatthew G. Knepley       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
4349371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
4359371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
4369371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
4379371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_TRIANGLE;
438da9060c4SMatthew G. Knepley       *faceTypes  = typesTmp;
439da9060c4SMatthew G. Knepley     }
440da9060c4SMatthew G. Knepley     if (faceSizes) {
441da9060c4SMatthew G. Knepley       sizesTmp[0] = 4;
4429371c9d4SSatish Balay       sizesTmp[1] = 3;
4439371c9d4SSatish Balay       sizesTmp[2] = 3;
4449371c9d4SSatish Balay       sizesTmp[3] = 3;
4459371c9d4SSatish Balay       sizesTmp[4] = 3;
446da9060c4SMatthew G. Knepley       *faceSizes  = sizesTmp;
447da9060c4SMatthew G. Knepley     }
448da9060c4SMatthew G. Knepley     if (faces) {
4499371c9d4SSatish Balay       facesTmp[0]  = cone[0];
4509371c9d4SSatish Balay       facesTmp[1]  = cone[1];
4519371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4529371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4539371c9d4SSatish Balay       facesTmp[4]  = cone[0];
4549371c9d4SSatish Balay       facesTmp[5]  = cone[3];
4559371c9d4SSatish Balay       facesTmp[6]  = cone[4]; /* Front */
4569371c9d4SSatish Balay       facesTmp[7]  = cone[3];
4579371c9d4SSatish Balay       facesTmp[8]  = cone[2];
4589371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Right */
4599371c9d4SSatish Balay       facesTmp[10] = cone[2];
4609371c9d4SSatish Balay       facesTmp[11] = cone[1];
4619371c9d4SSatish Balay       facesTmp[12] = cone[4]; /* Back */
4629371c9d4SSatish Balay       facesTmp[13] = cone[1];
4639371c9d4SSatish Balay       facesTmp[14] = cone[0];
4649371c9d4SSatish Balay       facesTmp[15] = cone[4]; /* Left */
465da9060c4SMatthew G. Knepley       *faces       = facesTmp;
466da9060c4SMatthew G. Knepley     }
467da9060c4SMatthew G. Knepley     break;
468d71ae5a4SJacob Faibussowitsch   default:
469d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
47099836e0eSStefano Zampini   }
471*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47299836e0eSStefano Zampini }
47399836e0eSStefano Zampini 
474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
475d71ae5a4SJacob Faibussowitsch {
47699836e0eSStefano Zampini   PetscFunctionBegin;
4779566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes));
4789566063dSJacob Faibussowitsch   if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes));
4799566063dSJacob Faibussowitsch   if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces));
480*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48199836e0eSStefano Zampini }
48299836e0eSStefano Zampini 
4839a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
484d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
485d71ae5a4SJacob Faibussowitsch {
486412e9a14SMatthew G. Knepley   DMLabel       ctLabel;
4879a5b13a2SMatthew G Knepley   PetscHashIJKL faceTable;
488412e9a14SMatthew G. Knepley   PetscInt      faceTypeNum[DM_NUM_POLYTOPES];
4899318fe57SMatthew G. Knepley   PetscInt      depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd;
4909f074e33SMatthew G Knepley 
4919f074e33SMatthew G Knepley   PetscFunctionBegin;
4929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4939566063dSJacob Faibussowitsch   PetscCall(PetscHashIJKLCreate(&faceTable));
4949566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
4959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
496412e9a14SMatthew G. Knepley   /* Number new faces and save face vertices in hash table */
4979566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
498412e9a14SMatthew G. Knepley   fEnd = fStart;
499412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
500412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
501412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
502ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
503412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
50499836e0eSStefano Zampini 
5059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5079566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
508412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
509412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
510412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
511412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
5129a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
513e8f14785SLisandro Dalcin       PetscHashIter        iter;
514e8f14785SLisandro Dalcin       PetscBool            missing;
5159f074e33SMatthew G Knepley 
5165f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
517412e9a14SMatthew G. Knepley       key.i = face[0];
518412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
519412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
520412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
5219566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
5229566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
523e9fa77a1SMatthew G. Knepley       if (missing) {
5249566063dSJacob Faibussowitsch         PetscCall(PetscHashIJKLIterSet(faceTable, iter, fEnd++));
525412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
526e9fa77a1SMatthew G. Knepley       }
5279a5b13a2SMatthew G Knepley     }
5289566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
52999836e0eSStefano Zampini   }
530412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
531412e9a14SMatthew G. Knepley   {
532412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
53399836e0eSStefano Zampini 
5349371c9d4SSatish Balay     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5359371c9d4SSatish Balay       if (faceTypeNum[ct]) ++numFT;
5369371c9d4SSatish Balay       faceTypeStart[ct] = 0;
5379371c9d4SSatish Balay     }
538412e9a14SMatthew G. Knepley     if (numFT > 1) {
5399566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLClear(faceTable));
540412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
541412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
542412e9a14SMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
543412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
544412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
545ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
546412e9a14SMatthew G. Knepley         PetscInt              numFaces, cf, foff = 0;
54799836e0eSStefano Zampini 
5489566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
5499566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
5509566063dSJacob Faibussowitsch         PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
551412e9a14SMatthew G. Knepley         for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
552412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
553412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
554412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
55599836e0eSStefano Zampini           PetscHashIJKLKey     key;
55699836e0eSStefano Zampini           PetscHashIter        iter;
55799836e0eSStefano Zampini           PetscBool            missing;
55899836e0eSStefano Zampini 
5595f80ce2aSJacob Faibussowitsch           PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
560412e9a14SMatthew G. Knepley           key.i = face[0];
561412e9a14SMatthew G. Knepley           key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
562412e9a14SMatthew G. Knepley           key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
563412e9a14SMatthew G. Knepley           key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
5649566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
5659566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
5669566063dSJacob Faibussowitsch           if (missing) PetscCall(PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
56799836e0eSStefano Zampini         }
5689566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
56999836e0eSStefano Zampini       }
570412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
5711dca8a05SBarry Smith         PetscCheck(faceTypeStart[ct] == faceTypeStart[ct - 1] + faceTypeNum[ct], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent numbering for cell type %s, %" PetscInt_FMT " != %" PetscInt_FMT " + %" PetscInt_FMT, DMPolytopeTypes[ct], faceTypeStart[ct], faceTypeStart[ct - 1], faceTypeNum[ct]);
5729a5b13a2SMatthew G Knepley       }
5739a5b13a2SMatthew G Knepley     }
574412e9a14SMatthew G. Knepley   }
575412e9a14SMatthew G. Knepley   /* Add new points, always at the end of the numbering */
5769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
5779566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
5789a5b13a2SMatthew G Knepley   /* Set cone sizes */
579412e9a14SMatthew G. Knepley   /*   Must create the celltype label here so that we do not automatically try to compute the types */
5809566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
5819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
5829a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
583412e9a14SMatthew G. Knepley     DMPolytopeType ct;
584412e9a14SMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, p;
5859f074e33SMatthew G Knepley 
586412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
5879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
588412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
5899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
5909566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, p, coneSize));
5919566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
5929566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, p, ct));
5939f074e33SMatthew G Knepley     }
5949f074e33SMatthew G Knepley   }
595412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
596412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
597412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
598412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
599412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
600412e9a14SMatthew G. Knepley 
6019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
6039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
6049566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(idm, c, ct));
6059566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(idm, c, numFaces));
606412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
607412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
608412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
609412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
610412e9a14SMatthew G. Knepley       PetscHashIJKLKey     key;
611412e9a14SMatthew G. Knepley       PetscHashIter        iter;
612412e9a14SMatthew G. Knepley       PetscBool            missing;
613412e9a14SMatthew G. Knepley       PetscInt             f;
614412e9a14SMatthew G. Knepley 
61563a3b9bcSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
616412e9a14SMatthew G. Knepley       key.i = face[0];
617412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
618412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
619412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
6209566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
6219566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
62263a3b9bcSJacob Faibussowitsch       PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %" PetscInt_FMT ", lf %" PetscInt_FMT ")", c, cf);
6239566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f));
6249566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, f, faceSize));
6259566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, f, faceType));
626412e9a14SMatthew G. Knepley     }
6279566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
6289f074e33SMatthew G Knepley   }
6299566063dSJacob Faibussowitsch   PetscCall(DMSetUp(idm));
630412e9a14SMatthew G. Knepley   /* Initialize cones so we do not need the bash table to tell us that a cone has been set */
631412e9a14SMatthew G. Knepley   {
632412e9a14SMatthew G. Knepley     PetscSection cs;
633412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
6349a5b13a2SMatthew G Knepley 
6359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSection(idm, &cs));
6369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCones(idm, &cones));
6379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(cs, &csize));
638412e9a14SMatthew G. Knepley     for (c = 0; c < csize; ++c) cones[c] = -1;
639412e9a14SMatthew G. Knepley   }
640412e9a14SMatthew G. Knepley   /* Set cones */
641412e9a14SMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
642412e9a14SMatthew G. Knepley     const PetscInt *cone;
643412e9a14SMatthew G. Knepley     PetscInt        pStart, pEnd, p;
644412e9a14SMatthew G. Knepley 
645412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
647412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
6489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, p, &cone));
6499566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(idm, p, cone));
6509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
6519566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeOrientation(idm, p, cone));
6529f074e33SMatthew G Knepley     }
6539a5b13a2SMatthew G Knepley   }
654412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
655412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
656412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
657ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
658412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
65999836e0eSStefano Zampini 
6609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
6629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
663412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
664412e9a14SMatthew G. Knepley       DMPolytopeType   faceType = faceTypes[cf];
665412e9a14SMatthew G. Knepley       const PetscInt   faceSize = faceSizes[cf];
666412e9a14SMatthew G. Knepley       const PetscInt  *face     = &faces[foff];
667412e9a14SMatthew G. Knepley       const PetscInt  *fcone;
6689a5b13a2SMatthew G Knepley       PetscHashIJKLKey key;
669e8f14785SLisandro Dalcin       PetscHashIter    iter;
670e8f14785SLisandro Dalcin       PetscBool        missing;
671412e9a14SMatthew G. Knepley       PetscInt         f;
6729f074e33SMatthew G Knepley 
67363a3b9bcSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
674412e9a14SMatthew G. Knepley       key.i = face[0];
675412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
676412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
677412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
6789566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
6799566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
6809566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f));
6819566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertCone(idm, c, cf, f));
6829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(idm, f, &fcone));
6839566063dSJacob Faibussowitsch       if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
684412e9a14SMatthew G. Knepley       {
685412e9a14SMatthew G. Knepley         const PetscInt *cone;
686412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
687a74221b0SStefano Zampini 
6889566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
6899566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &cone));
69063a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == faceSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %" PetscInt_FMT " for face %" PetscInt_FMT " should be %" PetscInt_FMT, coneSize, f, faceSize);
691d89e6e46SMatthew G. Knepley         /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
6929566063dSJacob Faibussowitsch         PetscCall(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt));
6939566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertConeOrientation(idm, c, cf, ornt));
69499836e0eSStefano Zampini       }
69599836e0eSStefano Zampini     }
6969566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
69799836e0eSStefano Zampini   }
6989566063dSJacob Faibussowitsch   PetscCall(PetscHashIJKLDestroy(&faceTable));
6999566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
7009566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
701*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7029f074e33SMatthew G Knepley }
7039f074e33SMatthew G Knepley 
704d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
705d71ae5a4SJacob Faibussowitsch {
706f80536cbSVaclav Hapla   PetscInt           nleaves;
707f80536cbSVaclav Hapla   PetscInt           nranks;
708a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks   = NULL;
709a0d42dbcSVaclav Hapla   const PetscInt    *roffset = NULL, *rmine = NULL, *rremote = NULL;
710f80536cbSVaclav Hapla   PetscInt           n, o, r;
711f80536cbSVaclav Hapla 
712f80536cbSVaclav Hapla   PetscFunctionBegin;
7139566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
714f80536cbSVaclav Hapla   nleaves = roffset[nranks];
7159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
716f80536cbSVaclav Hapla   for (r = 0; r < nranks; r++) {
717f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
718f80536cbSVaclav Hapla        - to unify order with the other side */
719f80536cbSVaclav Hapla     o = roffset[r];
720f80536cbSVaclav Hapla     n = roffset[r + 1] - o;
7219566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7229566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7239566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
724f80536cbSVaclav Hapla   }
725*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
726f80536cbSVaclav Hapla }
727f80536cbSVaclav Hapla 
728d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
729d71ae5a4SJacob Faibussowitsch {
730d89e6e46SMatthew G. Knepley   PetscSF            sf;
731d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
732d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
733d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
734d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
735d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
736d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
737d89e6e46SMatthew G. Knepley   PetscInt(*roots)[4], (*leaves)[4], mainCone[4];
738d89e6e46SMatthew G. Knepley   PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4];
7392e745bdaSMatthew G. Knepley   MPI_Comm    comm;
74027d0e99aSVaclav Hapla   PetscMPIInt rank, size;
7412e745bdaSMatthew G. Knepley   PetscInt    debug = 0;
7422e745bdaSMatthew G. Knepley 
7432e745bdaSMatthew G. Knepley   PetscFunctionBegin;
7449566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
7459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7469566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
7479566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
7489566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
749d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
7509566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
751*3ba16761SJacob Faibussowitsch   if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS);
7529566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
7539566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
754d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
755d89e6e46SMatthew G. Knepley     PetscInt coneSize;
7569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
757d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
758d89e6e46SMatthew G. Knepley   }
75963a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
7609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
7619e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
762d89e6e46SMatthew G. Knepley     const PetscInt *cone;
763d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
764d89e6e46SMatthew G. Knepley 
7659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
7669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
767d89e6e46SMatthew G. Knepley     /* Ignore vertices */
76827d0e99aSVaclav Hapla     if (coneSize < 2) {
769d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
77027d0e99aSVaclav Hapla         roots[p][c]      = -1;
77127d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
77227d0e99aSVaclav Hapla       }
77327d0e99aSVaclav Hapla       continue;
77427d0e99aSVaclav Hapla     }
7752e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
776d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
7779566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
7788a650c75SVaclav Hapla       if (ind0 < 0) {
7798a650c75SVaclav Hapla         roots[p][c]      = cone[c];
7808a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
781c8148b97SVaclav Hapla       } else {
7828a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
7838a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
7848a650c75SVaclav Hapla       }
7852e745bdaSMatthew G. Knepley     }
786d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
787d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
788d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
789d89e6e46SMatthew G. Knepley     }
7902e745bdaSMatthew G. Knepley   }
7919e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
792d89e6e46SMatthew G. Knepley     PetscInt c;
793d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
7948ccb905dSVaclav Hapla       leaves[p][c]      = -2;
7958ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
7968ccb905dSVaclav Hapla     }
797c8148b97SVaclav Hapla   }
7989566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
7999566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
8009566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8019566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
802d89e6e46SMatthew G. Knepley   if (debug) {
8039566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
804c5853193SPierre Jolivet     if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
805d89e6e46SMatthew G. Knepley   }
8069566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8079e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
808d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
809d89e6e46SMatthew G. Knepley     const PetscInt *cone;
810d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
811d89e6e46SMatthew G. Knepley 
812d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
8139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
8149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
816d89e6e46SMatthew G. Knepley     if (debug) {
8179371c9d4SSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "[%d]  %4" PetscInt_FMT ": cone=[%4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT "] roots=[(%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ")] leaves=[(%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ")]", rank, p, cone[0], cone[1], cone[2], cone[3], rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], rootsRanks[p][2], roots[p][2], rootsRanks[p][3], roots[p][3], leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1], leavesRanks[p][2], leaves[p][2], leavesRanks[p][3], leaves[p][3]));
818d89e6e46SMatthew G. Knepley     }
8199371c9d4SSatish Balay     if (leavesRanks[p][0] != rootsRanks[p][0] || leaves[p][0] != roots[p][0] || leavesRanks[p][1] != rootsRanks[p][1] || leaves[p][1] != roots[p][1] || leavesRanks[p][2] != rootsRanks[p][2] || leaves[p][2] != roots[p][2] || leavesRanks[p][3] != rootsRanks[p][3] || leaves[p][3] != roots[p][3]) {
820d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
821d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
822d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
823d89e6e46SMatthew G. Knepley 
82427d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
825d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
8269dddd249SSatish Balay           mainCone[c] = leaves[p][c];
82727d0e99aSVaclav Hapla           continue;
82827d0e99aSVaclav Hapla         }
829f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
830f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
8319566063dSJacob Faibussowitsch         PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r));
83263a3b9bcSJacob Faibussowitsch         PetscCheck(r >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " cone[%" PetscInt_FMT "]=%" PetscInt_FMT " root (%d,%" PetscInt_FMT ") leaf (%d,%" PetscInt_FMT "): leaf rank not found among remote ranks", p, c, cone[c], rootsRanks[p][c], roots[p][c], leavesRanks[p][c], leaves[p][c]);
8331dca8a05SBarry Smith         PetscCheck(ranks[r] >= 0 && ranks[r] < size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%" PetscInt_FMT " c=%" PetscInt_FMT " commsize=%d: ranks[%" PetscInt_FMT "] = %d makes no sense", p, c, size, r, ranks[r]);
834f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
835d89e6e46SMatthew G. Knepley         rS = roffset[r];
836d89e6e46SMatthew G. Knepley         rN = roffset[r + 1] - rS;
8379566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
83863a3b9bcSJacob Faibussowitsch         PetscCheck(ind0 >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " cone[%" PetscInt_FMT "]=%" PetscInt_FMT " root (%d,%" PetscInt_FMT ") leave (%d,%" PetscInt_FMT "): corresponding remote point not found - it seems there is missing connection in point SF!", p, c, cone[c], rootsRanks[p][c], roots[p][c], leavesRanks[p][c], leaves[p][c]);
839f80536cbSVaclav Hapla         /* Get the corresponding local point */
8405f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
841f80536cbSVaclav Hapla       }
84263a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, " mainCone=[%4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT "]\n", mainCone[0], mainCone[1], mainCone[2], mainCone[3]));
84327d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
8449566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
8459566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
8469566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
84723aaf07bSVaclav Hapla   }
84827d0e99aSVaclav Hapla   if (debug) {
8499566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
8509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
8512e745bdaSMatthew G. Knepley   }
8529566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
8539566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
8549566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
855*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8562e745bdaSMatthew G. Knepley }
8572e745bdaSMatthew G. Knepley 
858d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
859d71ae5a4SJacob Faibussowitsch {
8602e72742cSMatthew G. Knepley   PetscInt    idx;
8612e72742cSMatthew G. Knepley   PetscMPIInt rank;
8622e72742cSMatthew G. Knepley   PetscBool   flg;
8637bffde78SMichael Lange 
8647bffde78SMichael Lange   PetscFunctionBegin;
8659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
866*3ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
8679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8689566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
86963a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
8709566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
871*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8722e72742cSMatthew G. Knepley }
8732e72742cSMatthew G. Knepley 
874d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
875d71ae5a4SJacob Faibussowitsch {
8762e72742cSMatthew G. Knepley   PetscInt    idx;
8772e72742cSMatthew G. Knepley   PetscMPIInt rank;
8782e72742cSMatthew G. Knepley   PetscBool   flg;
8792e72742cSMatthew G. Knepley 
8802e72742cSMatthew G. Knepley   PetscFunctionBegin;
8819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
882*3ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
8839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8849566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
8852e72742cSMatthew G. Knepley   if (idxname) {
88663a3b9bcSJacob Faibussowitsch     for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " rank %" PetscInt_FMT " index %" PetscInt_FMT "\n", rank, idxname, idx, a[idx].rank, a[idx].index));
8872e72742cSMatthew G. Knepley   } else {
88863a3b9bcSJacob Faibussowitsch     for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]rank %" PetscInt_FMT " index %" PetscInt_FMT "\n", rank, a[idx].rank, a[idx].index));
8892e72742cSMatthew G. Knepley   }
8909566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
891*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8922e72742cSMatthew G. Knepley }
8932e72742cSMatthew G. Knepley 
894d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
895d71ae5a4SJacob Faibussowitsch {
8963be36e83SMatthew G. Knepley   PetscSF         sf;
8973be36e83SMatthew G. Knepley   const PetscInt *locals;
8983be36e83SMatthew G. Knepley   PetscMPIInt     rank;
8992e72742cSMatthew G. Knepley 
9002e72742cSMatthew G. Knepley   PetscFunctionBegin;
9019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9029566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9039566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
9045f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9052e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
9062e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
9072e72742cSMatthew G. Knepley   } else {
9082e72742cSMatthew G. Knepley     PetscHashIJKey key;
9093be36e83SMatthew G. Knepley     PetscInt       l;
9102e72742cSMatthew G. Knepley 
9112e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9122e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9139566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
9143be36e83SMatthew G. Knepley     if (l >= 0) {
9153be36e83SMatthew G. Knepley       *localPoint = locals[l];
9165f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
9172e72742cSMatthew G. Knepley   }
918*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9192e72742cSMatthew G. Knepley }
9202e72742cSMatthew G. Knepley 
921d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
922d71ae5a4SJacob Faibussowitsch {
9233be36e83SMatthew G. Knepley   PetscSF            sf;
9243be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9253be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9263be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9273be36e83SMatthew G. Knepley   PetscMPIInt        rank;
9283be36e83SMatthew G. Knepley 
9293be36e83SMatthew G. Knepley   PetscFunctionBegin;
9305f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9329566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9339566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
9343be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
9359566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9369566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9373be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
9389566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
9399371c9d4SSatish Balay   if (l < 0) {
9409371c9d4SSatish Balay     if (mapFailed) *mapFailed = PETSC_TRUE;
9419371c9d4SSatish Balay   } else *remotePoint = remotes[l];
942*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9433be36e83SMatthew G. Knepley owned:
9443be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
9453be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
946*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9473be36e83SMatthew G. Knepley }
9483be36e83SMatthew G. Knepley 
949d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
950d71ae5a4SJacob Faibussowitsch {
9513be36e83SMatthew G. Knepley   PetscSF         sf;
9523be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
9533be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
9543be36e83SMatthew G. Knepley 
9553be36e83SMatthew G. Knepley   PetscFunctionBegin;
9563be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
9579566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9589566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
959*3ba16761SJacob Faibussowitsch   if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS);
9609566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
9619371c9d4SSatish Balay   if (idx >= 0) {
9629371c9d4SSatish Balay     *isShared = PETSC_TRUE;
963*3ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9649371c9d4SSatish Balay   }
9659566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9669566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9673be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
968*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9693be36e83SMatthew G. Knepley }
9703be36e83SMatthew G. Knepley 
971d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
972d71ae5a4SJacob Faibussowitsch {
9733be36e83SMatthew G. Knepley   const PetscInt *cone;
9743be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9753be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
9763be36e83SMatthew G. Knepley 
9773be36e83SMatthew G. Knepley   PetscFunctionBegin;
9789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
9799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
9803be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
9813be36e83SMatthew G. Knepley     PetscBool pointShared;
9823be36e83SMatthew G. Knepley 
9839566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
9843be36e83SMatthew G. Knepley     cShared = (PetscBool)(cShared && pointShared);
9853be36e83SMatthew G. Knepley   }
9863be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
987*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9883be36e83SMatthew G. Knepley }
9893be36e83SMatthew G. Knepley 
990d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
991d71ae5a4SJacob Faibussowitsch {
9923be36e83SMatthew G. Knepley   const PetscInt *cone;
9933be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9943be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
9953be36e83SMatthew G. Knepley 
9963be36e83SMatthew G. Knepley   PetscFunctionBegin;
9979566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
9989566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
9993be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10003be36e83SMatthew G. Knepley     PetscSFNode rcp;
10015f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
10023be36e83SMatthew G. Knepley 
10039566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
10045f80ce2aSJacob Faibussowitsch     if (mapFailed) {
10053be36e83SMatthew G. Knepley       cmin = missing;
10063be36e83SMatthew G. Knepley     } else {
10073be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10083be36e83SMatthew G. Knepley     }
10093be36e83SMatthew G. Knepley   }
10103be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
1011*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10123be36e83SMatthew G. Knepley }
10133be36e83SMatthew G. Knepley 
10143be36e83SMatthew G. Knepley /*
10153be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10163be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10173be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10183be36e83SMatthew G. Knepley */
1019d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
1020d71ae5a4SJacob Faibussowitsch {
10213be36e83SMatthew G. Knepley   MPI_Comm        comm;
10223be36e83SMatthew G. Knepley   const PetscInt *support;
1023cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10243be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10253be36e83SMatthew G. Knepley 
10263be36e83SMatthew G. Knepley   PetscFunctionBegin;
10279566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
10289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
10309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
10319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
1032cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight + 1) {
1033cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
103463a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Skipping face %" PetscInt_FMT " to avoid adding cell to hashmap since this is nonoverlapping mesh\n", rank, p));
1035*3ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1036cf4dc471SVaclav Hapla   }
10379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
10389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
10399566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
10403be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
10413be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
10423be36e83SMatthew G. Knepley     const PetscInt *cone;
10433be36e83SMatthew G. Knepley     PetscSFNode     cpmin = {-1, -1}, rp = {-1, -1};
10443be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
10453be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
10463be36e83SMatthew G. Knepley     PetscHashIJKey  key;
10473be36e83SMatthew G. Knepley 
10483be36e83SMatthew G. Knepley     /* Only add point once */
104963a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
10503be36e83SMatthew G. Knepley     key.i = p;
10513be36e83SMatthew G. Knepley     key.j = face;
10529566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
10533be36e83SMatthew G. Knepley     if (f >= 0) continue;
10549566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
10559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
10569566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
10573be36e83SMatthew G. Knepley     if (debug) {
105863a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
105963a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Global point (%" PetscInt_FMT ", %" PetscInt_FMT ") Min Cone Point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index));
10603be36e83SMatthew G. Knepley     }
10613be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
10629566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
10633be36e83SMatthew G. Knepley       if (candidates) {
106463a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
10659566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
10669566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
10673be36e83SMatthew G. Knepley         candidates[off + idx].rank    = -1;
10683be36e83SMatthew G. Knepley         candidates[off + idx++].index = coneSize - 1;
10693be36e83SMatthew G. Knepley         candidates[off + idx].rank    = rank;
10703be36e83SMatthew G. Knepley         candidates[off + idx++].index = face;
10713be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
10723be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
10733be36e83SMatthew G. Knepley 
10743be36e83SMatthew G. Knepley           if (cp == p) continue;
10759566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
107663a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
10773be36e83SMatthew G. Knepley           ++idx;
10783be36e83SMatthew G. Knepley         }
10799566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
10803be36e83SMatthew G. Knepley       } else {
10813be36e83SMatthew G. Knepley         /* Add cone size to section */
108263a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
10839566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
10849566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
10859566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
10863be36e83SMatthew G. Knepley       }
10873be36e83SMatthew G. Knepley     }
10883be36e83SMatthew G. Knepley   }
1089*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10903be36e83SMatthew G. Knepley }
10913be36e83SMatthew G. Knepley 
10922e72742cSMatthew G. Knepley /*@
10932e72742cSMatthew G. Knepley   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation
10942e72742cSMatthew G. Knepley 
1095d083f849SBarry Smith   Collective on dm
10962e72742cSMatthew G. Knepley 
10972e72742cSMatthew G. Knepley   Input Parameters:
10982e72742cSMatthew G. Knepley + dm      - The interpolated DM
10992e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points
11002e72742cSMatthew G. Knepley 
11012e72742cSMatthew G. Knepley   Output Parameter:
11022e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points
11032e72742cSMatthew G. Knepley 
1104f0cfc026SVaclav Hapla   Level: developer
11052e72742cSMatthew G. Knepley 
11062e72742cSMatthew G. Knepley    Note: All debugging for this process can be turned on with the options: -dm_interp_pre_view -petscsf_interp_pre_view -petscsection_interp_candidate_view -petscsection_interp_candidate_remote_view -petscsection_interp_claim_view -petscsf_interp_pre_view -dmplex_interp_debug
11072e72742cSMatthew G. Knepley 
1108db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexUninterpolate()`
11092e72742cSMatthew G. Knepley @*/
1110d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
1111d71ae5a4SJacob Faibussowitsch {
11123be36e83SMatthew G. Knepley   MPI_Comm           comm;
11133be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
11143be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
11153be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11163be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11172e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11182e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11193be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11203be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11213be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1122f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11232e72742cSMatthew G. Knepley 
11242e72742cSMatthew G. Knepley   PetscFunctionBegin;
1125f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1126064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11279566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
1128*3ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
11293be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
11309566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
11319566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
113428b400f6SJacob Faibussowitsch   PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
11359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
11369566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
11379566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
11389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
11393be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
11409566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
114108401ef6SPierre Jolivet   PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
11429566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
11433be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
11443be36e83SMatthew G. Knepley     PetscHashIJKey key;
11452e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
11462e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
11479566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
11487bffde78SMichael Lange   }
114966aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
11509566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
11519566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
11529566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
11533be36e83SMatthew G. Knepley   /*
11543be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
11553be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
11563be36e83SMatthew G. Knepley   \begin{itemize}
11573be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
11583be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
11593be36e83SMatthew G. Knepley   \end{itemize}
11603be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
11613be36e83SMatthew G. Knepley   \item At the root, if at least two faces with a given cone are present, including a local face, mark the face as shared \label{alg:rootStep} and choose the root face
11623be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
11633be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
11643be36e83SMatthew G. Knepley   */
11653be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
11663be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
11673be36e83SMatthew G. Knepley        The array holds candidate shared faces, each face is refered to by the leaf point */
11689566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
11699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
11707bffde78SMichael Lange   {
11713be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
11722e72742cSMatthew G. Knepley 
11739566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
11743be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11753be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11762e72742cSMatthew G. Knepley 
117763a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
11789566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
11792e72742cSMatthew G. Knepley     }
11809566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
11819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
11829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
11839566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
11843be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11853be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11862e72742cSMatthew G. Knepley 
118763a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
11889566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
11892e72742cSMatthew G. Knepley     }
11909566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
11919566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
11927bffde78SMichael Lange   }
11939566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
11949566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
11959566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
11963be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
11972e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
11987bffde78SMichael Lange   {
11997bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
12007bffde78SMichael Lange     PetscInt *remoteOffsets;
12012e72742cSMatthew G. Knepley 
12029566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
12039566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
12049566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
12059566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
12069566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
12079566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
12089566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
12099566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12109566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12119566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
12129566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
12139566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
12142e72742cSMatthew G. Knepley 
12159566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12169566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12179566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12187bffde78SMichael Lange   }
12193be36e83SMatthew G. Knepley   /* Step 3: At the root, if at least two faces with a given cone are present, including a local face, mark the face as shared and choose the root face */
12207bffde78SMichael Lange   {
12213be36e83SMatthew G. Knepley     PetscHashIJKLRemote faceTable;
12223be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12233be36e83SMatthew G. Knepley 
12249566063dSJacob Faibussowitsch     PetscCall(PetscHashIJKLRemoteCreate(&faceTable));
12252e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12263be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12272e72742cSMatthew G. Knepley       PetscInt deg;
12283be36e83SMatthew G. Knepley 
12292e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
12302e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
12312e72742cSMatthew G. Knepley 
12329566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
12339566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
12343be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12352e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12363be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
12373be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
12383be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx + 1];
12393be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
12403be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
12413be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
12422e72742cSMatthew G. Knepley           const PetscInt        *join = NULL;
12433be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
12443be36e83SMatthew G. Knepley           PetscHashIter          iter;
12455f80ce2aSJacob Faibussowitsch           PetscBool              missing, mapToLocalPointFailed = PETSC_FALSE;
12462e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
12472e72742cSMatthew G. Knepley 
12489371c9d4SSatish Balay           if (debug)
12499371c9d4SSatish Balay             PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking face (%" PetscInt_FMT ", %" PetscInt_FMT ") at (%" PetscInt_FMT ", %" PetscInt_FMT ", %" PetscInt_FMT ") with cone size %" PetscInt_FMT "\n", rank, rface.rank,
12509371c9d4SSatish Balay                                               rface.index, r, idx, d, Np));
125163a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle face (%" PetscInt_FMT ", %" PetscInt_FMT ") at (%" PetscInt_FMT ", %" PetscInt_FMT ", %" PetscInt_FMT ") with %" PetscInt_FMT " cone points", rface.rank, rface.index, r, idx, d, Np);
12523be36e83SMatthew G. Knepley           fcp0.rank  = rank;
12533be36e83SMatthew G. Knepley           fcp0.index = r;
12543be36e83SMatthew G. Knepley           d += Np;
12553be36e83SMatthew G. Knepley           /* Put remote face in hash table */
12563be36e83SMatthew G. Knepley           key.i = fcp0;
12573be36e83SMatthew G. Knepley           key.j = fcone[0];
12583be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
12593be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
12609566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
12619566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing));
12623be36e83SMatthew G. Knepley           if (missing) {
126363a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
12649566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface));
12653be36e83SMatthew G. Knepley           } else {
12663be36e83SMatthew G. Knepley             PetscSFNode oface;
12673be36e83SMatthew G. Knepley 
12689566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface));
12693be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
127063a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
12719566063dSJacob Faibussowitsch               PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface));
12723be36e83SMatthew G. Knepley             }
12733be36e83SMatthew G. Knepley           }
12743be36e83SMatthew G. Knepley           /* Check for local face */
12752e72742cSMatthew G. Knepley           points[0] = r;
12763be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
12779566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
12785f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
127963a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
12807bffde78SMichael Lange           }
12815f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
12829566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
12837bffde78SMichael Lange           if (joinSize == 1) {
12843be36e83SMatthew G. Knepley             PetscSFNode lface;
12853be36e83SMatthew G. Knepley             PetscSFNode oface;
12863be36e83SMatthew G. Knepley 
12873be36e83SMatthew G. Knepley             /* Always replace with local face */
12883be36e83SMatthew G. Knepley             lface.rank  = rank;
12893be36e83SMatthew G. Knepley             lface.index = join[0];
12909566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface));
12919371c9d4SSatish Balay             if (debug)
12929371c9d4SSatish Balay               PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing (%" PetscInt_FMT ", %" PetscInt_FMT ") with local face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, oface.index, oface.rank, lface.index, lface.rank));
12939566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, lface));
12947bffde78SMichael Lange           }
12959566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
12963be36e83SMatthew G. Knepley         }
12973be36e83SMatthew G. Knepley       }
12983be36e83SMatthew G. Knepley       /* Put back faces for this root */
12993be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
13003be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
13013be36e83SMatthew G. Knepley 
13029566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
13039566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
13043be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
13053be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13063be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
13073be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13083be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13093be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
13103be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
13113be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
13123be36e83SMatthew G. Knepley           PetscHashIter          iter;
13133be36e83SMatthew G. Knepley           PetscBool              missing;
13143be36e83SMatthew G. Knepley 
131563a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
131663a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13173be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13183be36e83SMatthew G. Knepley           fcp0.index = r;
13193be36e83SMatthew G. Knepley           d += Np;
13203be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13213be36e83SMatthew G. Knepley           key.i = fcp0;
13223be36e83SMatthew G. Knepley           key.j = fcone[0];
13233be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13243be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13259566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13269371c9d4SSatish Balay           if (debug)
13279371c9d4SSatish Balay             PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]    key (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank,
13289371c9d4SSatish Balay                                               key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index));
13299566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing));
133063a3b9bcSJacob Faibussowitsch           PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1331f7d195e4SLawrence Mitchell           PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
13327bffde78SMichael Lange         }
13337bffde78SMichael Lange       }
13347bffde78SMichael Lange     }
13359566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
13369566063dSJacob Faibussowitsch     PetscCall(PetscHashIJKLRemoteDestroy(&faceTable));
13377bffde78SMichael Lange   }
13383be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
13397bffde78SMichael Lange   {
13407bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
13417bffde78SMichael Lange     PetscSFNode *remotePointsNew;
13422e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
13433be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
13442e72742cSMatthew G. Knepley 
13453be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
13469566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
13479566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
13489566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
13499566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
13509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
13519566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
13523be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
13539566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13549566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13559566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
13569566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
13579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
13589566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
13599566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
13603be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
13613be36e83SMatthew G. Knepley     /* TODO I should not have to do a join here since I already put the face and its cone in the candidate section */
13629566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
13633be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
13643be36e83SMatthew G. Knepley       PetscInt dof, off, d;
13652e72742cSMatthew G. Knepley 
136663a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
13679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
13689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
13692e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
13703be36e83SMatthew G. Knepley         if (claims[off + d].rank >= 0) {
13713be36e83SMatthew G. Knepley           const PetscInt  faceInd = off + d;
13723be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off + d].index;
13732e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
13742e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
13752e72742cSMatthew G. Knepley 
137663a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
13773be36e83SMatthew G. Knepley           points[0] = r;
137863a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
13793be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
13809566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
138163a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c + 1]));
13822e72742cSMatthew G. Knepley           }
13839566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
13842e72742cSMatthew G. Knepley           if (joinSize == 1) {
13853be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
138663a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
13873be36e83SMatthew G. Knepley             } else {
138863a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
13899566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
13902e72742cSMatthew G. Knepley             }
13913be36e83SMatthew G. Knepley           } else {
13929566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
13933be36e83SMatthew G. Knepley           }
13949566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
13953be36e83SMatthew G. Knepley         } else {
139663a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
13973be36e83SMatthew G. Knepley           d += claims[off + d].index + 1;
13987bffde78SMichael Lange         }
13997bffde78SMichael Lange       }
14003be36e83SMatthew G. Knepley     }
14019566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
14023be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
14039566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
14049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
14069566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
14073be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
14083be36e83SMatthew G. Knepley       localPointsNew[l]        = localPoints[l];
14093be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
14103be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
14117bffde78SMichael Lange     }
14123be36e83SMatthew G. Knepley     p = Nl;
14139566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
14143be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
14159566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(NlNew, &localPointsNew[Nl]));
14163be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14173be36e83SMatthew G. Knepley       PetscInt off;
14189566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
14191dca8a05SBarry Smith       PetscCheck(claims[off].rank >= 0 && claims[off].index >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %" PetscInt_FMT ", (%" PetscInt_FMT ", %" PetscInt_FMT ")", localPointsNew[p], claims[off].rank, claims[off].index);
14203be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14217bffde78SMichael Lange     }
14229566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
14239566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14249566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
14259566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
14269566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1427d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
14289566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
14299566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
14307bffde78SMichael Lange   }
14319566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
14329566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
14339566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
14349566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
14359566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
14369566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
14379566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
14389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
1439*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14407bffde78SMichael Lange }
14417bffde78SMichael Lange 
1442248eb259SVaclav Hapla /*@
144380330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
144480330477SMatthew G. Knepley 
1445d083f849SBarry Smith   Collective on dm
144680330477SMatthew G. Knepley 
1447e56d480eSMatthew G. Knepley   Input Parameters:
1448e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices
144910a67516SMatthew G. Knepley - dmInt - The interpolated DM
145080330477SMatthew G. Knepley 
145180330477SMatthew G. Knepley   Output Parameter:
14524e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object
145380330477SMatthew G. Knepley 
145480330477SMatthew G. Knepley   Level: intermediate
145580330477SMatthew G. Knepley 
145695452b02SPatrick Sanan   Notes:
14577fb59074SVaclav Hapla     Labels and coordinates are copied.
145843eeeb2dSStefano Zampini 
14599ade3219SVaclav Hapla   Developer Notes:
14609ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL.
14619ade3219SVaclav Hapla 
1462db781477SPatrick Sanan .seealso: `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
146380330477SMatthew G. Knepley @*/
1464d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
1465d71ae5a4SJacob Faibussowitsch {
1466a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
14679a5b13a2SMatthew G Knepley   DM                     idm, odm = dm;
14687bffde78SMichael Lange   PetscSF                sfPoint;
14692e1b13c2SMatthew G. Knepley   PetscInt               depth, dim, d;
147010a67516SMatthew G. Knepley   const char            *name;
1471b325530aSVaclav Hapla   PetscBool              flg = PETSC_TRUE;
14729f074e33SMatthew G Knepley 
14739f074e33SMatthew G Knepley   PetscFunctionBegin;
147410a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
147510a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
14769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
14779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
14789566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
14799566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
148008401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1481827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
14829566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
148376b791aaSMatthew G. Knepley     idm = dm;
1484b21b8912SMatthew G. Knepley   } else {
14859a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
14869a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
14879566063dSJacob Faibussowitsch       PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
14889566063dSJacob Faibussowitsch       PetscCall(DMSetType(idm, DMPLEX));
14899566063dSJacob Faibussowitsch       PetscCall(DMSetDimension(idm, dim));
14907bffde78SMichael Lange       if (depth > 0) {
14919566063dSJacob Faibussowitsch         PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
14929566063dSJacob Faibussowitsch         PetscCall(DMGetPointSF(odm, &sfPoint));
1493d7d32a9aSMatthew G. Knepley         if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
149494488200SVaclav Hapla         {
14953be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
149694488200SVaclav Hapla           PetscInt nroots;
14979566063dSJacob Faibussowitsch           PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
14989566063dSJacob Faibussowitsch           if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
149994488200SVaclav Hapla         }
15007bffde78SMichael Lange       }
15019566063dSJacob Faibussowitsch       if (odm != dm) PetscCall(DMDestroy(&odm));
15029a5b13a2SMatthew G Knepley       odm = idm;
15039f074e33SMatthew G Knepley     }
15049566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
15059566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)idm, name));
15069566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
15079566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
15089566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
15099566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
151084699f70SSatish Balay   }
1511827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1512827c4036SVaclav Hapla   {
1513d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)idm->data;
1514827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1515827c4036SVaclav Hapla   }
15165de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
15179a5b13a2SMatthew G Knepley   *dmInt = idm;
15189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
1519*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15209f074e33SMatthew G Knepley }
152107b0a1fcSMatthew G Knepley 
152280330477SMatthew G. Knepley /*@
152380330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
152480330477SMatthew G. Knepley 
1525d083f849SBarry Smith   Collective on dmA
152680330477SMatthew G. Knepley 
152780330477SMatthew G. Knepley   Input Parameter:
152880330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates
152980330477SMatthew G. Knepley 
153080330477SMatthew G. Knepley   Output Parameter:
153180330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates
153280330477SMatthew G. Knepley 
153380330477SMatthew G. Knepley   Level: intermediate
153480330477SMatthew G. Knepley 
153580330477SMatthew G. Knepley   Note: This is typically used when adding pieces other than vertices to a mesh
153680330477SMatthew G. Knepley 
1537db781477SPatrick Sanan .seealso: `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
153880330477SMatthew G. Knepley @*/
1539d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
1540d71ae5a4SJacob Faibussowitsch {
154107b0a1fcSMatthew G Knepley   Vec          coordinatesA, coordinatesB;
154243eeeb2dSStefano Zampini   VecType      vtype;
154307b0a1fcSMatthew G Knepley   PetscSection coordSectionA, coordSectionB;
154407b0a1fcSMatthew G Knepley   PetscScalar *coordsA, *coordsB;
15450bedd6beSMatthew G. Knepley   PetscInt     spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
154690a8aa44SJed Brown   PetscInt     cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
154743eeeb2dSStefano Zampini   PetscBool    lc = PETSC_FALSE;
154807b0a1fcSMatthew G Knepley 
154907b0a1fcSMatthew G Knepley   PetscFunctionBegin;
155043eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
155143eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
1552*3ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
15539566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
15549566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
15559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
15569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
155763a3b9bcSJacob Faibussowitsch   PetscCheck((vEndA - vStartA) == (vEndB - vStartB), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %" PetscInt_FMT " != %" PetscInt_FMT " in the second DM", vEndA - vStartA, vEndB - vStartB);
155861a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
155961a622f3SMatthew G. Knepley   {
156061a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
156161a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
156261a622f3SMatthew G. Knepley     PetscObject        objA, objB;
156361a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
156461a622f3SMatthew G. Knepley     const PetscScalar *constants;
156561a622f3SMatthew G. Knepley     PetscInt           cdim, Nc;
156661a622f3SMatthew G. Knepley 
15679566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
15689566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
15699566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
15709566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
15719566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
15729566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
157361a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
15749566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
15759566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
15769566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
15779566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
15789566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
15799566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
15809566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
15819566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
158261a622f3SMatthew G. Knepley     }
158361a622f3SMatthew G. Knepley   }
15849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
15859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
15869566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
15879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
1588*3ba16761SJacob Faibussowitsch   if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS);
15899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
1590*3ba16761SJacob Faibussowitsch   if (!Nf) PetscFunctionReturn(PETSC_SUCCESS);
159163a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1592df26b574SMatthew G. Knepley   if (!coordSectionB) {
1593df26b574SMatthew G. Knepley     PetscInt dim;
1594df26b574SMatthew G. Knepley 
15959566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
15969566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
15979566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
15989566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1599df26b574SMatthew G. Knepley   }
16009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
16019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
16029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
16039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
160443eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
160563a3b9bcSJacob Faibussowitsch     PetscCheck((cEndA - cStartA) == (cEndB - cStartB), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %" PetscInt_FMT " != %" PetscInt_FMT " in the second DM", cEndA - cStartA, cEndB - cStartB);
160643eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
160743eeeb2dSStefano Zampini     cE = vEndB;
160843eeeb2dSStefano Zampini     lc = PETSC_TRUE;
160943eeeb2dSStefano Zampini   } else {
161043eeeb2dSStefano Zampini     cS = vStartB;
161143eeeb2dSStefano Zampini     cE = vEndB;
161243eeeb2dSStefano Zampini   }
16139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
161407b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
16159566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
16169566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
161707b0a1fcSMatthew G Knepley   }
161843eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
161943eeeb2dSStefano Zampini     PetscInt c;
162043eeeb2dSStefano Zampini 
162143eeeb2dSStefano Zampini     for (c = cS - cStartB; c < cEndB - cStartB; c++) {
162243eeeb2dSStefano Zampini       PetscInt dof;
162343eeeb2dSStefano Zampini 
16249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
16259566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSectionB, c + cStartB, dof));
16269566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof));
162743eeeb2dSStefano Zampini     }
162843eeeb2dSStefano Zampini   }
16299566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
16309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
16319566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
16329566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
16339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
16349566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
16359566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
16369566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
16379566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
16389566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
16399566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
16409566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
164107b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB - vStartB; ++v) {
164243eeeb2dSStefano Zampini     PetscInt offA, offB;
164343eeeb2dSStefano Zampini 
16449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
16459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1646ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
164743eeeb2dSStefano Zampini   }
164843eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
164943eeeb2dSStefano Zampini     PetscInt c;
165043eeeb2dSStefano Zampini 
165143eeeb2dSStefano Zampini     for (c = cS - cStartB; c < cEndB - cStartB; c++) {
165243eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
165343eeeb2dSStefano Zampini 
16549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA));
16559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB));
16569566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
16579566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(coordsB + offB, coordsA + offA, dof));
165807b0a1fcSMatthew G Knepley     }
165907b0a1fcSMatthew G Knepley   }
16609566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
16619566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
16629566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
16639566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
1664*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
166507b0a1fcSMatthew G Knepley }
16665c386225SMatthew G. Knepley 
16674e3744c5SMatthew G. Knepley /*@
16684e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
16694e3744c5SMatthew G. Knepley 
1670d083f849SBarry Smith   Collective on dm
16714e3744c5SMatthew G. Knepley 
16724e3744c5SMatthew G. Knepley   Input Parameter:
16734e3744c5SMatthew G. Knepley . dm - The complete DMPlex object
16744e3744c5SMatthew G. Knepley 
16754e3744c5SMatthew G. Knepley   Output Parameter:
16764e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices
16774e3744c5SMatthew G. Knepley 
16784e3744c5SMatthew G. Knepley   Level: intermediate
16794e3744c5SMatthew G. Knepley 
168095452b02SPatrick Sanan   Notes:
168195452b02SPatrick Sanan     It does not copy over the coordinates.
168243eeeb2dSStefano Zampini 
16839ade3219SVaclav Hapla   Developer Notes:
16849ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
16859ade3219SVaclav Hapla 
1686db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
16874e3744c5SMatthew G. Knepley @*/
1688d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
1689d71ae5a4SJacob Faibussowitsch {
1690827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
16914e3744c5SMatthew G. Knepley   DM                     udm;
1692412e9a14SMatthew G. Knepley   PetscInt               dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
16934e3744c5SMatthew G. Knepley 
16944e3744c5SMatthew G. Knepley   PetscFunctionBegin;
169543eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
169643eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
16979566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
16989566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
169908401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1700827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1701827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
17029566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1703595d4abbSMatthew G. Knepley     *dmUnint = dm;
1704*3ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
17054e3744c5SMatthew G. Knepley   }
17069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
17079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17089566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
17099566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
17109566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
17119566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
17124e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1713595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17144e3744c5SMatthew G. Knepley 
17159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17164e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17174e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17184e3744c5SMatthew G. Knepley 
17194e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
17204e3744c5SMatthew G. Knepley     }
17219566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17229566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1723595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
17244e3744c5SMatthew G. Knepley   }
17259566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
17269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
17274e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1728595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17294e3744c5SMatthew G. Knepley 
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17314e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17324e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17334e3744c5SMatthew G. Knepley 
17344e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
17354e3744c5SMatthew G. Knepley     }
17369566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17379566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
17384e3744c5SMatthew G. Knepley   }
17399566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
17409566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
17419566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
17425c7de58aSMatthew G. Knepley   /* Reduce SF */
17435c7de58aSMatthew G. Knepley   {
17445c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
17455c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
17465c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
17475c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
17485c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
174922fd0ad9SVaclav Hapla     PetscInt           numRoots, numLeaves, l;
17505c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
17515c7de58aSMatthew G. Knepley 
17525c7de58aSMatthew G. Knepley     /* Get original SF information */
17539566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
1754d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
17559566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
17569566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
175722fd0ad9SVaclav Hapla     if (numRoots >= 0) {
17585c7de58aSMatthew G. Knepley       /* Allocate space for cells and vertices */
175922fd0ad9SVaclav Hapla       for (l = 0; l < numLeaves; ++l) {
176022fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
176122fd0ad9SVaclav Hapla 
176222fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
176322fd0ad9SVaclav Hapla       }
17645c7de58aSMatthew G. Knepley       /* Fill in leaves */
17659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
17669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
17675c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
176822fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
176922fd0ad9SVaclav Hapla 
177022fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
177122fd0ad9SVaclav Hapla           localPointsUn[n]        = p;
17725c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
17735c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
17745c7de58aSMatthew G. Knepley           ++n;
17755c7de58aSMatthew G. Knepley         }
17765c7de58aSMatthew G. Knepley       }
177763a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
177822fd0ad9SVaclav Hapla       PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
17795c7de58aSMatthew G. Knepley     }
17805c7de58aSMatthew G. Knepley   }
1781827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1782827c4036SVaclav Hapla   {
1783d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)udm->data;
1784827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1785827c4036SVaclav Hapla   }
17865de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1787d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
17884e3744c5SMatthew G. Knepley   *dmUnint = udm;
1789*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17904e3744c5SMatthew G. Knepley }
1791a7748839SVaclav Hapla 
1792d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1793d71ae5a4SJacob Faibussowitsch {
1794a7748839SVaclav Hapla   PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1795a7748839SVaclav Hapla   MPI_Comm comm;
1796a7748839SVaclav Hapla 
1797a7748839SVaclav Hapla   PetscFunctionBegin;
17989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
17999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
18009566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1801a7748839SVaclav Hapla 
1802a7748839SVaclav Hapla   if (depth == dim) {
1803a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1804a7748839SVaclav Hapla     if (!dim) goto finish;
1805a7748839SVaclav Hapla 
1806a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
18079566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1808a7748839SVaclav Hapla     for (p = pStart; p < pEnd; p++) {
18099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1810a7748839SVaclav Hapla       if (coneSize) {
1811a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1812a7748839SVaclav Hapla         goto finish;
1813a7748839SVaclav Hapla       }
1814a7748839SVaclav Hapla     }
1815a7748839SVaclav Hapla 
1816a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1817a7748839SVaclav Hapla     for (h = 0; h < dim; h++) {
18189566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1819a7748839SVaclav Hapla       for (p = pStart; p < pEnd; p++) {
18209566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1821a7748839SVaclav Hapla         if (!coneSize) {
1822a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1823a7748839SVaclav Hapla           goto finish;
1824a7748839SVaclav Hapla         }
1825a7748839SVaclav Hapla       }
1826a7748839SVaclav Hapla     }
1827a7748839SVaclav Hapla   } else if (depth == 1) {
1828a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1829a7748839SVaclav Hapla   } else {
1830a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1831a7748839SVaclav Hapla   }
1832a7748839SVaclav Hapla finish:
1833*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1834a7748839SVaclav Hapla }
1835a7748839SVaclav Hapla 
1836a7748839SVaclav Hapla /*@
18379ade3219SVaclav Hapla   DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated.
1838a7748839SVaclav Hapla 
1839a7748839SVaclav Hapla   Not Collective
1840a7748839SVaclav Hapla 
1841a7748839SVaclav Hapla   Input Parameter:
1842a7748839SVaclav Hapla . dm      - The DM object
1843a7748839SVaclav Hapla 
1844a7748839SVaclav Hapla   Output Parameter:
1845a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1846a7748839SVaclav Hapla 
1847a7748839SVaclav Hapla   Level: intermediate
1848a7748839SVaclav Hapla 
1849a7748839SVaclav Hapla   Notes:
18509ade3219SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this is NOT collective
18519ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
1852a7748839SVaclav Hapla   However, DMPlexInterpolate() guarantees the result is the same on all.
18539ade3219SVaclav Hapla 
1854a7748839SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED.
1855a7748839SVaclav Hapla 
18569ade3219SVaclav Hapla   Developer Notes:
18579ade3219SVaclav Hapla   Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID.
18589ade3219SVaclav Hapla 
18599ade3219SVaclav Hapla   If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called.
18609ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
18619ade3219SVaclav Hapla   DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL.
18629ade3219SVaclav Hapla 
18639ade3219SVaclav Hapla   If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated.
18649ade3219SVaclav Hapla 
18659ade3219SVaclav Hapla   DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL,
18669ade3219SVaclav Hapla   and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
18679ade3219SVaclav Hapla 
1868db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1869a7748839SVaclav Hapla @*/
1870d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1871d71ae5a4SJacob Faibussowitsch {
1872a7748839SVaclav Hapla   DM_Plex *plex = (DM_Plex *)dm->data;
1873a7748839SVaclav Hapla 
1874a7748839SVaclav Hapla   PetscFunctionBegin;
1875a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1876a7748839SVaclav Hapla   PetscValidPointer(interpolated, 2);
1877a7748839SVaclav Hapla   if (plex->interpolated < 0) {
18789566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
187976bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
1880a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1881a7748839SVaclav Hapla 
18829566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
188308401ef6SPierre Jolivet     PetscCheck(flg == plex->interpolated, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1884a7748839SVaclav Hapla   }
1885a7748839SVaclav Hapla   *interpolated = plex->interpolated;
1886*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1887a7748839SVaclav Hapla }
1888a7748839SVaclav Hapla 
1889a7748839SVaclav Hapla /*@
18909ade3219SVaclav Hapla   DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner).
1891a7748839SVaclav Hapla 
18922666ff3cSVaclav Hapla   Collective
1893a7748839SVaclav Hapla 
1894a7748839SVaclav Hapla   Input Parameter:
1895a7748839SVaclav Hapla . dm      - The DM object
1896a7748839SVaclav Hapla 
1897a7748839SVaclav Hapla   Output Parameter:
1898a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1899a7748839SVaclav Hapla 
1900a7748839SVaclav Hapla   Level: intermediate
1901a7748839SVaclav Hapla 
1902a7748839SVaclav Hapla   Notes:
19039ade3219SVaclav Hapla   Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks.
19049ade3219SVaclav Hapla 
19059ade3219SVaclav Hapla   This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks.
19069ade3219SVaclav Hapla 
19079ade3219SVaclav Hapla   Developer Notes:
19089ade3219SVaclav Hapla   Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID.
19099ade3219SVaclav Hapla 
19109ade3219SVaclav Hapla   If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated.
19119ade3219SVaclav Hapla   MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
19129ade3219SVaclav Hapla   if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED,
19139ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
19149ade3219SVaclav Hapla 
19159ade3219SVaclav Hapla   If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective.
1916a7748839SVaclav Hapla 
1917db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
1918a7748839SVaclav Hapla @*/
1919d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1920d71ae5a4SJacob Faibussowitsch {
1921a7748839SVaclav Hapla   DM_Plex  *plex  = (DM_Plex *)dm->data;
1922a7748839SVaclav Hapla   PetscBool debug = PETSC_FALSE;
1923a7748839SVaclav Hapla 
1924a7748839SVaclav Hapla   PetscFunctionBegin;
1925a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1926a7748839SVaclav Hapla   PetscValidPointer(interpolated, 2);
19279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
1928a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1929a7748839SVaclav Hapla     DMPlexInterpolatedFlag min, max;
1930a7748839SVaclav Hapla     MPI_Comm               comm;
1931a7748839SVaclav Hapla 
19329566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19339566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
19349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
19359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
1936a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1937a7748839SVaclav Hapla     if (debug) {
1938a7748839SVaclav Hapla       PetscMPIInt rank;
1939a7748839SVaclav Hapla 
19409566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
19419566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
19429566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
1943a7748839SVaclav Hapla     }
1944a7748839SVaclav Hapla   }
1945a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
1946*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1947a7748839SVaclav Hapla }
1948