xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision d7d32a9a289aef733b8ef2c46eded51cad567349)
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 
359371c9d4SSatish Balay   static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[]) {
363be36e83SMatthew G. Knepley   PetscInt i;
373be36e83SMatthew G. Knepley 
383be36e83SMatthew G. Knepley   PetscFunctionBegin;
393be36e83SMatthew G. Knepley   for (i = 1; i < n; ++i) {
403be36e83SMatthew G. Knepley     PetscSFNode x = A[i];
413be36e83SMatthew G. Knepley     PetscInt    j;
423be36e83SMatthew G. Knepley 
433be36e83SMatthew G. Knepley     for (j = i - 1; j >= 0; --j) {
443be36e83SMatthew G. Knepley       if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break;
453be36e83SMatthew G. Knepley       A[j + 1] = A[j];
463be36e83SMatthew G. Knepley     }
473be36e83SMatthew G. Knepley     A[j + 1] = x;
483be36e83SMatthew G. Knepley   }
493be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
503be36e83SMatthew G. Knepley }
519f074e33SMatthew G Knepley 
529f074e33SMatthew G Knepley /*
53439ece16SMatthew G. Knepley   DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone
54439ece16SMatthew G. Knepley */
559371c9d4SSatish Balay PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) {
56412e9a14SMatthew G. Knepley   DMPolytopeType *typesTmp;
57412e9a14SMatthew G. Knepley   PetscInt       *sizesTmp, *facesTmp;
58439ece16SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize;
59439ece16SMatthew G. Knepley 
60439ece16SMatthew G. Knepley   PetscFunctionBegin;
61439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(cone, 3);
639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
649566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &typesTmp));
659566063dSJacob Faibussowitsch   if (faceSizes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &sizesTmp));
669566063dSJacob Faibussowitsch   if (faces) PetscCall(DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp));
67ba2698f1SMatthew G. Knepley   switch (ct) {
68ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_POINT:
69ba2698f1SMatthew G. Knepley     if (numFaces) *numFaces = 0;
70ba2698f1SMatthew G. Knepley     break;
71ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
72412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 2;
73412e9a14SMatthew G. Knepley     if (faceTypes) {
749371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
759371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
76412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
77412e9a14SMatthew G. Knepley     }
78412e9a14SMatthew G. Knepley     if (faceSizes) {
799371c9d4SSatish Balay       sizesTmp[0] = 1;
809371c9d4SSatish Balay       sizesTmp[1] = 1;
81412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
82412e9a14SMatthew G. Knepley     }
83c49d9212SMatthew G. Knepley     if (faces) {
849371c9d4SSatish Balay       facesTmp[0] = cone[0];
859371c9d4SSatish Balay       facesTmp[1] = cone[1];
86c49d9212SMatthew G. Knepley       *faces      = facesTmp;
87c49d9212SMatthew G. Knepley     }
88412e9a14SMatthew G. Knepley     break;
89412e9a14SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
90c49d9212SMatthew G. Knepley     if (numFaces) *numFaces = 2;
91412e9a14SMatthew G. Knepley     if (faceTypes) {
929371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
939371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
94412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
95412e9a14SMatthew G. Knepley     }
96412e9a14SMatthew G. Knepley     if (faceSizes) {
979371c9d4SSatish Balay       sizesTmp[0] = 1;
989371c9d4SSatish Balay       sizesTmp[1] = 1;
99412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
100412e9a14SMatthew G. Knepley     }
101412e9a14SMatthew G. Knepley     if (faces) {
1029371c9d4SSatish Balay       facesTmp[0] = cone[0];
1039371c9d4SSatish Balay       facesTmp[1] = cone[1];
104412e9a14SMatthew G. Knepley       *faces      = facesTmp;
105412e9a14SMatthew G. Knepley     }
106c49d9212SMatthew G. Knepley     break;
107ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
108412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 3;
109412e9a14SMatthew G. Knepley     if (faceTypes) {
1109371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1119371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1129371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
113412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
114412e9a14SMatthew G. Knepley     }
115412e9a14SMatthew G. Knepley     if (faceSizes) {
1169371c9d4SSatish Balay       sizesTmp[0] = 2;
1179371c9d4SSatish Balay       sizesTmp[1] = 2;
1189371c9d4SSatish Balay       sizesTmp[2] = 2;
119412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
120412e9a14SMatthew G. Knepley     }
1219a5b13a2SMatthew G Knepley     if (faces) {
1229371c9d4SSatish Balay       facesTmp[0] = cone[0];
1239371c9d4SSatish Balay       facesTmp[1] = cone[1];
1249371c9d4SSatish Balay       facesTmp[2] = cone[1];
1259371c9d4SSatish Balay       facesTmp[3] = cone[2];
1269371c9d4SSatish Balay       facesTmp[4] = cone[2];
1279371c9d4SSatish Balay       facesTmp[5] = cone[0];
1289a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1299a5b13a2SMatthew G Knepley     }
1309f074e33SMatthew G Knepley     break;
131ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
1329a5b13a2SMatthew G Knepley     /* Vertices follow right hand rule */
133412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
134412e9a14SMatthew G. Knepley     if (faceTypes) {
1359371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1369371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1379371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
1389371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEGMENT;
139412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
140412e9a14SMatthew G. Knepley     }
141412e9a14SMatthew G. Knepley     if (faceSizes) {
1429371c9d4SSatish Balay       sizesTmp[0] = 2;
1439371c9d4SSatish Balay       sizesTmp[1] = 2;
1449371c9d4SSatish Balay       sizesTmp[2] = 2;
1459371c9d4SSatish Balay       sizesTmp[3] = 2;
146412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
147412e9a14SMatthew G. Knepley     }
1489a5b13a2SMatthew G Knepley     if (faces) {
1499371c9d4SSatish Balay       facesTmp[0] = cone[0];
1509371c9d4SSatish Balay       facesTmp[1] = cone[1];
1519371c9d4SSatish Balay       facesTmp[2] = cone[1];
1529371c9d4SSatish Balay       facesTmp[3] = cone[2];
1539371c9d4SSatish Balay       facesTmp[4] = cone[2];
1549371c9d4SSatish Balay       facesTmp[5] = cone[3];
1559371c9d4SSatish Balay       facesTmp[6] = cone[3];
1569371c9d4SSatish Balay       facesTmp[7] = cone[0];
1579a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1589a5b13a2SMatthew G Knepley     }
159412e9a14SMatthew G. Knepley     break;
160412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
1619a5b13a2SMatthew G Knepley     if (numFaces) *numFaces = 4;
162412e9a14SMatthew G. Knepley     if (faceTypes) {
1639371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1649371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1659371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1669371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
167412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
168412e9a14SMatthew G. Knepley     }
169412e9a14SMatthew G. Knepley     if (faceSizes) {
1709371c9d4SSatish Balay       sizesTmp[0] = 2;
1719371c9d4SSatish Balay       sizesTmp[1] = 2;
1729371c9d4SSatish Balay       sizesTmp[2] = 2;
1739371c9d4SSatish Balay       sizesTmp[3] = 2;
174412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
175412e9a14SMatthew G. Knepley     }
176412e9a14SMatthew G. Knepley     if (faces) {
1779371c9d4SSatish Balay       facesTmp[0] = cone[0];
1789371c9d4SSatish Balay       facesTmp[1] = cone[1];
1799371c9d4SSatish Balay       facesTmp[2] = cone[2];
1809371c9d4SSatish Balay       facesTmp[3] = cone[3];
1819371c9d4SSatish Balay       facesTmp[4] = cone[0];
1829371c9d4SSatish Balay       facesTmp[5] = cone[2];
1839371c9d4SSatish Balay       facesTmp[6] = cone[1];
1849371c9d4SSatish Balay       facesTmp[7] = cone[3];
185412e9a14SMatthew G. Knepley       *faces      = facesTmp;
186412e9a14SMatthew G. Knepley     }
1879f074e33SMatthew G Knepley     break;
188ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
1892e1b13c2SMatthew G. Knepley     /* Vertices of first face follow right hand rule and normal points away from last vertex */
190412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
191412e9a14SMatthew G. Knepley     if (faceTypes) {
1929371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
1939371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
1949371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
1959371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
196412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
197412e9a14SMatthew G. Knepley     }
198412e9a14SMatthew G. Knepley     if (faceSizes) {
1999371c9d4SSatish Balay       sizesTmp[0] = 3;
2009371c9d4SSatish Balay       sizesTmp[1] = 3;
2019371c9d4SSatish Balay       sizesTmp[2] = 3;
2029371c9d4SSatish Balay       sizesTmp[3] = 3;
203412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
204412e9a14SMatthew G. Knepley     }
2059a5b13a2SMatthew G Knepley     if (faces) {
2069371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2079371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2089371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2099371c9d4SSatish Balay       facesTmp[3]  = cone[0];
2109371c9d4SSatish Balay       facesTmp[4]  = cone[3];
2119371c9d4SSatish Balay       facesTmp[5]  = cone[1];
2129371c9d4SSatish Balay       facesTmp[6]  = cone[0];
2139371c9d4SSatish Balay       facesTmp[7]  = cone[2];
2149371c9d4SSatish Balay       facesTmp[8]  = cone[3];
2159371c9d4SSatish Balay       facesTmp[9]  = cone[2];
2169371c9d4SSatish Balay       facesTmp[10] = cone[1];
2179371c9d4SSatish Balay       facesTmp[11] = cone[3];
2189a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2199a5b13a2SMatthew G Knepley     }
2209a5b13a2SMatthew G Knepley     break;
221ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
222e368ef20SMatthew G. Knepley     /*  7--------6
223e368ef20SMatthew G. Knepley          /|       /|
224e368ef20SMatthew G. Knepley         / |      / |
225e368ef20SMatthew G. Knepley        4--------5  |
226e368ef20SMatthew G. Knepley        |  |     |  |
227e368ef20SMatthew G. Knepley        |  |     |  |
228e368ef20SMatthew G. Knepley        |  1--------2
229e368ef20SMatthew G. Knepley        | /      | /
230e368ef20SMatthew G. Knepley        |/       |/
231e368ef20SMatthew G. Knepley        0--------3
232e368ef20SMatthew G. Knepley        */
233412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
234412e9a14SMatthew G. Knepley     if (faceTypes) {
2359371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
2369371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
2379371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2389371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2399371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
2409371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
241412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
242412e9a14SMatthew G. Knepley     }
243412e9a14SMatthew G. Knepley     if (faceSizes) {
2449371c9d4SSatish Balay       sizesTmp[0] = 4;
2459371c9d4SSatish Balay       sizesTmp[1] = 4;
2469371c9d4SSatish Balay       sizesTmp[2] = 4;
2479371c9d4SSatish Balay       sizesTmp[3] = 4;
2489371c9d4SSatish Balay       sizesTmp[4] = 4;
2499371c9d4SSatish Balay       sizesTmp[5] = 4;
250412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
251412e9a14SMatthew G. Knepley     }
2529a5b13a2SMatthew G Knepley     if (faces) {
2539371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2549371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2559371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2569371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
2579371c9d4SSatish Balay       facesTmp[4]  = cone[4];
2589371c9d4SSatish Balay       facesTmp[5]  = cone[5];
2599371c9d4SSatish Balay       facesTmp[6]  = cone[6];
2609371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
2619371c9d4SSatish Balay       facesTmp[8]  = cone[0];
2629371c9d4SSatish Balay       facesTmp[9]  = cone[3];
2639371c9d4SSatish Balay       facesTmp[10] = cone[5];
2649371c9d4SSatish Balay       facesTmp[11] = cone[4]; /* Front */
2659371c9d4SSatish Balay       facesTmp[12] = cone[2];
2669371c9d4SSatish Balay       facesTmp[13] = cone[1];
2679371c9d4SSatish Balay       facesTmp[14] = cone[7];
2689371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Back */
2699371c9d4SSatish Balay       facesTmp[16] = cone[3];
2709371c9d4SSatish Balay       facesTmp[17] = cone[2];
2719371c9d4SSatish Balay       facesTmp[18] = cone[6];
2729371c9d4SSatish Balay       facesTmp[19] = cone[5]; /* Right */
2739371c9d4SSatish Balay       facesTmp[20] = cone[0];
2749371c9d4SSatish Balay       facesTmp[21] = cone[4];
2759371c9d4SSatish Balay       facesTmp[22] = cone[7];
2769371c9d4SSatish Balay       facesTmp[23] = cone[1]; /* Left */
2779a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2789a5b13a2SMatthew G Knepley     }
27999836e0eSStefano Zampini     break;
280ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM:
281412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
282412e9a14SMatthew G. Knepley     if (faceTypes) {
2839371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2849371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2859371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2869371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2879371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
288412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
289412e9a14SMatthew G. Knepley     }
290412e9a14SMatthew G. Knepley     if (faceSizes) {
2919371c9d4SSatish Balay       sizesTmp[0] = 3;
2929371c9d4SSatish Balay       sizesTmp[1] = 3;
2939371c9d4SSatish Balay       sizesTmp[2] = 4;
2949371c9d4SSatish Balay       sizesTmp[3] = 4;
2959371c9d4SSatish Balay       sizesTmp[4] = 4;
296412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
297412e9a14SMatthew G. Knepley     }
298ba2698f1SMatthew G. Knepley     if (faces) {
2999371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3009371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3019371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3029371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3039371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3049371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3059371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3069371c9d4SSatish Balay       facesTmp[7]  = cone[2];
3079371c9d4SSatish Balay       facesTmp[8]  = cone[4];
3089371c9d4SSatish Balay       facesTmp[9]  = cone[3]; /* Back left */
3099371c9d4SSatish Balay       facesTmp[10] = cone[2];
3109371c9d4SSatish Balay       facesTmp[11] = cone[1];
3119371c9d4SSatish Balay       facesTmp[12] = cone[5];
3129371c9d4SSatish Balay       facesTmp[13] = cone[4]; /* Front */
3139371c9d4SSatish Balay       facesTmp[14] = cone[1];
3149371c9d4SSatish Balay       facesTmp[15] = cone[0];
3159371c9d4SSatish Balay       facesTmp[16] = cone[3];
3169371c9d4SSatish Balay       facesTmp[17] = cone[5]; /* Back right */
317ba2698f1SMatthew G. Knepley       *faces       = facesTmp;
31899836e0eSStefano Zampini     }
31999836e0eSStefano Zampini     break;
320ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
321412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
322412e9a14SMatthew G. Knepley     if (faceTypes) {
3239371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
3249371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
3259371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3269371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3279371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
328412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
329412e9a14SMatthew G. Knepley     }
330412e9a14SMatthew G. Knepley     if (faceSizes) {
3319371c9d4SSatish Balay       sizesTmp[0] = 3;
3329371c9d4SSatish Balay       sizesTmp[1] = 3;
3339371c9d4SSatish Balay       sizesTmp[2] = 4;
3349371c9d4SSatish Balay       sizesTmp[3] = 4;
3359371c9d4SSatish Balay       sizesTmp[4] = 4;
336412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
337412e9a14SMatthew G. Knepley     }
33899836e0eSStefano Zampini     if (faces) {
3399371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3409371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3419371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3429371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3439371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3449371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3459371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3469371c9d4SSatish Balay       facesTmp[7]  = cone[1];
3479371c9d4SSatish Balay       facesTmp[8]  = cone[3];
3489371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Back left */
3499371c9d4SSatish Balay       facesTmp[10] = cone[1];
3509371c9d4SSatish Balay       facesTmp[11] = cone[2];
3519371c9d4SSatish Balay       facesTmp[12] = cone[4];
3529371c9d4SSatish Balay       facesTmp[13] = cone[5]; /* Back right */
3539371c9d4SSatish Balay       facesTmp[14] = cone[2];
3549371c9d4SSatish Balay       facesTmp[15] = cone[0];
3559371c9d4SSatish Balay       facesTmp[16] = cone[5];
3569371c9d4SSatish Balay       facesTmp[17] = cone[3]; /* Front */
35799836e0eSStefano Zampini       *faces       = facesTmp;
35899836e0eSStefano Zampini     }
359412e9a14SMatthew G. Knepley     break;
360412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
361412e9a14SMatthew G. Knepley     /*  7--------6
362412e9a14SMatthew G. Knepley          /|       /|
363412e9a14SMatthew G. Knepley         / |      / |
364412e9a14SMatthew G. Knepley        4--------5  |
365412e9a14SMatthew G. Knepley        |  |     |  |
366412e9a14SMatthew G. Knepley        |  |     |  |
367412e9a14SMatthew G. Knepley        |  3--------2
368412e9a14SMatthew G. Knepley        | /      | /
369412e9a14SMatthew G. Knepley        |/       |/
370412e9a14SMatthew G. Knepley        0--------1
371412e9a14SMatthew G. Knepley        */
372412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
373412e9a14SMatthew G. Knepley     if (faceTypes) {
3749371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
3759371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
3769371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3779371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3789371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3799371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
380412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
381412e9a14SMatthew G. Knepley     }
382412e9a14SMatthew G. Knepley     if (faceSizes) {
3839371c9d4SSatish Balay       sizesTmp[0] = 4;
3849371c9d4SSatish Balay       sizesTmp[1] = 4;
3859371c9d4SSatish Balay       sizesTmp[2] = 4;
3869371c9d4SSatish Balay       sizesTmp[3] = 4;
3879371c9d4SSatish Balay       sizesTmp[4] = 4;
3889371c9d4SSatish Balay       sizesTmp[5] = 4;
389412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
390412e9a14SMatthew G. Knepley     }
391412e9a14SMatthew G. Knepley     if (faces) {
3929371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3939371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3949371c9d4SSatish Balay       facesTmp[2]  = cone[2];
3959371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
3969371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3979371c9d4SSatish Balay       facesTmp[5]  = cone[5];
3989371c9d4SSatish Balay       facesTmp[6]  = cone[6];
3999371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
4009371c9d4SSatish Balay       facesTmp[8]  = cone[0];
4019371c9d4SSatish Balay       facesTmp[9]  = cone[1];
4029371c9d4SSatish Balay       facesTmp[10] = cone[4];
4039371c9d4SSatish Balay       facesTmp[11] = cone[5]; /* Front */
4049371c9d4SSatish Balay       facesTmp[12] = cone[1];
4059371c9d4SSatish Balay       facesTmp[13] = cone[2];
4069371c9d4SSatish Balay       facesTmp[14] = cone[5];
4079371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Right */
4089371c9d4SSatish Balay       facesTmp[16] = cone[2];
4099371c9d4SSatish Balay       facesTmp[17] = cone[3];
4109371c9d4SSatish Balay       facesTmp[18] = cone[6];
4119371c9d4SSatish Balay       facesTmp[19] = cone[7]; /* Back */
4129371c9d4SSatish Balay       facesTmp[20] = cone[3];
4139371c9d4SSatish Balay       facesTmp[21] = cone[0];
4149371c9d4SSatish Balay       facesTmp[22] = cone[7];
4159371c9d4SSatish Balay       facesTmp[23] = cone[4]; /* Left */
416412e9a14SMatthew G. Knepley       *faces       = facesTmp;
417412e9a14SMatthew G. Knepley     }
41899836e0eSStefano Zampini     break;
419da9060c4SMatthew G. Knepley   case DM_POLYTOPE_PYRAMID:
420da9060c4SMatthew G. Knepley     /*
421da9060c4SMatthew G. Knepley        4----
422da9060c4SMatthew G. Knepley        |\-\ \-----
423da9060c4SMatthew G. Knepley        | \ -\     \
424da9060c4SMatthew G. Knepley        |  1--\-----2
425da9060c4SMatthew G. Knepley        | /    \   /
426da9060c4SMatthew G. Knepley        |/      \ /
427da9060c4SMatthew G. Knepley        0--------3
428da9060c4SMatthew G. Knepley        */
429da9060c4SMatthew G. Knepley     if (numFaces) *numFaces = 5;
430da9060c4SMatthew G. Knepley     if (faceTypes) {
431da9060c4SMatthew G. Knepley       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
4329371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
4339371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
4349371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
4359371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_TRIANGLE;
436da9060c4SMatthew G. Knepley       *faceTypes  = typesTmp;
437da9060c4SMatthew G. Knepley     }
438da9060c4SMatthew G. Knepley     if (faceSizes) {
439da9060c4SMatthew G. Knepley       sizesTmp[0] = 4;
4409371c9d4SSatish Balay       sizesTmp[1] = 3;
4419371c9d4SSatish Balay       sizesTmp[2] = 3;
4429371c9d4SSatish Balay       sizesTmp[3] = 3;
4439371c9d4SSatish Balay       sizesTmp[4] = 3;
444da9060c4SMatthew G. Knepley       *faceSizes  = sizesTmp;
445da9060c4SMatthew G. Knepley     }
446da9060c4SMatthew G. Knepley     if (faces) {
4479371c9d4SSatish Balay       facesTmp[0]  = cone[0];
4489371c9d4SSatish Balay       facesTmp[1]  = cone[1];
4499371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4509371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4519371c9d4SSatish Balay       facesTmp[4]  = cone[0];
4529371c9d4SSatish Balay       facesTmp[5]  = cone[3];
4539371c9d4SSatish Balay       facesTmp[6]  = cone[4]; /* Front */
4549371c9d4SSatish Balay       facesTmp[7]  = cone[3];
4559371c9d4SSatish Balay       facesTmp[8]  = cone[2];
4569371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Right */
4579371c9d4SSatish Balay       facesTmp[10] = cone[2];
4589371c9d4SSatish Balay       facesTmp[11] = cone[1];
4599371c9d4SSatish Balay       facesTmp[12] = cone[4]; /* Back */
4609371c9d4SSatish Balay       facesTmp[13] = cone[1];
4619371c9d4SSatish Balay       facesTmp[14] = cone[0];
4629371c9d4SSatish Balay       facesTmp[15] = cone[4]; /* Left */
463da9060c4SMatthew G. Knepley       *faces       = facesTmp;
464da9060c4SMatthew G. Knepley     }
465da9060c4SMatthew G. Knepley     break;
46698921bdaSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
46799836e0eSStefano Zampini   }
46899836e0eSStefano Zampini   PetscFunctionReturn(0);
46999836e0eSStefano Zampini }
47099836e0eSStefano Zampini 
4719371c9d4SSatish Balay PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) {
47299836e0eSStefano Zampini   PetscFunctionBegin;
4739566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes));
4749566063dSJacob Faibussowitsch   if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes));
4759566063dSJacob Faibussowitsch   if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces));
47699836e0eSStefano Zampini   PetscFunctionReturn(0);
47799836e0eSStefano Zampini }
47899836e0eSStefano Zampini 
4799a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
4809371c9d4SSatish Balay static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm) {
481412e9a14SMatthew G. Knepley   DMLabel       ctLabel;
4829a5b13a2SMatthew G Knepley   PetscHashIJKL faceTable;
483412e9a14SMatthew G. Knepley   PetscInt      faceTypeNum[DM_NUM_POLYTOPES];
4849318fe57SMatthew G. Knepley   PetscInt      depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd;
4859f074e33SMatthew G Knepley 
4869f074e33SMatthew G Knepley   PetscFunctionBegin;
4879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4889566063dSJacob Faibussowitsch   PetscCall(PetscHashIJKLCreate(&faceTable));
4899566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
4909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
491412e9a14SMatthew G. Knepley   /* Number new faces and save face vertices in hash table */
4929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
493412e9a14SMatthew G. Knepley   fEnd = fStart;
494412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
495412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
496412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
497ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
498412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
49999836e0eSStefano Zampini 
5009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
503412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
504412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
505412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
506412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
5079a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
508e8f14785SLisandro Dalcin       PetscHashIter        iter;
509e8f14785SLisandro Dalcin       PetscBool            missing;
5109f074e33SMatthew G Knepley 
5115f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
512412e9a14SMatthew G. Knepley       key.i = face[0];
513412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
514412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
515412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
5169566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
5179566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
518e9fa77a1SMatthew G. Knepley       if (missing) {
5199566063dSJacob Faibussowitsch         PetscCall(PetscHashIJKLIterSet(faceTable, iter, fEnd++));
520412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
521e9fa77a1SMatthew G. Knepley       }
5229a5b13a2SMatthew G Knepley     }
5239566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
52499836e0eSStefano Zampini   }
525412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
526412e9a14SMatthew G. Knepley   {
527412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
52899836e0eSStefano Zampini 
5299371c9d4SSatish Balay     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5309371c9d4SSatish Balay       if (faceTypeNum[ct]) ++numFT;
5319371c9d4SSatish Balay       faceTypeStart[ct] = 0;
5329371c9d4SSatish Balay     }
533412e9a14SMatthew G. Knepley     if (numFT > 1) {
5349566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLClear(faceTable));
535412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
536412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
537412e9a14SMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
538412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
539412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
540ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
541412e9a14SMatthew G. Knepley         PetscInt              numFaces, cf, foff = 0;
54299836e0eSStefano Zampini 
5439566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
5449566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
5459566063dSJacob Faibussowitsch         PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
546412e9a14SMatthew G. Knepley         for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
547412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
548412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
549412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
55099836e0eSStefano Zampini           PetscHashIJKLKey     key;
55199836e0eSStefano Zampini           PetscHashIter        iter;
55299836e0eSStefano Zampini           PetscBool            missing;
55399836e0eSStefano Zampini 
5545f80ce2aSJacob Faibussowitsch           PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
555412e9a14SMatthew G. Knepley           key.i = face[0];
556412e9a14SMatthew G. Knepley           key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
557412e9a14SMatthew G. Knepley           key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
558412e9a14SMatthew G. Knepley           key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
5599566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
5609566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
5619566063dSJacob Faibussowitsch           if (missing) PetscCall(PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
56299836e0eSStefano Zampini         }
5639566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
56499836e0eSStefano Zampini       }
565412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
5661dca8a05SBarry 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]);
5679a5b13a2SMatthew G Knepley       }
5689a5b13a2SMatthew G Knepley     }
569412e9a14SMatthew G. Knepley   }
570412e9a14SMatthew G. Knepley   /* Add new points, always at the end of the numbering */
5719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
5729566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
5739a5b13a2SMatthew G Knepley   /* Set cone sizes */
574412e9a14SMatthew G. Knepley   /*   Must create the celltype label here so that we do not automatically try to compute the types */
5759566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
5769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
5779a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
578412e9a14SMatthew G. Knepley     DMPolytopeType ct;
579412e9a14SMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, p;
5809f074e33SMatthew G Knepley 
581412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
5829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
583412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
5849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
5859566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, p, coneSize));
5869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
5879566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, p, ct));
5889f074e33SMatthew G Knepley     }
5899f074e33SMatthew G Knepley   }
590412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
591412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
592412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
593412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
594412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
595412e9a14SMatthew G. Knepley 
5969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5979566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5999566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(idm, c, ct));
6009566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(idm, c, numFaces));
601412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
602412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
603412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
604412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
605412e9a14SMatthew G. Knepley       PetscHashIJKLKey     key;
606412e9a14SMatthew G. Knepley       PetscHashIter        iter;
607412e9a14SMatthew G. Knepley       PetscBool            missing;
608412e9a14SMatthew G. Knepley       PetscInt             f;
609412e9a14SMatthew G. Knepley 
61063a3b9bcSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
611412e9a14SMatthew G. Knepley       key.i = face[0];
612412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
613412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
614412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
6159566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
6169566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
61763a3b9bcSJacob Faibussowitsch       PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %" PetscInt_FMT ", lf %" PetscInt_FMT ")", c, cf);
6189566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f));
6199566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, f, faceSize));
6209566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, f, faceType));
621412e9a14SMatthew G. Knepley     }
6229566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
6239f074e33SMatthew G Knepley   }
6249566063dSJacob Faibussowitsch   PetscCall(DMSetUp(idm));
625412e9a14SMatthew G. Knepley   /* Initialize cones so we do not need the bash table to tell us that a cone has been set */
626412e9a14SMatthew G. Knepley   {
627412e9a14SMatthew G. Knepley     PetscSection cs;
628412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
6299a5b13a2SMatthew G Knepley 
6309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSection(idm, &cs));
6319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCones(idm, &cones));
6329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(cs, &csize));
633412e9a14SMatthew G. Knepley     for (c = 0; c < csize; ++c) cones[c] = -1;
634412e9a14SMatthew G. Knepley   }
635412e9a14SMatthew G. Knepley   /* Set cones */
636412e9a14SMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
637412e9a14SMatthew G. Knepley     const PetscInt *cone;
638412e9a14SMatthew G. Knepley     PetscInt        pStart, pEnd, p;
639412e9a14SMatthew G. Knepley 
640412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
642412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
6439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, p, &cone));
6449566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(idm, p, cone));
6459566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
6469566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeOrientation(idm, p, cone));
6479f074e33SMatthew G Knepley     }
6489a5b13a2SMatthew G Knepley   }
649412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
650412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
651412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
652ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
653412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
65499836e0eSStefano Zampini 
6559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
6579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
658412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
659412e9a14SMatthew G. Knepley       DMPolytopeType   faceType = faceTypes[cf];
660412e9a14SMatthew G. Knepley       const PetscInt   faceSize = faceSizes[cf];
661412e9a14SMatthew G. Knepley       const PetscInt  *face     = &faces[foff];
662412e9a14SMatthew G. Knepley       const PetscInt  *fcone;
6639a5b13a2SMatthew G Knepley       PetscHashIJKLKey key;
664e8f14785SLisandro Dalcin       PetscHashIter    iter;
665e8f14785SLisandro Dalcin       PetscBool        missing;
666412e9a14SMatthew G. Knepley       PetscInt         f;
6679f074e33SMatthew G Knepley 
66863a3b9bcSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
669412e9a14SMatthew G. Knepley       key.i = face[0];
670412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
671412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
672412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
6739566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
6749566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
6759566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f));
6769566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertCone(idm, c, cf, f));
6779566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(idm, f, &fcone));
6789566063dSJacob Faibussowitsch       if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
679412e9a14SMatthew G. Knepley       {
680412e9a14SMatthew G. Knepley         const PetscInt *cone;
681412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
682a74221b0SStefano Zampini 
6839566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
6849566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &cone));
68563a3b9bcSJacob 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);
686d89e6e46SMatthew G. Knepley         /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
6879566063dSJacob Faibussowitsch         PetscCall(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt));
6889566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertConeOrientation(idm, c, cf, ornt));
68999836e0eSStefano Zampini       }
69099836e0eSStefano Zampini     }
6919566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
69299836e0eSStefano Zampini   }
6939566063dSJacob Faibussowitsch   PetscCall(PetscHashIJKLDestroy(&faceTable));
6949566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
6959566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
6969f074e33SMatthew G Knepley   PetscFunctionReturn(0);
6979f074e33SMatthew G Knepley }
6989f074e33SMatthew G Knepley 
6999371c9d4SSatish Balay static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) {
700f80536cbSVaclav Hapla   PetscInt           nleaves;
701f80536cbSVaclav Hapla   PetscInt           nranks;
702a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks   = NULL;
703a0d42dbcSVaclav Hapla   const PetscInt    *roffset = NULL, *rmine = NULL, *rremote = NULL;
704f80536cbSVaclav Hapla   PetscInt           n, o, r;
705f80536cbSVaclav Hapla 
706f80536cbSVaclav Hapla   PetscFunctionBegin;
7079566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
708f80536cbSVaclav Hapla   nleaves = roffset[nranks];
7099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
710f80536cbSVaclav Hapla   for (r = 0; r < nranks; r++) {
711f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
712f80536cbSVaclav Hapla        - to unify order with the other side */
713f80536cbSVaclav Hapla     o = roffset[r];
714f80536cbSVaclav Hapla     n = roffset[r + 1] - o;
7159566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7169566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7179566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
718f80536cbSVaclav Hapla   }
719f80536cbSVaclav Hapla   PetscFunctionReturn(0);
720f80536cbSVaclav Hapla }
721f80536cbSVaclav Hapla 
7229371c9d4SSatish Balay PetscErrorCode DMPlexOrientInterface_Internal(DM dm) {
723d89e6e46SMatthew G. Knepley   PetscSF            sf;
724d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
725d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
726d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
727d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
728d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
729d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
730d89e6e46SMatthew G. Knepley   PetscInt(*roots)[4], (*leaves)[4], mainCone[4];
731d89e6e46SMatthew G. Knepley   PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4];
7322e745bdaSMatthew G. Knepley   MPI_Comm    comm;
73327d0e99aSVaclav Hapla   PetscMPIInt rank, size;
7342e745bdaSMatthew G. Knepley   PetscInt    debug = 0;
7352e745bdaSMatthew G. Knepley 
7362e745bdaSMatthew G. Knepley   PetscFunctionBegin;
7379566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
7389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
7409566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
7419566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
742*d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
7439566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
744d89e6e46SMatthew G. Knepley   if (nroots < 0) PetscFunctionReturn(0);
7459566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
7469566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
747d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
748d89e6e46SMatthew G. Knepley     PetscInt coneSize;
7499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
750d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
751d89e6e46SMatthew G. Knepley   }
75263a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
7539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
7549e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
755d89e6e46SMatthew G. Knepley     const PetscInt *cone;
756d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
757d89e6e46SMatthew G. Knepley 
7589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
7599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
760d89e6e46SMatthew G. Knepley     /* Ignore vertices */
76127d0e99aSVaclav Hapla     if (coneSize < 2) {
762d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
76327d0e99aSVaclav Hapla         roots[p][c]      = -1;
76427d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
76527d0e99aSVaclav Hapla       }
76627d0e99aSVaclav Hapla       continue;
76727d0e99aSVaclav Hapla     }
7682e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
769d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
7709566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
7718a650c75SVaclav Hapla       if (ind0 < 0) {
7728a650c75SVaclav Hapla         roots[p][c]      = cone[c];
7738a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
774c8148b97SVaclav Hapla       } else {
7758a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
7768a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
7778a650c75SVaclav Hapla       }
7782e745bdaSMatthew G. Knepley     }
779d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
780d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
781d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
782d89e6e46SMatthew G. Knepley     }
7832e745bdaSMatthew G. Knepley   }
7849e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
785d89e6e46SMatthew G. Knepley     PetscInt c;
786d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
7878ccb905dSVaclav Hapla       leaves[p][c]      = -2;
7888ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
7898ccb905dSVaclav Hapla     }
790c8148b97SVaclav Hapla   }
7919566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
7929566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
7939566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
7949566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
795d89e6e46SMatthew G. Knepley   if (debug) {
7969566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
797c5853193SPierre Jolivet     if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
798d89e6e46SMatthew G. Knepley   }
7999566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8009e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
801d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
802d89e6e46SMatthew G. Knepley     const PetscInt *cone;
803d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
804d89e6e46SMatthew G. Knepley 
805d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
8069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
8079566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
809d89e6e46SMatthew G. Knepley     if (debug) {
8109371c9d4SSatish 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]));
811d89e6e46SMatthew G. Knepley     }
8129371c9d4SSatish 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]) {
813d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
814d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
815d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
816d89e6e46SMatthew G. Knepley 
81727d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
818d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
8199dddd249SSatish Balay           mainCone[c] = leaves[p][c];
82027d0e99aSVaclav Hapla           continue;
82127d0e99aSVaclav Hapla         }
822f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
823f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
8249566063dSJacob Faibussowitsch         PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r));
82563a3b9bcSJacob 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]);
8261dca8a05SBarry 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]);
827f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
828d89e6e46SMatthew G. Knepley         rS = roffset[r];
829d89e6e46SMatthew G. Knepley         rN = roffset[r + 1] - rS;
8309566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
83163a3b9bcSJacob 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]);
832f80536cbSVaclav Hapla         /* Get the corresponding local point */
8335f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
834f80536cbSVaclav Hapla       }
83563a3b9bcSJacob 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]));
83627d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
8379566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
8389566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
8399566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
84023aaf07bSVaclav Hapla   }
84127d0e99aSVaclav Hapla   if (debug) {
8429566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
8439566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
8442e745bdaSMatthew G. Knepley   }
8459566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
8469566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
8479566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
8482e745bdaSMatthew G. Knepley   PetscFunctionReturn(0);
8492e745bdaSMatthew G. Knepley }
8502e745bdaSMatthew G. Knepley 
8519371c9d4SSatish Balay static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[]) {
8522e72742cSMatthew G. Knepley   PetscInt    idx;
8532e72742cSMatthew G. Knepley   PetscMPIInt rank;
8542e72742cSMatthew G. Knepley   PetscBool   flg;
8557bffde78SMichael Lange 
8567bffde78SMichael Lange   PetscFunctionBegin;
8579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
8582e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
8599566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8609566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
86163a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
8629566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
8632e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
8642e72742cSMatthew G. Knepley }
8652e72742cSMatthew G. Knepley 
8669371c9d4SSatish Balay static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) {
8672e72742cSMatthew G. Knepley   PetscInt    idx;
8682e72742cSMatthew G. Knepley   PetscMPIInt rank;
8692e72742cSMatthew G. Knepley   PetscBool   flg;
8702e72742cSMatthew G. Knepley 
8712e72742cSMatthew G. Knepley   PetscFunctionBegin;
8729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
8732e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
8749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8759566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
8762e72742cSMatthew G. Knepley   if (idxname) {
87763a3b9bcSJacob 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));
8782e72742cSMatthew G. Knepley   } else {
87963a3b9bcSJacob 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));
8802e72742cSMatthew G. Knepley   }
8819566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
8822e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
8832e72742cSMatthew G. Knepley }
8842e72742cSMatthew G. Knepley 
8859371c9d4SSatish Balay static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed) {
8863be36e83SMatthew G. Knepley   PetscSF         sf;
8873be36e83SMatthew G. Knepley   const PetscInt *locals;
8883be36e83SMatthew G. Knepley   PetscMPIInt     rank;
8892e72742cSMatthew G. Knepley 
8902e72742cSMatthew G. Knepley   PetscFunctionBegin;
8919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8929566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
8939566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
8945f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
8952e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
8962e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
8972e72742cSMatthew G. Knepley   } else {
8982e72742cSMatthew G. Knepley     PetscHashIJKey key;
8993be36e83SMatthew G. Knepley     PetscInt       l;
9002e72742cSMatthew G. Knepley 
9012e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9022e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9039566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
9043be36e83SMatthew G. Knepley     if (l >= 0) {
9053be36e83SMatthew G. Knepley       *localPoint = locals[l];
9065f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
9072e72742cSMatthew G. Knepley   }
9082e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
9092e72742cSMatthew G. Knepley }
9102e72742cSMatthew G. Knepley 
9119371c9d4SSatish Balay static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed) {
9123be36e83SMatthew G. Knepley   PetscSF            sf;
9133be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9143be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9153be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9163be36e83SMatthew G. Knepley   PetscMPIInt        rank;
9173be36e83SMatthew G. Knepley 
9183be36e83SMatthew G. Knepley   PetscFunctionBegin;
9195f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9219566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9229566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
9233be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
9249566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9259566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9263be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
9279566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
9289371c9d4SSatish Balay   if (l < 0) {
9299371c9d4SSatish Balay     if (mapFailed) *mapFailed = PETSC_TRUE;
9309371c9d4SSatish Balay   } else *remotePoint = remotes[l];
9313be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9323be36e83SMatthew G. Knepley owned:
9333be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
9343be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
9353be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9363be36e83SMatthew G. Knepley }
9373be36e83SMatthew G. Knepley 
9389371c9d4SSatish Balay static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) {
9393be36e83SMatthew G. Knepley   PetscSF         sf;
9403be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
9413be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
9423be36e83SMatthew G. Knepley 
9433be36e83SMatthew G. Knepley   PetscFunctionBegin;
9443be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
9459566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9469566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
9473be36e83SMatthew G. Knepley   if (Nl < 0) PetscFunctionReturn(0);
9489566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
9499371c9d4SSatish Balay   if (idx >= 0) {
9509371c9d4SSatish Balay     *isShared = PETSC_TRUE;
9519371c9d4SSatish Balay     PetscFunctionReturn(0);
9529371c9d4SSatish Balay   }
9539566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9549566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9553be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
9563be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9573be36e83SMatthew G. Knepley }
9583be36e83SMatthew G. Knepley 
9599371c9d4SSatish Balay static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) {
9603be36e83SMatthew G. Knepley   const PetscInt *cone;
9613be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9623be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
9633be36e83SMatthew G. Knepley 
9643be36e83SMatthew G. Knepley   PetscFunctionBegin;
9659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
9669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
9673be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
9683be36e83SMatthew G. Knepley     PetscBool pointShared;
9693be36e83SMatthew G. Knepley 
9709566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
9713be36e83SMatthew G. Knepley     cShared = (PetscBool)(cShared && pointShared);
9723be36e83SMatthew G. Knepley   }
9733be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
9743be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9753be36e83SMatthew G. Knepley }
9763be36e83SMatthew G. Knepley 
9779371c9d4SSatish Balay static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) {
9783be36e83SMatthew G. Knepley   const PetscInt *cone;
9793be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9803be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
9813be36e83SMatthew G. Knepley 
9823be36e83SMatthew G. Knepley   PetscFunctionBegin;
9839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
9849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
9853be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
9863be36e83SMatthew G. Knepley     PetscSFNode rcp;
9875f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
9883be36e83SMatthew G. Knepley 
9899566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
9905f80ce2aSJacob Faibussowitsch     if (mapFailed) {
9913be36e83SMatthew G. Knepley       cmin = missing;
9923be36e83SMatthew G. Knepley     } else {
9933be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
9943be36e83SMatthew G. Knepley     }
9953be36e83SMatthew G. Knepley   }
9963be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
9973be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9983be36e83SMatthew G. Knepley }
9993be36e83SMatthew G. Knepley 
10003be36e83SMatthew G. Knepley /*
10013be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10023be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10033be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10043be36e83SMatthew G. Knepley */
10059371c9d4SSatish Balay static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) {
10063be36e83SMatthew G. Knepley   MPI_Comm        comm;
10073be36e83SMatthew G. Knepley   const PetscInt *support;
1008cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10093be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10103be36e83SMatthew G. Knepley 
10113be36e83SMatthew G. Knepley   PetscFunctionBegin;
10129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
10139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
10159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
10169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
1017cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight + 1) {
1018cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
101963a3b9bcSJacob 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));
1020cf4dc471SVaclav Hapla     PetscFunctionReturn(0);
1021cf4dc471SVaclav Hapla   }
10229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
10239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
10249566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
10253be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
10263be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
10273be36e83SMatthew G. Knepley     const PetscInt *cone;
10283be36e83SMatthew G. Knepley     PetscSFNode     cpmin = {-1, -1}, rp = {-1, -1};
10293be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
10303be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
10313be36e83SMatthew G. Knepley     PetscHashIJKey  key;
10323be36e83SMatthew G. Knepley 
10333be36e83SMatthew G. Knepley     /* Only add point once */
103463a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
10353be36e83SMatthew G. Knepley     key.i = p;
10363be36e83SMatthew G. Knepley     key.j = face;
10379566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
10383be36e83SMatthew G. Knepley     if (f >= 0) continue;
10399566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
10409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
10419566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
10423be36e83SMatthew G. Knepley     if (debug) {
104363a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
104463a3b9bcSJacob 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));
10453be36e83SMatthew G. Knepley     }
10463be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
10479566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
10483be36e83SMatthew G. Knepley       if (candidates) {
104963a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
10509566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
10519566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
10523be36e83SMatthew G. Knepley         candidates[off + idx].rank    = -1;
10533be36e83SMatthew G. Knepley         candidates[off + idx++].index = coneSize - 1;
10543be36e83SMatthew G. Knepley         candidates[off + idx].rank    = rank;
10553be36e83SMatthew G. Knepley         candidates[off + idx++].index = face;
10563be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
10573be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
10583be36e83SMatthew G. Knepley 
10593be36e83SMatthew G. Knepley           if (cp == p) continue;
10609566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
106163a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
10623be36e83SMatthew G. Knepley           ++idx;
10633be36e83SMatthew G. Knepley         }
10649566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
10653be36e83SMatthew G. Knepley       } else {
10663be36e83SMatthew G. Knepley         /* Add cone size to section */
106763a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
10689566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
10699566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
10709566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
10713be36e83SMatthew G. Knepley       }
10723be36e83SMatthew G. Knepley     }
10733be36e83SMatthew G. Knepley   }
10743be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
10753be36e83SMatthew G. Knepley }
10763be36e83SMatthew G. Knepley 
10772e72742cSMatthew G. Knepley /*@
10782e72742cSMatthew G. Knepley   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation
10792e72742cSMatthew G. Knepley 
1080d083f849SBarry Smith   Collective on dm
10812e72742cSMatthew G. Knepley 
10822e72742cSMatthew G. Knepley   Input Parameters:
10832e72742cSMatthew G. Knepley + dm      - The interpolated DM
10842e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points
10852e72742cSMatthew G. Knepley 
10862e72742cSMatthew G. Knepley   Output Parameter:
10872e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points
10882e72742cSMatthew G. Knepley 
1089f0cfc026SVaclav Hapla   Level: developer
10902e72742cSMatthew G. Knepley 
10912e72742cSMatthew 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
10922e72742cSMatthew G. Knepley 
1093db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexUninterpolate()`
10942e72742cSMatthew G. Knepley @*/
10959371c9d4SSatish Balay PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) {
10963be36e83SMatthew G. Knepley   MPI_Comm           comm;
10973be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
10983be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
10993be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11003be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11012e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11022e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11033be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11043be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11053be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1106f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11072e72742cSMatthew G. Knepley 
11082e72742cSMatthew G. Knepley   PetscFunctionBegin;
1109f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1110064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11119566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
1112f0cfc026SVaclav Hapla   if (!flg) PetscFunctionReturn(0);
11133be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
11149566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
11159566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
111828b400f6SJacob Faibussowitsch   PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
11199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
11209566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
11219566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
11229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
11233be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
11249566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
112508401ef6SPierre Jolivet   PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
11269566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
11273be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
11283be36e83SMatthew G. Knepley     PetscHashIJKey key;
11292e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
11302e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
11319566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
11327bffde78SMichael Lange   }
113366aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
11349566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
11359566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
11369566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
11373be36e83SMatthew G. Knepley   /*
11383be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
11393be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
11403be36e83SMatthew G. Knepley   \begin{itemize}
11413be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
11423be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
11433be36e83SMatthew G. Knepley   \end{itemize}
11443be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
11453be36e83SMatthew 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
11463be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
11473be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
11483be36e83SMatthew G. Knepley   */
11493be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
11503be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
11513be36e83SMatthew G. Knepley        The array holds candidate shared faces, each face is refered to by the leaf point */
11529566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
11539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
11547bffde78SMichael Lange   {
11553be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
11562e72742cSMatthew G. Knepley 
11579566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
11583be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11593be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11602e72742cSMatthew G. Knepley 
116163a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
11629566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
11632e72742cSMatthew G. Knepley     }
11649566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
11659566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
11669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
11679566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
11683be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11693be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11702e72742cSMatthew G. Knepley 
117163a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
11729566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
11732e72742cSMatthew G. Knepley     }
11749566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
11759566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
11767bffde78SMichael Lange   }
11779566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
11789566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
11799566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
11803be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
11812e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
11827bffde78SMichael Lange   {
11837bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
11847bffde78SMichael Lange     PetscInt *remoteOffsets;
11852e72742cSMatthew G. Knepley 
11869566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
11879566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
11889566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
11899566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
11909566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
11919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
11929566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
11939566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
11949566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
11959566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
11969566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
11979566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
11982e72742cSMatthew G. Knepley 
11999566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12009566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12019566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12027bffde78SMichael Lange   }
12033be36e83SMatthew 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 */
12047bffde78SMichael Lange   {
12053be36e83SMatthew G. Knepley     PetscHashIJKLRemote faceTable;
12063be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12073be36e83SMatthew G. Knepley 
12089566063dSJacob Faibussowitsch     PetscCall(PetscHashIJKLRemoteCreate(&faceTable));
12092e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12103be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12112e72742cSMatthew G. Knepley       PetscInt deg;
12123be36e83SMatthew G. Knepley 
12132e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
12142e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
12152e72742cSMatthew G. Knepley 
12169566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
12179566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
12183be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12192e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12203be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
12213be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
12223be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx + 1];
12233be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
12243be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
12253be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
12262e72742cSMatthew G. Knepley           const PetscInt        *join = NULL;
12273be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
12283be36e83SMatthew G. Knepley           PetscHashIter          iter;
12295f80ce2aSJacob Faibussowitsch           PetscBool              missing, mapToLocalPointFailed = PETSC_FALSE;
12302e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
12312e72742cSMatthew G. Knepley 
12329371c9d4SSatish Balay           if (debug)
12339371c9d4SSatish 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,
12349371c9d4SSatish Balay                                               rface.index, r, idx, d, Np));
123563a3b9bcSJacob 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);
12363be36e83SMatthew G. Knepley           fcp0.rank  = rank;
12373be36e83SMatthew G. Knepley           fcp0.index = r;
12383be36e83SMatthew G. Knepley           d += Np;
12393be36e83SMatthew G. Knepley           /* Put remote face in hash table */
12403be36e83SMatthew G. Knepley           key.i = fcp0;
12413be36e83SMatthew G. Knepley           key.j = fcone[0];
12423be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
12433be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
12449566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
12459566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing));
12463be36e83SMatthew G. Knepley           if (missing) {
124763a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
12489566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface));
12493be36e83SMatthew G. Knepley           } else {
12503be36e83SMatthew G. Knepley             PetscSFNode oface;
12513be36e83SMatthew G. Knepley 
12529566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface));
12533be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
125463a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
12559566063dSJacob Faibussowitsch               PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface));
12563be36e83SMatthew G. Knepley             }
12573be36e83SMatthew G. Knepley           }
12583be36e83SMatthew G. Knepley           /* Check for local face */
12592e72742cSMatthew G. Knepley           points[0] = r;
12603be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
12619566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
12625f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
126363a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
12647bffde78SMichael Lange           }
12655f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
12669566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
12677bffde78SMichael Lange           if (joinSize == 1) {
12683be36e83SMatthew G. Knepley             PetscSFNode lface;
12693be36e83SMatthew G. Knepley             PetscSFNode oface;
12703be36e83SMatthew G. Knepley 
12713be36e83SMatthew G. Knepley             /* Always replace with local face */
12723be36e83SMatthew G. Knepley             lface.rank  = rank;
12733be36e83SMatthew G. Knepley             lface.index = join[0];
12749566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface));
12759371c9d4SSatish Balay             if (debug)
12769371c9d4SSatish 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));
12779566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, lface));
12787bffde78SMichael Lange           }
12799566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
12803be36e83SMatthew G. Knepley         }
12813be36e83SMatthew G. Knepley       }
12823be36e83SMatthew G. Knepley       /* Put back faces for this root */
12833be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
12843be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
12853be36e83SMatthew G. Knepley 
12869566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
12879566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
12883be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12893be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12903be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
12913be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
12923be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
12933be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
12943be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
12953be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
12963be36e83SMatthew G. Knepley           PetscHashIter          iter;
12973be36e83SMatthew G. Knepley           PetscBool              missing;
12983be36e83SMatthew G. Knepley 
129963a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
130063a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13013be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13023be36e83SMatthew G. Knepley           fcp0.index = r;
13033be36e83SMatthew G. Knepley           d += Np;
13043be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13053be36e83SMatthew G. Knepley           key.i = fcp0;
13063be36e83SMatthew G. Knepley           key.j = fcone[0];
13073be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13083be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13099566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13109371c9d4SSatish Balay           if (debug)
13119371c9d4SSatish 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,
13129371c9d4SSatish 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));
13139566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing));
131463a3b9bcSJacob Faibussowitsch           PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1315f7d195e4SLawrence Mitchell           PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
13167bffde78SMichael Lange         }
13177bffde78SMichael Lange       }
13187bffde78SMichael Lange     }
13199566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
13209566063dSJacob Faibussowitsch     PetscCall(PetscHashIJKLRemoteDestroy(&faceTable));
13217bffde78SMichael Lange   }
13223be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
13237bffde78SMichael Lange   {
13247bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
13257bffde78SMichael Lange     PetscSFNode *remotePointsNew;
13262e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
13273be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
13282e72742cSMatthew G. Knepley 
13293be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
13309566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
13319566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
13329566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
13339566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
13349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
13359566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
13363be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
13379566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13389566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13399566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
13409566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
13419566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
13429566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
13439566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
13443be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
13453be36e83SMatthew 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 */
13469566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
13473be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
13483be36e83SMatthew G. Knepley       PetscInt dof, off, d;
13492e72742cSMatthew G. Knepley 
135063a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
13519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
13529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
13532e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
13543be36e83SMatthew G. Knepley         if (claims[off + d].rank >= 0) {
13553be36e83SMatthew G. Knepley           const PetscInt  faceInd = off + d;
13563be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off + d].index;
13572e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
13582e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
13592e72742cSMatthew G. Knepley 
136063a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
13613be36e83SMatthew G. Knepley           points[0] = r;
136263a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
13633be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
13649566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
136563a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c + 1]));
13662e72742cSMatthew G. Knepley           }
13679566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
13682e72742cSMatthew G. Knepley           if (joinSize == 1) {
13693be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
137063a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
13713be36e83SMatthew G. Knepley             } else {
137263a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
13739566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
13742e72742cSMatthew G. Knepley             }
13753be36e83SMatthew G. Knepley           } else {
13769566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
13773be36e83SMatthew G. Knepley           }
13789566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
13793be36e83SMatthew G. Knepley         } else {
138063a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
13813be36e83SMatthew G. Knepley           d += claims[off + d].index + 1;
13827bffde78SMichael Lange         }
13837bffde78SMichael Lange       }
13843be36e83SMatthew G. Knepley     }
13859566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
13863be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
13879566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
13889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
13899566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
13909566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
13913be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
13923be36e83SMatthew G. Knepley       localPointsNew[l]        = localPoints[l];
13933be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
13943be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
13957bffde78SMichael Lange     }
13963be36e83SMatthew G. Knepley     p = Nl;
13979566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
13983be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
13999566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(NlNew, &localPointsNew[Nl]));
14003be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14013be36e83SMatthew G. Knepley       PetscInt off;
14029566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
14031dca8a05SBarry 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);
14043be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14057bffde78SMichael Lange     }
14069566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
14079566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14089566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
14099566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
14109566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1411*d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
14129566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
14139566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
14147bffde78SMichael Lange   }
14159566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
14169566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
14179566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
14189566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
14199566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
14209566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
14219566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
14229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
14237bffde78SMichael Lange   PetscFunctionReturn(0);
14247bffde78SMichael Lange }
14257bffde78SMichael Lange 
1426248eb259SVaclav Hapla /*@
142780330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
142880330477SMatthew G. Knepley 
1429d083f849SBarry Smith   Collective on dm
143080330477SMatthew G. Knepley 
1431e56d480eSMatthew G. Knepley   Input Parameters:
1432e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices
143310a67516SMatthew G. Knepley - dmInt - The interpolated DM
143480330477SMatthew G. Knepley 
143580330477SMatthew G. Knepley   Output Parameter:
14364e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object
143780330477SMatthew G. Knepley 
143880330477SMatthew G. Knepley   Level: intermediate
143980330477SMatthew G. Knepley 
144095452b02SPatrick Sanan   Notes:
14417fb59074SVaclav Hapla     Labels and coordinates are copied.
144243eeeb2dSStefano Zampini 
14439ade3219SVaclav Hapla   Developer Notes:
14449ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL.
14459ade3219SVaclav Hapla 
1446db781477SPatrick Sanan .seealso: `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
144780330477SMatthew G. Knepley @*/
14489371c9d4SSatish Balay PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) {
1449a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
14509a5b13a2SMatthew G Knepley   DM                     idm, odm = dm;
14517bffde78SMichael Lange   PetscSF                sfPoint;
14522e1b13c2SMatthew G. Knepley   PetscInt               depth, dim, d;
145310a67516SMatthew G. Knepley   const char            *name;
1454b325530aSVaclav Hapla   PetscBool              flg = PETSC_TRUE;
14559f074e33SMatthew G Knepley 
14569f074e33SMatthew G Knepley   PetscFunctionBegin;
145710a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
145810a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
14599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
14609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
14619566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
14629566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
146308401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1464827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
14659566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
146676b791aaSMatthew G. Knepley     idm = dm;
1467b21b8912SMatthew G. Knepley   } else {
14689a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
14699a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
14709566063dSJacob Faibussowitsch       PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
14719566063dSJacob Faibussowitsch       PetscCall(DMSetType(idm, DMPLEX));
14729566063dSJacob Faibussowitsch       PetscCall(DMSetDimension(idm, dim));
14737bffde78SMichael Lange       if (depth > 0) {
14749566063dSJacob Faibussowitsch         PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
14759566063dSJacob Faibussowitsch         PetscCall(DMGetPointSF(odm, &sfPoint));
1476*d7d32a9aSMatthew G. Knepley         if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
147794488200SVaclav Hapla         {
14783be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
147994488200SVaclav Hapla           PetscInt nroots;
14809566063dSJacob Faibussowitsch           PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
14819566063dSJacob Faibussowitsch           if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
148294488200SVaclav Hapla         }
14837bffde78SMichael Lange       }
14849566063dSJacob Faibussowitsch       if (odm != dm) PetscCall(DMDestroy(&odm));
14859a5b13a2SMatthew G Knepley       odm = idm;
14869f074e33SMatthew G Knepley     }
14879566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
14889566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)idm, name));
14899566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
14909566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
14919566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
14929566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
149384699f70SSatish Balay   }
1494827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1495827c4036SVaclav Hapla   {
1496d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)idm->data;
1497827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1498827c4036SVaclav Hapla   }
14995de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
15009a5b13a2SMatthew G Knepley   *dmInt = idm;
15019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
15029f074e33SMatthew G Knepley   PetscFunctionReturn(0);
15039f074e33SMatthew G Knepley }
150407b0a1fcSMatthew G Knepley 
150580330477SMatthew G. Knepley /*@
150680330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
150780330477SMatthew G. Knepley 
1508d083f849SBarry Smith   Collective on dmA
150980330477SMatthew G. Knepley 
151080330477SMatthew G. Knepley   Input Parameter:
151180330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates
151280330477SMatthew G. Knepley 
151380330477SMatthew G. Knepley   Output Parameter:
151480330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates
151580330477SMatthew G. Knepley 
151680330477SMatthew G. Knepley   Level: intermediate
151780330477SMatthew G. Knepley 
151880330477SMatthew G. Knepley   Note: This is typically used when adding pieces other than vertices to a mesh
151980330477SMatthew G. Knepley 
1520db781477SPatrick Sanan .seealso: `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
152180330477SMatthew G. Knepley @*/
15229371c9d4SSatish Balay PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) {
152307b0a1fcSMatthew G Knepley   Vec          coordinatesA, coordinatesB;
152443eeeb2dSStefano Zampini   VecType      vtype;
152507b0a1fcSMatthew G Knepley   PetscSection coordSectionA, coordSectionB;
152607b0a1fcSMatthew G Knepley   PetscScalar *coordsA, *coordsB;
15270bedd6beSMatthew G. Knepley   PetscInt     spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
152890a8aa44SJed Brown   PetscInt     cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
152943eeeb2dSStefano Zampini   PetscBool    lc = PETSC_FALSE;
153007b0a1fcSMatthew G Knepley 
153107b0a1fcSMatthew G Knepley   PetscFunctionBegin;
153243eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
153343eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
153476b791aaSMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
15359566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
15369566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
15379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
15389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
153963a3b9bcSJacob 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);
154061a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
154161a622f3SMatthew G. Knepley   {
154261a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
154361a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
154461a622f3SMatthew G. Knepley     PetscObject        objA, objB;
154561a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
154661a622f3SMatthew G. Knepley     const PetscScalar *constants;
154761a622f3SMatthew G. Knepley     PetscInt           cdim, Nc;
154861a622f3SMatthew G. Knepley 
15499566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
15509566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
15519566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
15529566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
15539566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
15549566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
155561a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
15569566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
15579566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
15589566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
15599566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
15609566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
15619566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
15629566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
15639566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
156461a622f3SMatthew G. Knepley     }
156561a622f3SMatthew G. Knepley   }
15669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
15679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
15689566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
15699566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
1570972bc18aSToby Isaac   if (coordSectionA == coordSectionB) PetscFunctionReturn(0);
15719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
15720bedd6beSMatthew G. Knepley   if (!Nf) PetscFunctionReturn(0);
157363a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1574df26b574SMatthew G. Knepley   if (!coordSectionB) {
1575df26b574SMatthew G. Knepley     PetscInt dim;
1576df26b574SMatthew G. Knepley 
15779566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
15789566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
15799566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
15809566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1581df26b574SMatthew G. Knepley   }
15829566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
15839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
15849566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
15859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
158643eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
158763a3b9bcSJacob 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);
158843eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
158943eeeb2dSStefano Zampini     cE = vEndB;
159043eeeb2dSStefano Zampini     lc = PETSC_TRUE;
159143eeeb2dSStefano Zampini   } else {
159243eeeb2dSStefano Zampini     cS = vStartB;
159343eeeb2dSStefano Zampini     cE = vEndB;
159443eeeb2dSStefano Zampini   }
15959566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
159607b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
15979566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
15989566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
159907b0a1fcSMatthew G Knepley   }
160043eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
160143eeeb2dSStefano Zampini     PetscInt c;
160243eeeb2dSStefano Zampini 
160343eeeb2dSStefano Zampini     for (c = cS - cStartB; c < cEndB - cStartB; c++) {
160443eeeb2dSStefano Zampini       PetscInt dof;
160543eeeb2dSStefano Zampini 
16069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
16079566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSectionB, c + cStartB, dof));
16089566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof));
160943eeeb2dSStefano Zampini     }
161043eeeb2dSStefano Zampini   }
16119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
16129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
16139566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
16149566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
16159566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
16169566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
16179566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
16189566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
16199566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
16209566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
16219566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
16229566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
162307b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB - vStartB; ++v) {
162443eeeb2dSStefano Zampini     PetscInt offA, offB;
162543eeeb2dSStefano Zampini 
16269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
16279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1628ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
162943eeeb2dSStefano Zampini   }
163043eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
163143eeeb2dSStefano Zampini     PetscInt c;
163243eeeb2dSStefano Zampini 
163343eeeb2dSStefano Zampini     for (c = cS - cStartB; c < cEndB - cStartB; c++) {
163443eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
163543eeeb2dSStefano Zampini 
16369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA));
16379566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB));
16389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
16399566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(coordsB + offB, coordsA + offA, dof));
164007b0a1fcSMatthew G Knepley     }
164107b0a1fcSMatthew G Knepley   }
16429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
16439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
16449566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
16459566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
164607b0a1fcSMatthew G Knepley   PetscFunctionReturn(0);
164707b0a1fcSMatthew G Knepley }
16485c386225SMatthew G. Knepley 
16494e3744c5SMatthew G. Knepley /*@
16504e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
16514e3744c5SMatthew G. Knepley 
1652d083f849SBarry Smith   Collective on dm
16534e3744c5SMatthew G. Knepley 
16544e3744c5SMatthew G. Knepley   Input Parameter:
16554e3744c5SMatthew G. Knepley . dm - The complete DMPlex object
16564e3744c5SMatthew G. Knepley 
16574e3744c5SMatthew G. Knepley   Output Parameter:
16584e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices
16594e3744c5SMatthew G. Knepley 
16604e3744c5SMatthew G. Knepley   Level: intermediate
16614e3744c5SMatthew G. Knepley 
166295452b02SPatrick Sanan   Notes:
166395452b02SPatrick Sanan     It does not copy over the coordinates.
166443eeeb2dSStefano Zampini 
16659ade3219SVaclav Hapla   Developer Notes:
16669ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
16679ade3219SVaclav Hapla 
1668db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
16694e3744c5SMatthew G. Knepley @*/
16709371c9d4SSatish Balay PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) {
1671827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
16724e3744c5SMatthew G. Knepley   DM                     udm;
1673412e9a14SMatthew G. Knepley   PetscInt               dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
16744e3744c5SMatthew G. Knepley 
16754e3744c5SMatthew G. Knepley   PetscFunctionBegin;
167643eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
167743eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
16789566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
16799566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
168008401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1681827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1682827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
16839566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1684595d4abbSMatthew G. Knepley     *dmUnint = dm;
1685595d4abbSMatthew G. Knepley     PetscFunctionReturn(0);
16864e3744c5SMatthew G. Knepley   }
16879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
16889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
16899566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
16909566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
16919566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
16929566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
16934e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1694595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
16954e3744c5SMatthew G. Knepley 
16969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
16974e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
16984e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
16994e3744c5SMatthew G. Knepley 
17004e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
17014e3744c5SMatthew G. Knepley     }
17029566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17039566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1704595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
17054e3744c5SMatthew G. Knepley   }
17069566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
17079566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
17084e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1709595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17104e3744c5SMatthew G. Knepley 
17119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17124e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17134e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17144e3744c5SMatthew G. Knepley 
17154e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
17164e3744c5SMatthew G. Knepley     }
17179566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17189566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
17194e3744c5SMatthew G. Knepley   }
17209566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
17219566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
17229566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
17235c7de58aSMatthew G. Knepley   /* Reduce SF */
17245c7de58aSMatthew G. Knepley   {
17255c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
17265c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
17275c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
17285c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
17295c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
173022fd0ad9SVaclav Hapla     PetscInt           numRoots, numLeaves, l;
17315c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
17325c7de58aSMatthew G. Knepley 
17335c7de58aSMatthew G. Knepley     /* Get original SF information */
17349566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
1735*d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
17369566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
17379566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
173822fd0ad9SVaclav Hapla     if (numRoots >= 0) {
17395c7de58aSMatthew G. Knepley       /* Allocate space for cells and vertices */
174022fd0ad9SVaclav Hapla       for (l = 0; l < numLeaves; ++l) {
174122fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
174222fd0ad9SVaclav Hapla 
174322fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
174422fd0ad9SVaclav Hapla       }
17455c7de58aSMatthew G. Knepley       /* Fill in leaves */
17469566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
17479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
17485c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
174922fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
175022fd0ad9SVaclav Hapla 
175122fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
175222fd0ad9SVaclav Hapla           localPointsUn[n]        = p;
17535c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
17545c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
17555c7de58aSMatthew G. Knepley           ++n;
17565c7de58aSMatthew G. Knepley         }
17575c7de58aSMatthew G. Knepley       }
175863a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
175922fd0ad9SVaclav Hapla       PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
17605c7de58aSMatthew G. Knepley     }
17615c7de58aSMatthew G. Knepley   }
1762827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1763827c4036SVaclav Hapla   {
1764d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)udm->data;
1765827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1766827c4036SVaclav Hapla   }
17675de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1768*d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
17694e3744c5SMatthew G. Knepley   *dmUnint = udm;
17704e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
17714e3744c5SMatthew G. Knepley }
1772a7748839SVaclav Hapla 
17739371c9d4SSatish Balay static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) {
1774a7748839SVaclav Hapla   PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1775a7748839SVaclav Hapla   MPI_Comm comm;
1776a7748839SVaclav Hapla 
1777a7748839SVaclav Hapla   PetscFunctionBegin;
17789566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
17799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
17809566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1781a7748839SVaclav Hapla 
1782a7748839SVaclav Hapla   if (depth == dim) {
1783a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1784a7748839SVaclav Hapla     if (!dim) goto finish;
1785a7748839SVaclav Hapla 
1786a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
17879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1788a7748839SVaclav Hapla     for (p = pStart; p < pEnd; p++) {
17899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1790a7748839SVaclav Hapla       if (coneSize) {
1791a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1792a7748839SVaclav Hapla         goto finish;
1793a7748839SVaclav Hapla       }
1794a7748839SVaclav Hapla     }
1795a7748839SVaclav Hapla 
1796a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1797a7748839SVaclav Hapla     for (h = 0; h < dim; h++) {
17989566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1799a7748839SVaclav Hapla       for (p = pStart; p < pEnd; p++) {
18009566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1801a7748839SVaclav Hapla         if (!coneSize) {
1802a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1803a7748839SVaclav Hapla           goto finish;
1804a7748839SVaclav Hapla         }
1805a7748839SVaclav Hapla       }
1806a7748839SVaclav Hapla     }
1807a7748839SVaclav Hapla   } else if (depth == 1) {
1808a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1809a7748839SVaclav Hapla   } else {
1810a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1811a7748839SVaclav Hapla   }
1812a7748839SVaclav Hapla finish:
1813a7748839SVaclav Hapla   PetscFunctionReturn(0);
1814a7748839SVaclav Hapla }
1815a7748839SVaclav Hapla 
1816a7748839SVaclav Hapla /*@
18179ade3219SVaclav Hapla   DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated.
1818a7748839SVaclav Hapla 
1819a7748839SVaclav Hapla   Not Collective
1820a7748839SVaclav Hapla 
1821a7748839SVaclav Hapla   Input Parameter:
1822a7748839SVaclav Hapla . dm      - The DM object
1823a7748839SVaclav Hapla 
1824a7748839SVaclav Hapla   Output Parameter:
1825a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1826a7748839SVaclav Hapla 
1827a7748839SVaclav Hapla   Level: intermediate
1828a7748839SVaclav Hapla 
1829a7748839SVaclav Hapla   Notes:
18309ade3219SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this is NOT collective
18319ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
1832a7748839SVaclav Hapla   However, DMPlexInterpolate() guarantees the result is the same on all.
18339ade3219SVaclav Hapla 
1834a7748839SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED.
1835a7748839SVaclav Hapla 
18369ade3219SVaclav Hapla   Developer Notes:
18379ade3219SVaclav Hapla   Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID.
18389ade3219SVaclav Hapla 
18399ade3219SVaclav Hapla   If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called.
18409ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
18419ade3219SVaclav Hapla   DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL.
18429ade3219SVaclav Hapla 
18439ade3219SVaclav Hapla   If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated.
18449ade3219SVaclav Hapla 
18459ade3219SVaclav Hapla   DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL,
18469ade3219SVaclav Hapla   and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
18479ade3219SVaclav Hapla 
1848db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1849a7748839SVaclav Hapla @*/
18509371c9d4SSatish Balay PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) {
1851a7748839SVaclav Hapla   DM_Plex *plex = (DM_Plex *)dm->data;
1852a7748839SVaclav Hapla 
1853a7748839SVaclav Hapla   PetscFunctionBegin;
1854a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1855a7748839SVaclav Hapla   PetscValidPointer(interpolated, 2);
1856a7748839SVaclav Hapla   if (plex->interpolated < 0) {
18579566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
185876bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
1859a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1860a7748839SVaclav Hapla 
18619566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
186208401ef6SPierre Jolivet     PetscCheck(flg == plex->interpolated, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1863a7748839SVaclav Hapla   }
1864a7748839SVaclav Hapla   *interpolated = plex->interpolated;
1865a7748839SVaclav Hapla   PetscFunctionReturn(0);
1866a7748839SVaclav Hapla }
1867a7748839SVaclav Hapla 
1868a7748839SVaclav Hapla /*@
18699ade3219SVaclav Hapla   DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner).
1870a7748839SVaclav Hapla 
18712666ff3cSVaclav Hapla   Collective
1872a7748839SVaclav Hapla 
1873a7748839SVaclav Hapla   Input Parameter:
1874a7748839SVaclav Hapla . dm      - The DM object
1875a7748839SVaclav Hapla 
1876a7748839SVaclav Hapla   Output Parameter:
1877a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1878a7748839SVaclav Hapla 
1879a7748839SVaclav Hapla   Level: intermediate
1880a7748839SVaclav Hapla 
1881a7748839SVaclav Hapla   Notes:
18829ade3219SVaclav Hapla   Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks.
18839ade3219SVaclav Hapla 
18849ade3219SVaclav Hapla   This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks.
18859ade3219SVaclav Hapla 
18869ade3219SVaclav Hapla   Developer Notes:
18879ade3219SVaclav Hapla   Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID.
18889ade3219SVaclav Hapla 
18899ade3219SVaclav Hapla   If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated.
18909ade3219SVaclav Hapla   MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
18919ade3219SVaclav Hapla   if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED,
18929ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
18939ade3219SVaclav Hapla 
18949ade3219SVaclav Hapla   If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective.
1895a7748839SVaclav Hapla 
1896db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
1897a7748839SVaclav Hapla @*/
18989371c9d4SSatish Balay PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) {
1899a7748839SVaclav Hapla   DM_Plex  *plex  = (DM_Plex *)dm->data;
1900a7748839SVaclav Hapla   PetscBool debug = PETSC_FALSE;
1901a7748839SVaclav Hapla 
1902a7748839SVaclav Hapla   PetscFunctionBegin;
1903a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1904a7748839SVaclav Hapla   PetscValidPointer(interpolated, 2);
19059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
1906a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1907a7748839SVaclav Hapla     DMPlexInterpolatedFlag min, max;
1908a7748839SVaclav Hapla     MPI_Comm               comm;
1909a7748839SVaclav Hapla 
19109566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19119566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
19129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
19139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
1914a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1915a7748839SVaclav Hapla     if (debug) {
1916a7748839SVaclav Hapla       PetscMPIInt rank;
1917a7748839SVaclav Hapla 
19189566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
19199566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
19209566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
1921a7748839SVaclav Hapla     }
1922a7748839SVaclav Hapla   }
1923a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
1924a7748839SVaclav Hapla   PetscFunctionReturn(0);
1925a7748839SVaclav Hapla }
1926