xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 1afe9b7d1bab757772665b1201a591a3920ee71c)
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 
7a03d55ffSStefano Zampini /* HMapIJKL */
8e8f14785SLisandro Dalcin 
9a03d55ffSStefano Zampini #include <petsc/private/hashmapijkl.h>
10e8f14785SLisandro Dalcin 
113be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1};
123be36e83SMatthew G. Knepley 
13a03d55ffSStefano Zampini typedef struct _PetscHMapIJKLRemoteKey {
149371c9d4SSatish Balay   PetscSFNode i, j, k, l;
15a03d55ffSStefano Zampini } PetscHMapIJKLRemoteKey;
163be36e83SMatthew G. Knepley 
17a03d55ffSStefano Zampini #define PetscHMapIJKLRemoteKeyHash(key) \
189371c9d4SSatish 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)))
193be36e83SMatthew G. Knepley 
20a03d55ffSStefano Zampini #define PetscHMapIJKLRemoteKeyEqual(k1, k2) \
213be36e83SMatthew 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)
223be36e83SMatthew G. Knepley 
23a03d55ffSStefano Zampini PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HMapIJKLRemote, PetscHMapIJKLRemoteKey, PetscSFNode, PetscHMapIJKLRemoteKeyHash, PetscHMapIJKLRemoteKeyEqual, _PetscInvalidSFNode))
243be36e83SMatthew G. Knepley 
25d71ae5a4SJacob Faibussowitsch   static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[])
26d71ae5a4SJacob Faibussowitsch {
273be36e83SMatthew G. Knepley   PetscInt i;
283be36e83SMatthew G. Knepley 
293be36e83SMatthew G. Knepley   PetscFunctionBegin;
303be36e83SMatthew G. Knepley   for (i = 1; i < n; ++i) {
313be36e83SMatthew G. Knepley     PetscSFNode x = A[i];
323be36e83SMatthew G. Knepley     PetscInt    j;
333be36e83SMatthew G. Knepley 
343be36e83SMatthew G. Knepley     for (j = i - 1; j >= 0; --j) {
353be36e83SMatthew G. Knepley       if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break;
363be36e83SMatthew G. Knepley       A[j + 1] = A[j];
373be36e83SMatthew G. Knepley     }
383be36e83SMatthew G. Knepley     A[j + 1] = x;
393be36e83SMatthew G. Knepley   }
403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
413be36e83SMatthew G. Knepley }
429f074e33SMatthew G Knepley 
439f074e33SMatthew G Knepley /*
44439ece16SMatthew G. Knepley   DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone
45439ece16SMatthew G. Knepley */
46d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
47d71ae5a4SJacob Faibussowitsch {
48442f3b32SStefano Zampini   DMPolytopeType *typesTmp = NULL;
49442f3b32SStefano Zampini   PetscInt       *sizesTmp = NULL, *facesTmp = NULL;
50442f3b32SStefano Zampini   PetscInt       *tmp;
51442f3b32SStefano Zampini   PetscInt        maxConeSize, maxSupportSize, maxSize;
52442f3b32SStefano Zampini   PetscInt        getSize = 0;
53439ece16SMatthew G. Knepley 
54439ece16SMatthew G. Knepley   PetscFunctionBegin;
55439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
564f572ea9SToby Isaac   if (cone) PetscAssertPointer(cone, 3);
579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
58442f3b32SStefano Zampini   maxSize = PetscMax(maxConeSize, maxSupportSize);
59442f3b32SStefano Zampini   if (faceTypes) getSize += maxSize;
60442f3b32SStefano Zampini   if (faceSizes) getSize += maxSize;
61442f3b32SStefano Zampini   if (faces) getSize += PetscSqr(maxSize);
62442f3b32SStefano Zampini   PetscCall(DMGetWorkArray(dm, getSize, MPIU_INT, &tmp));
63442f3b32SStefano Zampini   if (faceTypes) {
64442f3b32SStefano Zampini     typesTmp = (DMPolytopeType *)tmp;
65442f3b32SStefano Zampini     tmp += maxSize;
66442f3b32SStefano Zampini   }
67442f3b32SStefano Zampini   if (faceSizes) {
68442f3b32SStefano Zampini     sizesTmp = tmp;
69442f3b32SStefano Zampini     tmp += maxSize;
70442f3b32SStefano Zampini   }
71442f3b32SStefano Zampini   if (faces) facesTmp = tmp;
72ba2698f1SMatthew G. Knepley   switch (ct) {
73ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_POINT:
74ba2698f1SMatthew G. Knepley     if (numFaces) *numFaces = 0;
756f5c9017SMatthew G. Knepley     if (faceTypes) *faceTypes = typesTmp;
766f5c9017SMatthew G. Knepley     if (faceSizes) *faceSizes = sizesTmp;
776f5c9017SMatthew G. Knepley     if (faces) *faces = facesTmp;
78ba2698f1SMatthew G. Knepley     break;
79ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
80412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 2;
81412e9a14SMatthew G. Knepley     if (faceTypes) {
829371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
839371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
84412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
85412e9a14SMatthew G. Knepley     }
86412e9a14SMatthew G. Knepley     if (faceSizes) {
879371c9d4SSatish Balay       sizesTmp[0] = 1;
889371c9d4SSatish Balay       sizesTmp[1] = 1;
89412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
90412e9a14SMatthew G. Knepley     }
91c49d9212SMatthew G. Knepley     if (faces) {
929371c9d4SSatish Balay       facesTmp[0] = cone[0];
939371c9d4SSatish Balay       facesTmp[1] = cone[1];
94c49d9212SMatthew G. Knepley       *faces      = facesTmp;
95c49d9212SMatthew G. Knepley     }
96412e9a14SMatthew G. Knepley     break;
97412e9a14SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
98c49d9212SMatthew G. Knepley     if (numFaces) *numFaces = 2;
99412e9a14SMatthew G. Knepley     if (faceTypes) {
1009371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
1019371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
102412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
103412e9a14SMatthew G. Knepley     }
104412e9a14SMatthew G. Knepley     if (faceSizes) {
1059371c9d4SSatish Balay       sizesTmp[0] = 1;
1069371c9d4SSatish Balay       sizesTmp[1] = 1;
107412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
108412e9a14SMatthew G. Knepley     }
109412e9a14SMatthew G. Knepley     if (faces) {
1109371c9d4SSatish Balay       facesTmp[0] = cone[0];
1119371c9d4SSatish Balay       facesTmp[1] = cone[1];
112412e9a14SMatthew G. Knepley       *faces      = facesTmp;
113412e9a14SMatthew G. Knepley     }
114c49d9212SMatthew G. Knepley     break;
115ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
116412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 3;
117412e9a14SMatthew G. Knepley     if (faceTypes) {
1189371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1199371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1209371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
121412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
122412e9a14SMatthew G. Knepley     }
123412e9a14SMatthew G. Knepley     if (faceSizes) {
1249371c9d4SSatish Balay       sizesTmp[0] = 2;
1259371c9d4SSatish Balay       sizesTmp[1] = 2;
1269371c9d4SSatish Balay       sizesTmp[2] = 2;
127412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
128412e9a14SMatthew G. Knepley     }
1299a5b13a2SMatthew G Knepley     if (faces) {
1309371c9d4SSatish Balay       facesTmp[0] = cone[0];
1319371c9d4SSatish Balay       facesTmp[1] = cone[1];
1329371c9d4SSatish Balay       facesTmp[2] = cone[1];
1339371c9d4SSatish Balay       facesTmp[3] = cone[2];
1349371c9d4SSatish Balay       facesTmp[4] = cone[2];
1359371c9d4SSatish Balay       facesTmp[5] = cone[0];
1369a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1379a5b13a2SMatthew G Knepley     }
1389f074e33SMatthew G Knepley     break;
139ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
1409a5b13a2SMatthew G Knepley     /* Vertices follow right hand rule */
141412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
142412e9a14SMatthew G. Knepley     if (faceTypes) {
1439371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1449371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1459371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
1469371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEGMENT;
147412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
148412e9a14SMatthew G. Knepley     }
149412e9a14SMatthew G. Knepley     if (faceSizes) {
1509371c9d4SSatish Balay       sizesTmp[0] = 2;
1519371c9d4SSatish Balay       sizesTmp[1] = 2;
1529371c9d4SSatish Balay       sizesTmp[2] = 2;
1539371c9d4SSatish Balay       sizesTmp[3] = 2;
154412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
155412e9a14SMatthew G. Knepley     }
1569a5b13a2SMatthew G Knepley     if (faces) {
1579371c9d4SSatish Balay       facesTmp[0] = cone[0];
1589371c9d4SSatish Balay       facesTmp[1] = cone[1];
1599371c9d4SSatish Balay       facesTmp[2] = cone[1];
1609371c9d4SSatish Balay       facesTmp[3] = cone[2];
1619371c9d4SSatish Balay       facesTmp[4] = cone[2];
1629371c9d4SSatish Balay       facesTmp[5] = cone[3];
1639371c9d4SSatish Balay       facesTmp[6] = cone[3];
1649371c9d4SSatish Balay       facesTmp[7] = cone[0];
1659a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1669a5b13a2SMatthew G Knepley     }
167412e9a14SMatthew G. Knepley     break;
168412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
1699a5b13a2SMatthew G Knepley     if (numFaces) *numFaces = 4;
170412e9a14SMatthew G. Knepley     if (faceTypes) {
1719371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1729371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1739371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1749371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
175412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
176412e9a14SMatthew G. Knepley     }
177412e9a14SMatthew G. Knepley     if (faceSizes) {
1789371c9d4SSatish Balay       sizesTmp[0] = 2;
1799371c9d4SSatish Balay       sizesTmp[1] = 2;
1809371c9d4SSatish Balay       sizesTmp[2] = 2;
1819371c9d4SSatish Balay       sizesTmp[3] = 2;
182412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
183412e9a14SMatthew G. Knepley     }
184412e9a14SMatthew G. Knepley     if (faces) {
1859371c9d4SSatish Balay       facesTmp[0] = cone[0];
1869371c9d4SSatish Balay       facesTmp[1] = cone[1];
1879371c9d4SSatish Balay       facesTmp[2] = cone[2];
1889371c9d4SSatish Balay       facesTmp[3] = cone[3];
1899371c9d4SSatish Balay       facesTmp[4] = cone[0];
1909371c9d4SSatish Balay       facesTmp[5] = cone[2];
1919371c9d4SSatish Balay       facesTmp[6] = cone[1];
1929371c9d4SSatish Balay       facesTmp[7] = cone[3];
193412e9a14SMatthew G. Knepley       *faces      = facesTmp;
194412e9a14SMatthew G. Knepley     }
1959f074e33SMatthew G Knepley     break;
196ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
1972e1b13c2SMatthew G. Knepley     /* Vertices of first face follow right hand rule and normal points away from last vertex */
198412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
199412e9a14SMatthew G. Knepley     if (faceTypes) {
2009371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2019371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2029371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
2039371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
204412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
205412e9a14SMatthew G. Knepley     }
206412e9a14SMatthew G. Knepley     if (faceSizes) {
2079371c9d4SSatish Balay       sizesTmp[0] = 3;
2089371c9d4SSatish Balay       sizesTmp[1] = 3;
2099371c9d4SSatish Balay       sizesTmp[2] = 3;
2109371c9d4SSatish Balay       sizesTmp[3] = 3;
211412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
212412e9a14SMatthew G. Knepley     }
2139a5b13a2SMatthew G Knepley     if (faces) {
2149371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2159371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2169371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2179371c9d4SSatish Balay       facesTmp[3]  = cone[0];
2189371c9d4SSatish Balay       facesTmp[4]  = cone[3];
2199371c9d4SSatish Balay       facesTmp[5]  = cone[1];
2209371c9d4SSatish Balay       facesTmp[6]  = cone[0];
2219371c9d4SSatish Balay       facesTmp[7]  = cone[2];
2229371c9d4SSatish Balay       facesTmp[8]  = cone[3];
2239371c9d4SSatish Balay       facesTmp[9]  = cone[2];
2249371c9d4SSatish Balay       facesTmp[10] = cone[1];
2259371c9d4SSatish Balay       facesTmp[11] = cone[3];
2269a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2279a5b13a2SMatthew G Knepley     }
2289a5b13a2SMatthew G Knepley     break;
229ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
230e368ef20SMatthew G. Knepley     /*  7--------6
231e368ef20SMatthew G. Knepley          /|       /|
232e368ef20SMatthew G. Knepley         / |      / |
233e368ef20SMatthew G. Knepley        4--------5  |
234e368ef20SMatthew G. Knepley        |  |     |  |
235e368ef20SMatthew G. Knepley        |  |     |  |
236e368ef20SMatthew G. Knepley        |  1--------2
237e368ef20SMatthew G. Knepley        | /      | /
238e368ef20SMatthew G. Knepley        |/       |/
239e368ef20SMatthew G. Knepley        0--------3
240e368ef20SMatthew G. Knepley        */
241412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
242412e9a14SMatthew G. Knepley     if (faceTypes) {
2439371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
2449371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
2459371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2469371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2479371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
2489371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
249412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
250412e9a14SMatthew G. Knepley     }
251412e9a14SMatthew G. Knepley     if (faceSizes) {
2529371c9d4SSatish Balay       sizesTmp[0] = 4;
2539371c9d4SSatish Balay       sizesTmp[1] = 4;
2549371c9d4SSatish Balay       sizesTmp[2] = 4;
2559371c9d4SSatish Balay       sizesTmp[3] = 4;
2569371c9d4SSatish Balay       sizesTmp[4] = 4;
2579371c9d4SSatish Balay       sizesTmp[5] = 4;
258412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
259412e9a14SMatthew G. Knepley     }
2609a5b13a2SMatthew G Knepley     if (faces) {
2619371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2629371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2639371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2649371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
2659371c9d4SSatish Balay       facesTmp[4]  = cone[4];
2669371c9d4SSatish Balay       facesTmp[5]  = cone[5];
2679371c9d4SSatish Balay       facesTmp[6]  = cone[6];
2689371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
2699371c9d4SSatish Balay       facesTmp[8]  = cone[0];
2709371c9d4SSatish Balay       facesTmp[9]  = cone[3];
2719371c9d4SSatish Balay       facesTmp[10] = cone[5];
2729371c9d4SSatish Balay       facesTmp[11] = cone[4]; /* Front */
2739371c9d4SSatish Balay       facesTmp[12] = cone[2];
2749371c9d4SSatish Balay       facesTmp[13] = cone[1];
2759371c9d4SSatish Balay       facesTmp[14] = cone[7];
2769371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Back */
2779371c9d4SSatish Balay       facesTmp[16] = cone[3];
2789371c9d4SSatish Balay       facesTmp[17] = cone[2];
2799371c9d4SSatish Balay       facesTmp[18] = cone[6];
2809371c9d4SSatish Balay       facesTmp[19] = cone[5]; /* Right */
2819371c9d4SSatish Balay       facesTmp[20] = cone[0];
2829371c9d4SSatish Balay       facesTmp[21] = cone[4];
2839371c9d4SSatish Balay       facesTmp[22] = cone[7];
2849371c9d4SSatish Balay       facesTmp[23] = cone[1]; /* Left */
2859a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2869a5b13a2SMatthew G Knepley     }
28799836e0eSStefano Zampini     break;
288ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM:
289412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
290412e9a14SMatthew G. Knepley     if (faceTypes) {
2919371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2929371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2939371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2949371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2959371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
296412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
297412e9a14SMatthew G. Knepley     }
298412e9a14SMatthew G. Knepley     if (faceSizes) {
2999371c9d4SSatish Balay       sizesTmp[0] = 3;
3009371c9d4SSatish Balay       sizesTmp[1] = 3;
3019371c9d4SSatish Balay       sizesTmp[2] = 4;
3029371c9d4SSatish Balay       sizesTmp[3] = 4;
3039371c9d4SSatish Balay       sizesTmp[4] = 4;
304412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
305412e9a14SMatthew G. Knepley     }
306ba2698f1SMatthew G. Knepley     if (faces) {
3079371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3089371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3099371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3109371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3119371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3129371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3139371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3149371c9d4SSatish Balay       facesTmp[7]  = cone[2];
3159371c9d4SSatish Balay       facesTmp[8]  = cone[4];
3169371c9d4SSatish Balay       facesTmp[9]  = cone[3]; /* Back left */
3179371c9d4SSatish Balay       facesTmp[10] = cone[2];
3189371c9d4SSatish Balay       facesTmp[11] = cone[1];
3199371c9d4SSatish Balay       facesTmp[12] = cone[5];
3209371c9d4SSatish Balay       facesTmp[13] = cone[4]; /* Front */
3219371c9d4SSatish Balay       facesTmp[14] = cone[1];
3229371c9d4SSatish Balay       facesTmp[15] = cone[0];
3239371c9d4SSatish Balay       facesTmp[16] = cone[3];
3249371c9d4SSatish Balay       facesTmp[17] = cone[5]; /* Back right */
325ba2698f1SMatthew G. Knepley       *faces       = facesTmp;
32699836e0eSStefano Zampini     }
32799836e0eSStefano Zampini     break;
328ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
329412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
330412e9a14SMatthew G. Knepley     if (faceTypes) {
3319371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
3329371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
3339371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3349371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3359371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
336412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
337412e9a14SMatthew G. Knepley     }
338412e9a14SMatthew G. Knepley     if (faceSizes) {
3399371c9d4SSatish Balay       sizesTmp[0] = 3;
3409371c9d4SSatish Balay       sizesTmp[1] = 3;
3419371c9d4SSatish Balay       sizesTmp[2] = 4;
3429371c9d4SSatish Balay       sizesTmp[3] = 4;
3439371c9d4SSatish Balay       sizesTmp[4] = 4;
344412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
345412e9a14SMatthew G. Knepley     }
34699836e0eSStefano Zampini     if (faces) {
3479371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3489371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3499371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3509371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3519371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3529371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3539371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3549371c9d4SSatish Balay       facesTmp[7]  = cone[1];
3559371c9d4SSatish Balay       facesTmp[8]  = cone[3];
3569371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Back left */
3579371c9d4SSatish Balay       facesTmp[10] = cone[1];
3589371c9d4SSatish Balay       facesTmp[11] = cone[2];
3599371c9d4SSatish Balay       facesTmp[12] = cone[4];
3609371c9d4SSatish Balay       facesTmp[13] = cone[5]; /* Back right */
3619371c9d4SSatish Balay       facesTmp[14] = cone[2];
3629371c9d4SSatish Balay       facesTmp[15] = cone[0];
3639371c9d4SSatish Balay       facesTmp[16] = cone[5];
3649371c9d4SSatish Balay       facesTmp[17] = cone[3]; /* Front */
36599836e0eSStefano Zampini       *faces       = facesTmp;
36699836e0eSStefano Zampini     }
367412e9a14SMatthew G. Knepley     break;
368412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
369412e9a14SMatthew G. Knepley     /*  7--------6
370412e9a14SMatthew G. Knepley          /|       /|
371412e9a14SMatthew G. Knepley         / |      / |
372412e9a14SMatthew G. Knepley        4--------5  |
373412e9a14SMatthew G. Knepley        |  |     |  |
374412e9a14SMatthew G. Knepley        |  |     |  |
375412e9a14SMatthew G. Knepley        |  3--------2
376412e9a14SMatthew G. Knepley        | /      | /
377412e9a14SMatthew G. Knepley        |/       |/
378412e9a14SMatthew G. Knepley        0--------1
379412e9a14SMatthew G. Knepley        */
380412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
381412e9a14SMatthew G. Knepley     if (faceTypes) {
3829371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
3839371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
3849371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3859371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3869371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3879371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
388412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
389412e9a14SMatthew G. Knepley     }
390412e9a14SMatthew G. Knepley     if (faceSizes) {
3919371c9d4SSatish Balay       sizesTmp[0] = 4;
3929371c9d4SSatish Balay       sizesTmp[1] = 4;
3939371c9d4SSatish Balay       sizesTmp[2] = 4;
3949371c9d4SSatish Balay       sizesTmp[3] = 4;
3959371c9d4SSatish Balay       sizesTmp[4] = 4;
3969371c9d4SSatish Balay       sizesTmp[5] = 4;
397412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
398412e9a14SMatthew G. Knepley     }
399412e9a14SMatthew G. Knepley     if (faces) {
4009371c9d4SSatish Balay       facesTmp[0]  = cone[0];
4019371c9d4SSatish Balay       facesTmp[1]  = cone[1];
4029371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4039371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4049371c9d4SSatish Balay       facesTmp[4]  = cone[4];
4059371c9d4SSatish Balay       facesTmp[5]  = cone[5];
4069371c9d4SSatish Balay       facesTmp[6]  = cone[6];
4079371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
4089371c9d4SSatish Balay       facesTmp[8]  = cone[0];
4099371c9d4SSatish Balay       facesTmp[9]  = cone[1];
4109371c9d4SSatish Balay       facesTmp[10] = cone[4];
4119371c9d4SSatish Balay       facesTmp[11] = cone[5]; /* Front */
4129371c9d4SSatish Balay       facesTmp[12] = cone[1];
4139371c9d4SSatish Balay       facesTmp[13] = cone[2];
4149371c9d4SSatish Balay       facesTmp[14] = cone[5];
4159371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Right */
4169371c9d4SSatish Balay       facesTmp[16] = cone[2];
4179371c9d4SSatish Balay       facesTmp[17] = cone[3];
4189371c9d4SSatish Balay       facesTmp[18] = cone[6];
4199371c9d4SSatish Balay       facesTmp[19] = cone[7]; /* Back */
4209371c9d4SSatish Balay       facesTmp[20] = cone[3];
4219371c9d4SSatish Balay       facesTmp[21] = cone[0];
4229371c9d4SSatish Balay       facesTmp[22] = cone[7];
4239371c9d4SSatish Balay       facesTmp[23] = cone[4]; /* Left */
424412e9a14SMatthew G. Knepley       *faces       = facesTmp;
425412e9a14SMatthew G. Knepley     }
42699836e0eSStefano Zampini     break;
427da9060c4SMatthew G. Knepley   case DM_POLYTOPE_PYRAMID:
428da9060c4SMatthew G. Knepley     /*
429da9060c4SMatthew G. Knepley        4----
430da9060c4SMatthew G. Knepley        |\-\ \-----
431da9060c4SMatthew G. Knepley        | \ -\     \
432da9060c4SMatthew G. Knepley        |  1--\-----2
433da9060c4SMatthew G. Knepley        | /    \   /
434da9060c4SMatthew G. Knepley        |/      \ /
435da9060c4SMatthew G. Knepley        0--------3
436da9060c4SMatthew G. Knepley        */
437da9060c4SMatthew G. Knepley     if (numFaces) *numFaces = 5;
438da9060c4SMatthew G. Knepley     if (faceTypes) {
439da9060c4SMatthew G. Knepley       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
4409371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
4419371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
4429371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
4439371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_TRIANGLE;
444da9060c4SMatthew G. Knepley       *faceTypes  = typesTmp;
445da9060c4SMatthew G. Knepley     }
446da9060c4SMatthew G. Knepley     if (faceSizes) {
447da9060c4SMatthew G. Knepley       sizesTmp[0] = 4;
4489371c9d4SSatish Balay       sizesTmp[1] = 3;
4499371c9d4SSatish Balay       sizesTmp[2] = 3;
4509371c9d4SSatish Balay       sizesTmp[3] = 3;
4519371c9d4SSatish Balay       sizesTmp[4] = 3;
452da9060c4SMatthew G. Knepley       *faceSizes  = sizesTmp;
453da9060c4SMatthew G. Knepley     }
454da9060c4SMatthew G. Knepley     if (faces) {
4559371c9d4SSatish Balay       facesTmp[0]  = cone[0];
4569371c9d4SSatish Balay       facesTmp[1]  = cone[1];
4579371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4589371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4599371c9d4SSatish Balay       facesTmp[4]  = cone[0];
4609371c9d4SSatish Balay       facesTmp[5]  = cone[3];
4619371c9d4SSatish Balay       facesTmp[6]  = cone[4]; /* Front */
4629371c9d4SSatish Balay       facesTmp[7]  = cone[3];
4639371c9d4SSatish Balay       facesTmp[8]  = cone[2];
4649371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Right */
4659371c9d4SSatish Balay       facesTmp[10] = cone[2];
4669371c9d4SSatish Balay       facesTmp[11] = cone[1];
4679371c9d4SSatish Balay       facesTmp[12] = cone[4]; /* Back */
4689371c9d4SSatish Balay       facesTmp[13] = cone[1];
4699371c9d4SSatish Balay       facesTmp[14] = cone[0];
4709371c9d4SSatish Balay       facesTmp[15] = cone[4]; /* Left */
471da9060c4SMatthew G. Knepley       *faces       = facesTmp;
472da9060c4SMatthew G. Knepley     }
473da9060c4SMatthew G. Knepley     break;
474d71ae5a4SJacob Faibussowitsch   default:
475d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
47699836e0eSStefano Zampini   }
4773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47899836e0eSStefano Zampini }
47999836e0eSStefano Zampini 
480d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
481d71ae5a4SJacob Faibussowitsch {
48299836e0eSStefano Zampini   PetscFunctionBegin;
4839566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes));
484442f3b32SStefano Zampini   else if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes));
485442f3b32SStefano Zampini   else if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces));
486442f3b32SStefano Zampini   if (faceTypes) *faceTypes = NULL;
487442f3b32SStefano Zampini   if (faceSizes) *faceSizes = NULL;
488442f3b32SStefano Zampini   if (faces) *faces = NULL;
4893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49099836e0eSStefano Zampini }
49199836e0eSStefano Zampini 
4929a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
493d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
494d71ae5a4SJacob Faibussowitsch {
495412e9a14SMatthew G. Knepley   DMLabel       ctLabel;
496a03d55ffSStefano Zampini   PetscHMapIJKL faceTable;
497412e9a14SMatthew G. Knepley   PetscInt      faceTypeNum[DM_NUM_POLYTOPES];
498*1afe9b7dSMatthew G. Knepley   PetscInt      depth, pStart, Np, cStart, cEnd, fStart, fEnd, vStart, vEnd;
499a03d55ffSStefano Zampini   PetscInt      cntFaces, *facesId, minCone;
5009f074e33SMatthew G Knepley 
5019f074e33SMatthew G Knepley   PetscFunctionBegin;
5029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
503a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLCreate(&faceTable));
5049566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
505*1afe9b7dSMatthew G. Knepley   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
5069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
507*1afe9b7dSMatthew G. Knepley   // If the range incorporates the vertices, it means we have a non-manifold topology, so choose just cells
508*1afe9b7dSMatthew G. Knepley   if (cStart <= vStart && cEnd >= vEnd) cEnd = vStart;
5095c2c0cecSMatthew G. Knepley   // Number new faces and save face vertices in hash table
510*1afe9b7dSMatthew G. Knepley   //   If depth > cellDepth, meaning we are interpolating faces, put the new (d-1)-faces after them
511*1afe9b7dSMatthew G. Knepley   //   otherwise, we are interpolating cells, so put the faces after the vertices
5129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
513412e9a14SMatthew G. Knepley   fEnd = fStart;
514591a860aSStefano Zampini 
515a03d55ffSStefano Zampini   minCone  = PETSC_MAX_INT;
5165c2c0cecSMatthew G. Knepley   cntFaces = 0;
5175c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
518591a860aSStefano Zampini     const PetscInt *cone;
519591a860aSStefano Zampini     DMPolytopeType  ct;
520ed896b67SJose E. Roman     PetscInt        numFaces = 0, coneSize;
521591a860aSStefano Zampini 
522591a860aSStefano Zampini     PetscCall(DMPlexGetCellType(dm, c, &ct));
523591a860aSStefano Zampini     PetscCall(DMPlexGetCone(dm, c, &cone));
524a03d55ffSStefano Zampini     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
525a03d55ffSStefano Zampini     for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone);
5266f5c9017SMatthew G. Knepley     // Ignore faces since they are interpolated
5276f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL));
528591a860aSStefano Zampini     cntFaces += numFaces;
529591a860aSStefano Zampini   }
530a03d55ffSStefano Zampini   // Encode so that we can use 0 as an excluded value, instead of PETSC_MAX_INT
531a03d55ffSStefano Zampini   minCone = -(minCone - 1);
532591a860aSStefano Zampini 
533591a860aSStefano Zampini   PetscCall(PetscMalloc1(cntFaces, &facesId));
534591a860aSStefano Zampini 
5355c2c0cecSMatthew G. Knepley   cntFaces = 0;
5365c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
537412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
538412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
539ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
5405c2c0cecSMatthew G. Knepley     PetscInt              numFaces, foff = 0;
54199836e0eSStefano Zampini 
5429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5446f5c9017SMatthew G. Knepley     // Ignore faces since they are interpolated
5456f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5476f5c9017SMatthew G. Knepley     } else {
5486f5c9017SMatthew G. Knepley       numFaces = 0;
5496f5c9017SMatthew G. Knepley     }
5505c2c0cecSMatthew G. Knepley     for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
551412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
552412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
553412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
5549a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
555e8f14785SLisandro Dalcin       PetscHashIter        iter;
556e8f14785SLisandro Dalcin       PetscBool            missing;
5579f074e33SMatthew G Knepley 
5585f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
559a03d55ffSStefano Zampini       key.i = face[0] + minCone;
560a03d55ffSStefano Zampini       key.j = faceSize > 1 ? face[1] + minCone : 0;
561a03d55ffSStefano Zampini       key.k = faceSize > 2 ? face[2] + minCone : 0;
562a03d55ffSStefano Zampini       key.l = faceSize > 3 ? face[3] + minCone : 0;
5639566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
564a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
565e9fa77a1SMatthew G. Knepley       if (missing) {
566591a860aSStefano Zampini         facesId[cntFaces] = fEnd;
567a03d55ffSStefano Zampini         PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++));
568412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
569a03d55ffSStefano Zampini       } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
570591a860aSStefano Zampini       cntFaces++;
5719a5b13a2SMatthew G Knepley     }
5726f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
57399836e0eSStefano Zampini   }
574412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
575412e9a14SMatthew G. Knepley   {
576412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
57799836e0eSStefano Zampini 
5789371c9d4SSatish Balay     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5799371c9d4SSatish Balay       if (faceTypeNum[ct]) ++numFT;
5809371c9d4SSatish Balay       faceTypeStart[ct] = 0;
5819371c9d4SSatish Balay     }
582412e9a14SMatthew G. Knepley     if (numFT > 1) {
583a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLClear(faceTable));
584412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
585412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
5865c2c0cecSMatthew G. Knepley       cntFaces = 0;
5875c2c0cecSMatthew G. Knepley       for (PetscInt c = cStart; c < cEnd; ++c) {
588412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
589412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
590ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
5915c2c0cecSMatthew G. Knepley         PetscInt              numFaces, foff = 0;
59299836e0eSStefano Zampini 
5939566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
5949566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
5956f5c9017SMatthew G. Knepley         if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5969566063dSJacob Faibussowitsch           PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5976f5c9017SMatthew G. Knepley         } else {
5986f5c9017SMatthew G. Knepley           numFaces = 0;
5996f5c9017SMatthew G. Knepley         }
6005c2c0cecSMatthew G. Knepley         for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
601412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
602412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
603412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
60499836e0eSStefano Zampini           PetscHashIJKLKey     key;
60599836e0eSStefano Zampini           PetscHashIter        iter;
60699836e0eSStefano Zampini           PetscBool            missing;
60799836e0eSStefano Zampini 
608a03d55ffSStefano Zampini           key.i = face[0] + minCone;
609a03d55ffSStefano Zampini           key.j = faceSize > 1 ? face[1] + minCone : 0;
610a03d55ffSStefano Zampini           key.k = faceSize > 2 ? face[2] + minCone : 0;
611a03d55ffSStefano Zampini           key.l = faceSize > 3 ? face[3] + minCone : 0;
6129566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
613a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
614591a860aSStefano Zampini           if (missing) {
615591a860aSStefano Zampini             facesId[cntFaces] = faceTypeStart[faceType];
616a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
617a03d55ffSStefano Zampini           } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
618591a860aSStefano Zampini           cntFaces++;
61999836e0eSStefano Zampini         }
6206f5c9017SMatthew G. Knepley         if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
62199836e0eSStefano Zampini       }
622412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
6231dca8a05SBarry 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]);
6249a5b13a2SMatthew G Knepley       }
6259a5b13a2SMatthew G Knepley     }
626412e9a14SMatthew G. Knepley   }
627a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLDestroy(&faceTable));
628591a860aSStefano Zampini 
6295c2c0cecSMatthew G. Knepley   // Add new points, perhaps inserting into the numbering
6309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
6319566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
6325c2c0cecSMatthew G. Knepley   // Set cone sizes
6335c2c0cecSMatthew G. Knepley   //   Must create the celltype label here so that we do not automatically try to compute the types
6349566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
6359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
6365c2c0cecSMatthew G. Knepley   for (PetscInt d = 0; d <= depth; ++d) {
637412e9a14SMatthew G. Knepley     DMPolytopeType ct;
6385c2c0cecSMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, poff = 0;
6399f074e33SMatthew G Knepley 
6409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
641*1afe9b7dSMatthew G. Knepley     // Check for non-manifold condition
642*1afe9b7dSMatthew G. Knepley     if (d == cellDepth) {
643*1afe9b7dSMatthew G. Knepley       if (pEnd == cEnd) continue;
644*1afe9b7dSMatthew G. Knepley       else pStart = vEnd;
645*1afe9b7dSMatthew G. Knepley     }
6465c2c0cecSMatthew G. Knepley     // Account for insertion
6475c2c0cecSMatthew G. Knepley     if (pStart >= fStart) poff = fEnd - fStart;
6485c2c0cecSMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
6499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
6505c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetConeSize(idm, p + poff, coneSize));
6519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
6525c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetCellType(idm, p + poff, ct));
6539f074e33SMatthew G Knepley     }
6549f074e33SMatthew G Knepley   }
6555c2c0cecSMatthew G. Knepley   cntFaces = 0;
6565c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
657591a860aSStefano Zampini     const PetscInt       *cone, *faceSizes;
658412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
659412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
6605c2c0cecSMatthew G. Knepley     PetscInt              numFaces, poff = 0;
661412e9a14SMatthew G. Knepley 
6629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
6645c2c0cecSMatthew G. Knepley     if (c >= fStart) poff = fEnd - fStart;
6656f5c9017SMatthew G. Knepley     if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
6665c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetCellType(idm, c + poff, ct));
6675c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetConeSize(idm, c + poff, 2));
6686f5c9017SMatthew G. Knepley       continue;
6696f5c9017SMatthew G. Knepley     }
670591a860aSStefano Zampini     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6715c2c0cecSMatthew G. Knepley     PetscCall(DMPlexSetCellType(idm, c + poff, ct));
6725c2c0cecSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(idm, c + poff, numFaces));
6735c2c0cecSMatthew G. Knepley     for (PetscInt cf = 0; cf < numFaces; ++cf) {
674591a860aSStefano Zampini       const PetscInt f        = facesId[cntFaces];
675591a860aSStefano Zampini       DMPolytopeType faceType = faceTypes[cf];
676412e9a14SMatthew G. Knepley       const PetscInt faceSize = faceSizes[cf];
6779566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, f, faceSize));
6789566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, f, faceType));
679591a860aSStefano Zampini       cntFaces++;
680412e9a14SMatthew G. Knepley     }
681591a860aSStefano Zampini     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6829f074e33SMatthew G Knepley   }
6839566063dSJacob Faibussowitsch   PetscCall(DMSetUp(idm));
6845c2c0cecSMatthew G. Knepley   // Initialize cones so we do not need the bash table to tell us that a cone has been set
685412e9a14SMatthew G. Knepley   {
686412e9a14SMatthew G. Knepley     PetscSection cs;
687412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
6889a5b13a2SMatthew G Knepley 
6899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSection(idm, &cs));
6909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCones(idm, &cones));
6919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(cs, &csize));
6925c2c0cecSMatthew G. Knepley     for (PetscInt c = 0; c < csize; ++c) cones[c] = -1;
693412e9a14SMatthew G. Knepley   }
6945c2c0cecSMatthew G. Knepley   // Set cones
6955c2c0cecSMatthew G. Knepley   {
6965c2c0cecSMatthew G. Knepley     PetscInt *icone;
6975c2c0cecSMatthew G. Knepley     PetscInt  maxConeSize;
6985c2c0cecSMatthew G. Knepley 
6995c2c0cecSMatthew G. Knepley     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL));
7005c2c0cecSMatthew G. Knepley     PetscCall(PetscMalloc1(maxConeSize, &icone));
7015c2c0cecSMatthew G. Knepley     for (PetscInt d = 0; d <= depth; ++d) {
702412e9a14SMatthew G. Knepley       const PetscInt *cone;
7035c2c0cecSMatthew G. Knepley       PetscInt        pStart, pEnd, poff = 0, coneSize;
704412e9a14SMatthew G. Knepley 
7059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
706*1afe9b7dSMatthew G. Knepley       // Check for non-manifold condition
707*1afe9b7dSMatthew G. Knepley       if (d == cellDepth) {
708*1afe9b7dSMatthew G. Knepley         if (pEnd == cEnd) continue;
709*1afe9b7dSMatthew G. Knepley         else pStart = vEnd;
710*1afe9b7dSMatthew G. Knepley       }
7115c2c0cecSMatthew G. Knepley       // Account for insertion
7125c2c0cecSMatthew G. Knepley       if (pStart >= fStart) poff = fEnd - fStart;
7135c2c0cecSMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
7149566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
7155c2c0cecSMatthew G. Knepley         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
7165c2c0cecSMatthew G. Knepley         for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0);
7175c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetCone(idm, p + poff, icone));
7189566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
7195c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetConeOrientation(idm, p + poff, cone));
7209f074e33SMatthew G Knepley       }
7219a5b13a2SMatthew G Knepley     }
7225c2c0cecSMatthew G. Knepley     cntFaces = 0;
7235c2c0cecSMatthew G. Knepley     for (PetscInt c = cStart; c < cEnd; ++c) {
724412e9a14SMatthew G. Knepley       const PetscInt       *cone, *faceSizes, *faces;
725412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
726ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
7275c2c0cecSMatthew G. Knepley       PetscInt              coneSize, numFaces, foff = 0, poff = 0;
72899836e0eSStefano Zampini 
7299566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
7309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
7315c2c0cecSMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
7325c2c0cecSMatthew G. Knepley       if (c >= fStart) poff = fEnd - fStart;
7336f5c9017SMatthew G. Knepley       if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
7345c2c0cecSMatthew G. Knepley         for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0);
7355c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetCone(idm, c + poff, icone));
7366f5c9017SMatthew G. Knepley         PetscCall(DMPlexGetConeOrientation(dm, c, &cone));
7375c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetConeOrientation(idm, c + poff, cone));
7386f5c9017SMatthew G. Knepley         continue;
7396f5c9017SMatthew G. Knepley       }
7409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
7415c2c0cecSMatthew G. Knepley       for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
742412e9a14SMatthew G. Knepley         DMPolytopeType  faceType = faceTypes[cf];
743412e9a14SMatthew G. Knepley         const PetscInt  faceSize = faceSizes[cf];
744591a860aSStefano Zampini         const PetscInt  f        = facesId[cntFaces];
745412e9a14SMatthew G. Knepley         const PetscInt *face     = &faces[foff];
746412e9a14SMatthew G. Knepley         const PetscInt *fcone;
7479f074e33SMatthew G Knepley 
7489566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertCone(idm, c, cf, f));
7499566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &fcone));
7509566063dSJacob Faibussowitsch         if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
751412e9a14SMatthew G. Knepley         {
752*1afe9b7dSMatthew G. Knepley           const PetscInt *fcone2;
7535c2c0cecSMatthew G. Knepley           PetscInt        ornt;
754a74221b0SStefano Zampini 
7559566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
756*1afe9b7dSMatthew G. Knepley           PetscCall(DMPlexGetCone(idm, f, &fcone2));
75763a3b9bcSJacob 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);
758d89e6e46SMatthew G. Knepley           /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
759*1afe9b7dSMatthew G. Knepley           PetscCall(DMPolytopeGetVertexOrientation(faceType, fcone2, face, &ornt));
7605c2c0cecSMatthew G. Knepley           PetscCall(DMPlexInsertConeOrientation(idm, c + poff, cf, ornt));
76199836e0eSStefano Zampini         }
762591a860aSStefano Zampini         cntFaces++;
76399836e0eSStefano Zampini       }
7649566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
76599836e0eSStefano Zampini     }
7665c2c0cecSMatthew G. Knepley     PetscCall(PetscFree(icone));
7675c2c0cecSMatthew G. Knepley   }
768591a860aSStefano Zampini   PetscCall(PetscFree(facesId));
7699566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
7709566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
7713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7729f074e33SMatthew G Knepley }
7739f074e33SMatthew G Knepley 
774d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
775d71ae5a4SJacob Faibussowitsch {
776f80536cbSVaclav Hapla   PetscInt           nleaves;
777f80536cbSVaclav Hapla   PetscInt           nranks;
778a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks   = NULL;
779a0d42dbcSVaclav Hapla   const PetscInt    *roffset = NULL, *rmine = NULL, *rremote = NULL;
780f80536cbSVaclav Hapla   PetscInt           n, o, r;
781f80536cbSVaclav Hapla 
782f80536cbSVaclav Hapla   PetscFunctionBegin;
7839566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
784f80536cbSVaclav Hapla   nleaves = roffset[nranks];
7859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
786f80536cbSVaclav Hapla   for (r = 0; r < nranks; r++) {
787f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
788f80536cbSVaclav Hapla        - to unify order with the other side */
789f80536cbSVaclav Hapla     o = roffset[r];
790f80536cbSVaclav Hapla     n = roffset[r + 1] - o;
7919566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7929566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7939566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
794f80536cbSVaclav Hapla   }
7953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
796f80536cbSVaclav Hapla }
797f80536cbSVaclav Hapla 
798d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
799d71ae5a4SJacob Faibussowitsch {
800d89e6e46SMatthew G. Knepley   PetscSF            sf;
801d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
802d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
803d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
804d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
805d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
806d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
807d89e6e46SMatthew G. Knepley   PetscInt(*roots)[4], (*leaves)[4], mainCone[4];
808d89e6e46SMatthew G. Knepley   PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4];
8092e745bdaSMatthew G. Knepley   MPI_Comm    comm;
81027d0e99aSVaclav Hapla   PetscMPIInt rank, size;
8112e745bdaSMatthew G. Knepley   PetscInt    debug = 0;
8122e745bdaSMatthew G. Knepley 
8132e745bdaSMatthew G. Knepley   PetscFunctionBegin;
8149566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
8179566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
8189566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
819d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
8209566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
8213ba16761SJacob Faibussowitsch   if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS);
8229566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
8239566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
824d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
825d89e6e46SMatthew G. Knepley     PetscInt coneSize;
8269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
827d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
828d89e6e46SMatthew G. Knepley   }
82963a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
8309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
8319e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
832d89e6e46SMatthew G. Knepley     const PetscInt *cone;
833d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
834d89e6e46SMatthew G. Knepley 
8359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
837d89e6e46SMatthew G. Knepley     /* Ignore vertices */
83827d0e99aSVaclav Hapla     if (coneSize < 2) {
839d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
84027d0e99aSVaclav Hapla         roots[p][c]      = -1;
84127d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
84227d0e99aSVaclav Hapla       }
84327d0e99aSVaclav Hapla       continue;
84427d0e99aSVaclav Hapla     }
8452e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
846d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
8479566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
8488a650c75SVaclav Hapla       if (ind0 < 0) {
8498a650c75SVaclav Hapla         roots[p][c]      = cone[c];
8508a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
851c8148b97SVaclav Hapla       } else {
8528a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
8538a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
8548a650c75SVaclav Hapla       }
8552e745bdaSMatthew G. Knepley     }
856d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
857d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
858d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
859d89e6e46SMatthew G. Knepley     }
8602e745bdaSMatthew G. Knepley   }
8619e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
862d89e6e46SMatthew G. Knepley     PetscInt c;
863d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
8648ccb905dSVaclav Hapla       leaves[p][c]      = -2;
8658ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
8668ccb905dSVaclav Hapla     }
867c8148b97SVaclav Hapla   }
8689566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8699566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
8709566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8719566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
872d89e6e46SMatthew G. Knepley   if (debug) {
8739566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
874c5853193SPierre Jolivet     if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
875d89e6e46SMatthew G. Knepley   }
8769566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8779e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
878d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
879d89e6e46SMatthew G. Knepley     const PetscInt *cone;
880d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
881d89e6e46SMatthew G. Knepley 
882d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
8839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
8849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
886d89e6e46SMatthew G. Knepley     if (debug) {
8879371c9d4SSatish 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]));
888d89e6e46SMatthew G. Knepley     }
8899371c9d4SSatish 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]) {
890d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
891d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
892d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
893d89e6e46SMatthew G. Knepley 
89427d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
895d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
8969dddd249SSatish Balay           mainCone[c] = leaves[p][c];
89727d0e99aSVaclav Hapla           continue;
89827d0e99aSVaclav Hapla         }
899f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
900f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
9019566063dSJacob Faibussowitsch         PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r));
90263a3b9bcSJacob 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]);
9031dca8a05SBarry 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]);
904f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
905d89e6e46SMatthew G. Knepley         rS = roffset[r];
906d89e6e46SMatthew G. Knepley         rN = roffset[r + 1] - rS;
9079566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
90863a3b9bcSJacob 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]);
909f80536cbSVaclav Hapla         /* Get the corresponding local point */
9105f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
911f80536cbSVaclav Hapla       }
91263a3b9bcSJacob 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]));
91327d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
9149566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
9159566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
9169566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
91723aaf07bSVaclav Hapla   }
91827d0e99aSVaclav Hapla   if (debug) {
9199566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
9209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
9212e745bdaSMatthew G. Knepley   }
9229566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
9239566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
9249566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
9253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9262e745bdaSMatthew G. Knepley }
9272e745bdaSMatthew G. Knepley 
928d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
929d71ae5a4SJacob Faibussowitsch {
9302e72742cSMatthew G. Knepley   PetscInt    idx;
9312e72742cSMatthew G. Knepley   PetscMPIInt rank;
9322e72742cSMatthew G. Knepley   PetscBool   flg;
9337bffde78SMichael Lange 
9347bffde78SMichael Lange   PetscFunctionBegin;
9359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9363ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9389566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
93963a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
9409566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9422e72742cSMatthew G. Knepley }
9432e72742cSMatthew G. Knepley 
944d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
945d71ae5a4SJacob Faibussowitsch {
9462e72742cSMatthew G. Knepley   PetscInt    idx;
9472e72742cSMatthew G. Knepley   PetscMPIInt rank;
9482e72742cSMatthew G. Knepley   PetscBool   flg;
9492e72742cSMatthew G. Knepley 
9502e72742cSMatthew G. Knepley   PetscFunctionBegin;
9519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9523ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9549566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
9552e72742cSMatthew G. Knepley   if (idxname) {
95663a3b9bcSJacob 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));
9572e72742cSMatthew G. Knepley   } else {
95863a3b9bcSJacob 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));
9592e72742cSMatthew G. Knepley   }
9609566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9622e72742cSMatthew G. Knepley }
9632e72742cSMatthew G. Knepley 
964d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
965d71ae5a4SJacob Faibussowitsch {
9663be36e83SMatthew G. Knepley   PetscSF         sf;
9673be36e83SMatthew G. Knepley   const PetscInt *locals;
9683be36e83SMatthew G. Knepley   PetscMPIInt     rank;
9692e72742cSMatthew G. Knepley 
9702e72742cSMatthew G. Knepley   PetscFunctionBegin;
9719566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9729566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9739566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
9745f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9752e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
9762e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
9772e72742cSMatthew G. Knepley   } else {
9782e72742cSMatthew G. Knepley     PetscHashIJKey key;
9793be36e83SMatthew G. Knepley     PetscInt       l;
9802e72742cSMatthew G. Knepley 
9812e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9822e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9839566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
9843be36e83SMatthew G. Knepley     if (l >= 0) {
9853be36e83SMatthew G. Knepley       *localPoint = locals[l];
9865f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
9872e72742cSMatthew G. Knepley   }
9883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9892e72742cSMatthew G. Knepley }
9902e72742cSMatthew G. Knepley 
991d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
992d71ae5a4SJacob Faibussowitsch {
9933be36e83SMatthew G. Knepley   PetscSF            sf;
9943be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9953be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9963be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9973be36e83SMatthew G. Knepley   PetscMPIInt        rank;
9983be36e83SMatthew G. Knepley 
9993be36e83SMatthew G. Knepley   PetscFunctionBegin;
10005f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
10019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10029566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
10039566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
10043be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
10059566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
10069566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
10073be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
10089566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
10099371c9d4SSatish Balay   if (l < 0) {
10109371c9d4SSatish Balay     if (mapFailed) *mapFailed = PETSC_TRUE;
10119371c9d4SSatish Balay   } else *remotePoint = remotes[l];
10123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10133be36e83SMatthew G. Knepley owned:
10143be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
10153be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
10163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10173be36e83SMatthew G. Knepley }
10183be36e83SMatthew G. Knepley 
1019d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
1020d71ae5a4SJacob Faibussowitsch {
10213be36e83SMatthew G. Knepley   PetscSF         sf;
10223be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
10233be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
10243be36e83SMatthew G. Knepley 
10253be36e83SMatthew G. Knepley   PetscFunctionBegin;
10263be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
10279566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
10289566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
10293ba16761SJacob Faibussowitsch   if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS);
10309566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
10319371c9d4SSatish Balay   if (idx >= 0) {
10329371c9d4SSatish Balay     *isShared = PETSC_TRUE;
10333ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
10349371c9d4SSatish Balay   }
10359566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
10369566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
10373be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
10383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10393be36e83SMatthew G. Knepley }
10403be36e83SMatthew G. Knepley 
1041d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
1042d71ae5a4SJacob Faibussowitsch {
10433be36e83SMatthew G. Knepley   const PetscInt *cone;
10443be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10453be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
10463be36e83SMatthew G. Knepley 
10473be36e83SMatthew G. Knepley   PetscFunctionBegin;
10489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10503be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10513be36e83SMatthew G. Knepley     PetscBool pointShared;
10523be36e83SMatthew G. Knepley 
10539566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
10543be36e83SMatthew G. Knepley     cShared = (PetscBool)(cShared && pointShared);
10553be36e83SMatthew G. Knepley   }
10563be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
10573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10583be36e83SMatthew G. Knepley }
10593be36e83SMatthew G. Knepley 
1060d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
1061d71ae5a4SJacob Faibussowitsch {
10623be36e83SMatthew G. Knepley   const PetscInt *cone;
10633be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10643be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
10653be36e83SMatthew G. Knepley 
10663be36e83SMatthew G. Knepley   PetscFunctionBegin;
10679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10693be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10703be36e83SMatthew G. Knepley     PetscSFNode rcp;
10715f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
10723be36e83SMatthew G. Knepley 
10739566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
10745f80ce2aSJacob Faibussowitsch     if (mapFailed) {
10753be36e83SMatthew G. Knepley       cmin = missing;
10763be36e83SMatthew G. Knepley     } else {
10773be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10783be36e83SMatthew G. Knepley     }
10793be36e83SMatthew G. Knepley   }
10803be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
10813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10823be36e83SMatthew G. Knepley }
10833be36e83SMatthew G. Knepley 
10843be36e83SMatthew G. Knepley /*
10853be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10863be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10873be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10883be36e83SMatthew G. Knepley */
1089d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
1090d71ae5a4SJacob Faibussowitsch {
10913be36e83SMatthew G. Knepley   MPI_Comm        comm;
10923be36e83SMatthew G. Knepley   const PetscInt *support;
1093cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10943be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10953be36e83SMatthew G. Knepley 
10963be36e83SMatthew G. Knepley   PetscFunctionBegin;
10979566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
10989566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
11009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
11019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
1102cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight + 1) {
1103cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
110463a3b9bcSJacob 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));
11053ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1106cf4dc471SVaclav Hapla   }
11079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
11089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
11099566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
11103be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
11113be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
11123be36e83SMatthew G. Knepley     const PetscInt *cone;
11133be36e83SMatthew G. Knepley     PetscSFNode     cpmin = {-1, -1}, rp = {-1, -1};
11143be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
11153be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
11163be36e83SMatthew G. Knepley     PetscHashIJKey  key;
11173be36e83SMatthew G. Knepley 
11183be36e83SMatthew G. Knepley     /* Only add point once */
111963a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
11203be36e83SMatthew G. Knepley     key.i = p;
11213be36e83SMatthew G. Knepley     key.j = face;
11229566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
11233be36e83SMatthew G. Knepley     if (f >= 0) continue;
11249566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
11259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
11269566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
11273be36e83SMatthew G. Knepley     if (debug) {
112863a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
112963a3b9bcSJacob 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));
11303be36e83SMatthew G. Knepley     }
11313be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
11329566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
11333be36e83SMatthew G. Knepley       if (candidates) {
113463a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
11359566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11369566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
11373be36e83SMatthew G. Knepley         candidates[off + idx].rank    = -1;
11383be36e83SMatthew G. Knepley         candidates[off + idx++].index = coneSize - 1;
11393be36e83SMatthew G. Knepley         candidates[off + idx].rank    = rank;
11403be36e83SMatthew G. Knepley         candidates[off + idx++].index = face;
11413be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
11423be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
11433be36e83SMatthew G. Knepley 
11443be36e83SMatthew G. Knepley           if (cp == p) continue;
11459566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
114663a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
11473be36e83SMatthew G. Knepley           ++idx;
11483be36e83SMatthew G. Knepley         }
11499566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
11503be36e83SMatthew G. Knepley       } else {
11513be36e83SMatthew G. Knepley         /* Add cone size to section */
115263a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
11539566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11549566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
11559566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
11563be36e83SMatthew G. Knepley       }
11573be36e83SMatthew G. Knepley     }
11583be36e83SMatthew G. Knepley   }
11593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11603be36e83SMatthew G. Knepley }
11613be36e83SMatthew G. Knepley 
11622e72742cSMatthew G. Knepley /*@
116320f4b53cSBarry Smith   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation
11642e72742cSMatthew G. Knepley 
116520f4b53cSBarry Smith   Collective
11662e72742cSMatthew G. Knepley 
11672e72742cSMatthew G. Knepley   Input Parameters:
116820f4b53cSBarry Smith + dm      - The interpolated `DMPLEX`
116920f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points
11702e72742cSMatthew G. Knepley 
1171f0cfc026SVaclav Hapla   Level: developer
11722e72742cSMatthew G. Knepley 
117320f4b53cSBarry Smith   Note:
117420f4b53cSBarry Smith   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`
11752e72742cSMatthew G. Knepley 
117620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()`
11772e72742cSMatthew G. Knepley @*/
1178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
1179d71ae5a4SJacob Faibussowitsch {
11803be36e83SMatthew G. Knepley   MPI_Comm           comm;
11813be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
11823be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
11833be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11843be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11852e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11862e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11873be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11883be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11893be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1190f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11912e72742cSMatthew G. Knepley 
11922e72742cSMatthew G. Knepley   PetscFunctionBegin;
1193f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1194064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11959566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
11963ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
11973be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
11989566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
11999566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
12009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
12019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
120228b400f6SJacob Faibussowitsch   PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
12039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
12049566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
12059566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
12069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
12073be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
12089566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
120908401ef6SPierre Jolivet   PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
12109566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
12113be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
12123be36e83SMatthew G. Knepley     PetscHashIJKey key;
12132e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
12142e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
12159566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
12167bffde78SMichael Lange   }
121766aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
12189566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
12199566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
12209566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
12213be36e83SMatthew G. Knepley   /*
12223be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
12233be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
12243be36e83SMatthew G. Knepley   \begin{itemize}
12253be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
12263be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
12273be36e83SMatthew G. Knepley   \end{itemize}
12283be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
12293be36e83SMatthew 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
12303be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
12313be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
12323be36e83SMatthew G. Knepley   */
12333be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
12343be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
1235da81f932SPierre Jolivet        The array holds candidate shared faces, each face is referred to by the leaf point */
12369566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
12379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
12387bffde78SMichael Lange   {
12393be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
12402e72742cSMatthew G. Knepley 
12419566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
12423be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12433be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
12442e72742cSMatthew G. Knepley 
124563a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
12469566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
12472e72742cSMatthew G. Knepley     }
12489566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
12499566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
12509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
12519566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
12523be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12533be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
12542e72742cSMatthew G. Knepley 
125563a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
12569566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
12572e72742cSMatthew G. Knepley     }
12589566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
12599566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
12607bffde78SMichael Lange   }
12619566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
12629566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
12639566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
12643be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
12652e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
12667bffde78SMichael Lange   {
12677bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
12687bffde78SMichael Lange     PetscInt *remoteOffsets;
12692e72742cSMatthew G. Knepley 
12709566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
12719566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
12729566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
12739566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
12749566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
12759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
12769566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
12779566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12789566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12799566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
12809566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
12819566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
12822e72742cSMatthew G. Knepley 
12839566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12849566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12859566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12867bffde78SMichael Lange   }
12873be36e83SMatthew 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 */
12887bffde78SMichael Lange   {
1289a03d55ffSStefano Zampini     PetscHMapIJKLRemote faceTable;
12903be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12913be36e83SMatthew G. Knepley 
1292a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteCreate(&faceTable));
12932e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12943be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12952e72742cSMatthew G. Knepley       PetscInt deg;
12963be36e83SMatthew G. Knepley 
12972e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
12982e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
12992e72742cSMatthew G. Knepley 
13009566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
13019566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
13023be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
13032e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13043be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
13053be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13063be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx + 1];
13073be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13083be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
13093be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
13102e72742cSMatthew G. Knepley           const PetscInt        *join = NULL;
1311a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
13123be36e83SMatthew G. Knepley           PetscHashIter          iter;
13135f80ce2aSJacob Faibussowitsch           PetscBool              missing, mapToLocalPointFailed = PETSC_FALSE;
13142e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
13152e72742cSMatthew G. Knepley 
13169371c9d4SSatish Balay           if (debug)
13179371c9d4SSatish 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,
13189371c9d4SSatish Balay                                               rface.index, r, idx, d, Np));
131963a3b9bcSJacob 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);
13203be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13213be36e83SMatthew G. Knepley           fcp0.index = r;
13223be36e83SMatthew G. Knepley           d += Np;
13233be36e83SMatthew G. Knepley           /* Put remote face in hash table */
13243be36e83SMatthew G. Knepley           key.i = fcp0;
13253be36e83SMatthew G. Knepley           key.j = fcone[0];
13263be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13273be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13289566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
1329a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
13303be36e83SMatthew G. Knepley           if (missing) {
133163a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1332a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13333be36e83SMatthew G. Knepley           } else {
13343be36e83SMatthew G. Knepley             PetscSFNode oface;
13353be36e83SMatthew G. Knepley 
1336a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13373be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
133863a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1339a03d55ffSStefano Zampini               PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13403be36e83SMatthew G. Knepley             }
13413be36e83SMatthew G. Knepley           }
13423be36e83SMatthew G. Knepley           /* Check for local face */
13432e72742cSMatthew G. Knepley           points[0] = r;
13443be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
13459566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
13465f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
134763a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
13487bffde78SMichael Lange           }
13495f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
13509566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
13517bffde78SMichael Lange           if (joinSize == 1) {
13523be36e83SMatthew G. Knepley             PetscSFNode lface;
13533be36e83SMatthew G. Knepley             PetscSFNode oface;
13543be36e83SMatthew G. Knepley 
13553be36e83SMatthew G. Knepley             /* Always replace with local face */
13563be36e83SMatthew G. Knepley             lface.rank  = rank;
13573be36e83SMatthew G. Knepley             lface.index = join[0];
1358a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13599371c9d4SSatish Balay             if (debug)
13609371c9d4SSatish 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));
1361a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface));
13627bffde78SMichael Lange           }
13639566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
13643be36e83SMatthew G. Knepley         }
13653be36e83SMatthew G. Knepley       }
13663be36e83SMatthew G. Knepley       /* Put back faces for this root */
13673be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
13683be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
13693be36e83SMatthew G. Knepley 
13709566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
13719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
13723be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
13733be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13743be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
13753be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13763be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13773be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
13783be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
1379a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
13803be36e83SMatthew G. Knepley           PetscHashIter          iter;
13813be36e83SMatthew G. Knepley           PetscBool              missing;
13823be36e83SMatthew G. Knepley 
138363a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
138463a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13853be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13863be36e83SMatthew G. Knepley           fcp0.index = r;
13873be36e83SMatthew G. Knepley           d += Np;
13883be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13893be36e83SMatthew G. Knepley           key.i = fcp0;
13903be36e83SMatthew G. Knepley           key.j = fcone[0];
13913be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13923be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13939566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13949371c9d4SSatish Balay           if (debug)
13959371c9d4SSatish 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,
13969371c9d4SSatish 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));
1397a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
139863a3b9bcSJacob Faibussowitsch           PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1399a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
14007bffde78SMichael Lange         }
14017bffde78SMichael Lange       }
14027bffde78SMichael Lange     }
14039566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
1404a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable));
14057bffde78SMichael Lange   }
14063be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
14077bffde78SMichael Lange   {
14087bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
14097bffde78SMichael Lange     PetscSFNode *remotePointsNew;
14102e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
14113be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
14122e72742cSMatthew G. Knepley 
14133be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
14149566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
14159566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
14169566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
14179566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
14189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
14199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
14203be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
14219566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
14229566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
14239566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
14249566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
14259566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
14269566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
14279566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
14283be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
14293be36e83SMatthew 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 */
14309566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
14313be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
14323be36e83SMatthew G. Knepley       PetscInt dof, off, d;
14332e72742cSMatthew G. Knepley 
143463a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
14359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
14369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
14372e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
14383be36e83SMatthew G. Knepley         if (claims[off + d].rank >= 0) {
14393be36e83SMatthew G. Knepley           const PetscInt  faceInd = off + d;
14403be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off + d].index;
14412e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
14422e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
14432e72742cSMatthew G. Knepley 
144463a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
14453be36e83SMatthew G. Knepley           points[0] = r;
144663a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
14473be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
14489566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
144963a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c + 1]));
14502e72742cSMatthew G. Knepley           }
14519566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
14522e72742cSMatthew G. Knepley           if (joinSize == 1) {
14533be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
145463a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
14553be36e83SMatthew G. Knepley             } else {
145663a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
14579566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
14582e72742cSMatthew G. Knepley             }
14593be36e83SMatthew G. Knepley           } else {
14609566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
14613be36e83SMatthew G. Knepley           }
14629566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
14633be36e83SMatthew G. Knepley         } else {
146463a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
14653be36e83SMatthew G. Knepley           d += claims[off + d].index + 1;
14667bffde78SMichael Lange         }
14677bffde78SMichael Lange       }
14683be36e83SMatthew G. Knepley     }
14699566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
14703be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
14719566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
14729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14739566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
14749566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
14753be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
14763be36e83SMatthew G. Knepley       localPointsNew[l]        = localPoints[l];
14773be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
14783be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
14797bffde78SMichael Lange     }
14803be36e83SMatthew G. Knepley     p = Nl;
14819566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
14823be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
14838e3a54c0SPierre Jolivet     PetscCall(PetscSortInt(NlNew, PetscSafePointerPlusOffset(localPointsNew, Nl)));
14843be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14853be36e83SMatthew G. Knepley       PetscInt off;
14869566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
14871dca8a05SBarry 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);
14883be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14897bffde78SMichael Lange     }
14909566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
14919566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14929566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
14939566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
14949566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1495d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
14969566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
14979566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
14987bffde78SMichael Lange   }
14999566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
15009566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
15019566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
15029566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
15039566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
15049566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
15059566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
15069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
15073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15087bffde78SMichael Lange }
15097bffde78SMichael Lange 
1510248eb259SVaclav Hapla /*@
151180330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
151280330477SMatthew G. Knepley 
151320f4b53cSBarry Smith   Collective
151480330477SMatthew G. Knepley 
151520f4b53cSBarry Smith   Input Parameter:
151620f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices
151780330477SMatthew G. Knepley 
151880330477SMatthew G. Knepley   Output Parameter:
151920f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object
152080330477SMatthew G. Knepley 
152180330477SMatthew G. Knepley   Level: intermediate
152280330477SMatthew G. Knepley 
152320f4b53cSBarry Smith   Note:
15247fb59074SVaclav Hapla   Labels and coordinates are copied.
152543eeeb2dSStefano Zampini 
152660225df5SJacob Faibussowitsch   Developer Notes:
152720f4b53cSBarry Smith   It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`.
15289ade3219SVaclav Hapla 
152920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
153080330477SMatthew G. Knepley @*/
1531d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
1532d71ae5a4SJacob Faibussowitsch {
1533a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
15349a5b13a2SMatthew G Knepley   DM                     idm, odm = dm;
15357bffde78SMichael Lange   PetscSF                sfPoint;
15362e1b13c2SMatthew G. Knepley   PetscInt               depth, dim, d;
153710a67516SMatthew G. Knepley   const char            *name;
1538b325530aSVaclav Hapla   PetscBool              flg = PETSC_TRUE;
15399f074e33SMatthew G Knepley 
15409f074e33SMatthew G Knepley   PetscFunctionBegin;
154110a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15424f572ea9SToby Isaac   PetscAssertPointer(dmInt, 2);
15439566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
15449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
15459566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
15469566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
154708401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1548827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
15499566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
155076b791aaSMatthew G. Knepley     idm = dm;
1551b21b8912SMatthew G. Knepley   } else {
15525c2c0cecSMatthew G. Knepley     PetscBool nonmanifold = PETSC_FALSE;
15535c2c0cecSMatthew G. Knepley 
15545c2c0cecSMatthew G. Knepley     PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &nonmanifold, NULL));
15555c2c0cecSMatthew G. Knepley     if (nonmanifold) {
15565c2c0cecSMatthew G. Knepley       do {
15575c2c0cecSMatthew G. Knepley         const char *prefix;
15585c2c0cecSMatthew G. Knepley         PetscInt    pStart, pEnd, pdepth;
15595c2c0cecSMatthew G. Knepley         PetscBool   done = PETSC_TRUE;
15605c2c0cecSMatthew G. Knepley 
15615c2c0cecSMatthew G. Knepley         // Find a point which is not correctly interpolated
15625c2c0cecSMatthew G. Knepley         PetscCall(DMPlexGetChart(odm, &pStart, &pEnd));
15635c2c0cecSMatthew G. Knepley         for (PetscInt p = pStart; p < pEnd; ++p) {
15645c2c0cecSMatthew G. Knepley           DMPolytopeType  ct;
15655c2c0cecSMatthew G. Knepley           const PetscInt *cone;
15665c2c0cecSMatthew G. Knepley           PetscInt        coneSize, cdepth;
15675c2c0cecSMatthew G. Knepley 
15685c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetPointDepth(odm, p, &pdepth));
15695c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetCellType(odm, p, &ct));
15705c2c0cecSMatthew G. Knepley           // Check against celltype
15715c2c0cecSMatthew G. Knepley           if (pdepth != DMPolytopeTypeGetDim(ct)) {
15725c2c0cecSMatthew G. Knepley             done = PETSC_FALSE;
15735c2c0cecSMatthew G. Knepley             break;
15745c2c0cecSMatthew G. Knepley           }
15755c2c0cecSMatthew G. Knepley           // Check against boundary
15765c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetCone(odm, p, &cone));
15775c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetConeSize(odm, p, &coneSize));
15785c2c0cecSMatthew G. Knepley           for (PetscInt c = 0; c < coneSize; ++c) {
15795c2c0cecSMatthew G. Knepley             PetscCall(DMPlexGetPointDepth(odm, cone[c], &cdepth));
15805c2c0cecSMatthew G. Knepley             if (cdepth != pdepth - 1) {
15815c2c0cecSMatthew G. Knepley               done = PETSC_FALSE;
15825c2c0cecSMatthew G. Knepley               p    = pEnd;
15835c2c0cecSMatthew G. Knepley               break;
15845c2c0cecSMatthew G. Knepley             }
15855c2c0cecSMatthew G. Knepley           }
15865c2c0cecSMatthew G. Knepley         }
15875c2c0cecSMatthew G. Knepley         if (done) break;
15885c2c0cecSMatthew G. Knepley         /* Create interpolated mesh */
15895c2c0cecSMatthew G. Knepley         PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
15905c2c0cecSMatthew G. Knepley         PetscCall(DMSetType(idm, DMPLEX));
15915c2c0cecSMatthew G. Knepley         PetscCall(DMSetDimension(idm, dim));
15925c2c0cecSMatthew G. Knepley         PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
15935c2c0cecSMatthew G. Knepley         PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
15945c2c0cecSMatthew G. Knepley         if (depth > 0) {
15955c2c0cecSMatthew G. Knepley           PetscCall(DMPlexInterpolateFaces_Internal(odm, pdepth, idm));
15965c2c0cecSMatthew G. Knepley           PetscCall(DMGetPointSF(odm, &sfPoint));
15975c2c0cecSMatthew G. Knepley           if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
15985c2c0cecSMatthew G. Knepley           {
15995c2c0cecSMatthew G. Knepley             /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
16005c2c0cecSMatthew G. Knepley             PetscInt nroots;
16015c2c0cecSMatthew G. Knepley             PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
16025c2c0cecSMatthew G. Knepley             if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
16035c2c0cecSMatthew G. Knepley           }
16045c2c0cecSMatthew G. Knepley         }
16055c2c0cecSMatthew G. Knepley         if (odm != dm) PetscCall(DMDestroy(&odm));
16065c2c0cecSMatthew G. Knepley         odm = idm;
16075c2c0cecSMatthew G. Knepley       } while (1);
16085c2c0cecSMatthew G. Knepley     } else {
16099a5b13a2SMatthew G Knepley       for (d = 1; d < dim; ++d) {
16106f5c9017SMatthew G. Knepley         const char *prefix;
16116f5c9017SMatthew G. Knepley 
16129a5b13a2SMatthew G Knepley         /* Create interpolated mesh */
16139566063dSJacob Faibussowitsch         PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
16149566063dSJacob Faibussowitsch         PetscCall(DMSetType(idm, DMPLEX));
16159566063dSJacob Faibussowitsch         PetscCall(DMSetDimension(idm, dim));
16166f5c9017SMatthew G. Knepley         PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
16176f5c9017SMatthew G. Knepley         PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
16187bffde78SMichael Lange         if (depth > 0) {
16199566063dSJacob Faibussowitsch           PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
16209566063dSJacob Faibussowitsch           PetscCall(DMGetPointSF(odm, &sfPoint));
1621d7d32a9aSMatthew G. Knepley           if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
162294488200SVaclav Hapla           {
16233be36e83SMatthew G. Knepley             /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
162494488200SVaclav Hapla             PetscInt nroots;
16259566063dSJacob Faibussowitsch             PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
16269566063dSJacob Faibussowitsch             if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
162794488200SVaclav Hapla           }
16287bffde78SMichael Lange         }
16299566063dSJacob Faibussowitsch         if (odm != dm) PetscCall(DMDestroy(&odm));
16309a5b13a2SMatthew G Knepley         odm = idm;
16319f074e33SMatthew G Knepley       }
16325c2c0cecSMatthew G. Knepley     }
16339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
16349566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)idm, name));
16359566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
16369566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
16379566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
16389566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
163984699f70SSatish Balay   }
1640827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1641827c4036SVaclav Hapla   {
1642d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)idm->data;
1643827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1644827c4036SVaclav Hapla   }
16455de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
16469a5b13a2SMatthew G Knepley   *dmInt = idm;
16479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
16483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16499f074e33SMatthew G Knepley }
165007b0a1fcSMatthew G Knepley 
165180330477SMatthew G. Knepley /*@
165280330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
165380330477SMatthew G. Knepley 
165420f4b53cSBarry Smith   Collective
165580330477SMatthew G. Knepley 
165680330477SMatthew G. Knepley   Input Parameter:
165720f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates
165880330477SMatthew G. Knepley 
165980330477SMatthew G. Knepley   Output Parameter:
166020f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates
166180330477SMatthew G. Knepley 
166280330477SMatthew G. Knepley   Level: intermediate
166380330477SMatthew G. Knepley 
16646f5c9017SMatthew G. Knepley   Notes:
166520f4b53cSBarry Smith   This is typically used when adding pieces other than vertices to a mesh
166680330477SMatthew G. Knepley 
16676f5c9017SMatthew G. Knepley   This function does not copy localized coordinates.
16686f5c9017SMatthew G. Knepley 
166920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
167080330477SMatthew G. Knepley @*/
1671d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
1672d71ae5a4SJacob Faibussowitsch {
167307b0a1fcSMatthew G Knepley   Vec          coordinatesA, coordinatesB;
167443eeeb2dSStefano Zampini   VecType      vtype;
167507b0a1fcSMatthew G Knepley   PetscSection coordSectionA, coordSectionB;
167607b0a1fcSMatthew G Knepley   PetscScalar *coordsA, *coordsB;
16770bedd6beSMatthew G. Knepley   PetscInt     spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
167890a8aa44SJed Brown   PetscInt     cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
167907b0a1fcSMatthew G Knepley 
168007b0a1fcSMatthew G Knepley   PetscFunctionBegin;
168143eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
168243eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
16833ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
16849566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
16859566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
16869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
16879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
168863a3b9bcSJacob 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);
168961a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
169061a622f3SMatthew G. Knepley   {
169161a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
169261a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
169361a622f3SMatthew G. Knepley     PetscObject        objA, objB;
169461a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
169561a622f3SMatthew G. Knepley     const PetscScalar *constants;
169661a622f3SMatthew G. Knepley     PetscInt           cdim, Nc;
169761a622f3SMatthew G. Knepley 
16989566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
16999566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
17009566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
17019566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
17029566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
17039566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
170461a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
17059566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
17069566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
17079566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
17089566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
17099566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
17109566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
17119566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
17129566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
171361a622f3SMatthew G. Knepley     }
171461a622f3SMatthew G. Knepley   }
17159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
17169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
17179566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
17189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
17193ba16761SJacob Faibussowitsch   if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS);
17209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
17213ba16761SJacob Faibussowitsch   if (!Nf) PetscFunctionReturn(PETSC_SUCCESS);
172263a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1723df26b574SMatthew G. Knepley   if (!coordSectionB) {
1724df26b574SMatthew G. Knepley     PetscInt dim;
1725df26b574SMatthew G. Knepley 
17269566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
17279566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
17289566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
17299566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1730df26b574SMatthew G. Knepley   }
17319566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
17329566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
17339566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
17349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
173543eeeb2dSStefano Zampini   cS = vStartB;
173643eeeb2dSStefano Zampini   cE = vEndB;
17379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
173807b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
17399566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
17409566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
174107b0a1fcSMatthew G Knepley   }
17429566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
17439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
17449566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
17459566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
17469566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
17479566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
17489566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
17499566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
17509566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
17519566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
17529566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
17539566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
175407b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB - vStartB; ++v) {
175543eeeb2dSStefano Zampini     PetscInt offA, offB;
175643eeeb2dSStefano Zampini 
17579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
17589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1759ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
176043eeeb2dSStefano Zampini   }
17619566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
17629566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
17639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
17649566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
17653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
176607b0a1fcSMatthew G Knepley }
17675c386225SMatthew G. Knepley 
17684e3744c5SMatthew G. Knepley /*@
17694e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
17704e3744c5SMatthew G. Knepley 
177120f4b53cSBarry Smith   Collective
17724e3744c5SMatthew G. Knepley 
17734e3744c5SMatthew G. Knepley   Input Parameter:
177420f4b53cSBarry Smith . dm - The complete `DMPLEX` object
17754e3744c5SMatthew G. Knepley 
17764e3744c5SMatthew G. Knepley   Output Parameter:
177720f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices
17784e3744c5SMatthew G. Knepley 
17794e3744c5SMatthew G. Knepley   Level: intermediate
17804e3744c5SMatthew G. Knepley 
178120f4b53cSBarry Smith   Note:
178295452b02SPatrick Sanan   It does not copy over the coordinates.
178343eeeb2dSStefano Zampini 
178460225df5SJacob Faibussowitsch   Developer Notes:
178520f4b53cSBarry Smith   Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
17869ade3219SVaclav Hapla 
178720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
17884e3744c5SMatthew G. Knepley @*/
1789d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
1790d71ae5a4SJacob Faibussowitsch {
1791827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
17924e3744c5SMatthew G. Knepley   DM                     udm;
1793412e9a14SMatthew G. Knepley   PetscInt               dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
17944e3744c5SMatthew G. Knepley 
17954e3744c5SMatthew G. Knepley   PetscFunctionBegin;
179643eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17974f572ea9SToby Isaac   PetscAssertPointer(dmUnint, 2);
1798172ee266SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0));
17999566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
18009566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
180108401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1802827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1803827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
18049566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1805595d4abbSMatthew G. Knepley     *dmUnint = dm;
18063ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18074e3744c5SMatthew G. Knepley   }
18089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
18099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
18109566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
18119566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
18129566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
18139566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
18144e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1815595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
18164e3744c5SMatthew G. Knepley 
18179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18184e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
18194e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
18204e3744c5SMatthew G. Knepley 
18214e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
18224e3744c5SMatthew G. Knepley     }
18239566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18249566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1825595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
18264e3744c5SMatthew G. Knepley   }
18279566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
18289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
18294e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1830595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
18314e3744c5SMatthew G. Knepley 
18329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18334e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
18344e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
18354e3744c5SMatthew G. Knepley 
18364e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
18374e3744c5SMatthew G. Knepley     }
18389566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18399566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
18404e3744c5SMatthew G. Knepley   }
18419566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
18429566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
18439566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
18445c7de58aSMatthew G. Knepley   /* Reduce SF */
18455c7de58aSMatthew G. Knepley   {
18465c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
18475c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
18485c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
18495c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
18505c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
185122fd0ad9SVaclav Hapla     PetscInt           numRoots, numLeaves, l;
18525c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
18535c7de58aSMatthew G. Knepley 
18545c7de58aSMatthew G. Knepley     /* Get original SF information */
18559566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
1856d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
18579566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
18589566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
185922fd0ad9SVaclav Hapla     if (numRoots >= 0) {
18605c7de58aSMatthew G. Knepley       /* Allocate space for cells and vertices */
186122fd0ad9SVaclav Hapla       for (l = 0; l < numLeaves; ++l) {
186222fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
186322fd0ad9SVaclav Hapla 
186422fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
186522fd0ad9SVaclav Hapla       }
18665c7de58aSMatthew G. Knepley       /* Fill in leaves */
18679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
18689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
18695c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
187022fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
187122fd0ad9SVaclav Hapla 
187222fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
187322fd0ad9SVaclav Hapla           localPointsUn[n]        = p;
18745c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
18755c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
18765c7de58aSMatthew G. Knepley           ++n;
18775c7de58aSMatthew G. Knepley         }
18785c7de58aSMatthew G. Knepley       }
187963a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
188022fd0ad9SVaclav Hapla       PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
18815c7de58aSMatthew G. Knepley     }
18825c7de58aSMatthew G. Knepley   }
1883827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1884827c4036SVaclav Hapla   {
1885d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)udm->data;
1886827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1887827c4036SVaclav Hapla   }
18885de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1889d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
18904e3744c5SMatthew G. Knepley   *dmUnint = udm;
1891172ee266SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0));
18923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18934e3744c5SMatthew G. Knepley }
1894a7748839SVaclav Hapla 
1895d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1896d71ae5a4SJacob Faibussowitsch {
1897a7748839SVaclav Hapla   PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1898a7748839SVaclav Hapla   MPI_Comm comm;
1899a7748839SVaclav Hapla 
1900a7748839SVaclav Hapla   PetscFunctionBegin;
19019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
19039566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1904a7748839SVaclav Hapla 
1905a7748839SVaclav Hapla   if (depth == dim) {
1906a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1907a7748839SVaclav Hapla     if (!dim) goto finish;
1908a7748839SVaclav Hapla 
1909a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
19109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1911a7748839SVaclav Hapla     for (p = pStart; p < pEnd; p++) {
19129566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1913a7748839SVaclav Hapla       if (coneSize) {
1914a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1915a7748839SVaclav Hapla         goto finish;
1916a7748839SVaclav Hapla       }
1917a7748839SVaclav Hapla     }
1918a7748839SVaclav Hapla 
1919a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1920a7748839SVaclav Hapla     for (h = 0; h < dim; h++) {
19219566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1922a7748839SVaclav Hapla       for (p = pStart; p < pEnd; p++) {
19239566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1924a7748839SVaclav Hapla         if (!coneSize) {
1925a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1926a7748839SVaclav Hapla           goto finish;
1927a7748839SVaclav Hapla         }
1928a7748839SVaclav Hapla       }
1929a7748839SVaclav Hapla     }
1930a7748839SVaclav Hapla   } else if (depth == 1) {
1931a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1932a7748839SVaclav Hapla   } else {
1933a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1934a7748839SVaclav Hapla   }
1935a7748839SVaclav Hapla finish:
19363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1937a7748839SVaclav Hapla }
1938a7748839SVaclav Hapla 
1939a7748839SVaclav Hapla /*@
194020f4b53cSBarry Smith   DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated.
1941a7748839SVaclav Hapla 
1942a7748839SVaclav Hapla   Not Collective
1943a7748839SVaclav Hapla 
1944a7748839SVaclav Hapla   Input Parameter:
194520f4b53cSBarry Smith . dm - The `DMPLEX` object
1946a7748839SVaclav Hapla 
1947a7748839SVaclav Hapla   Output Parameter:
194820f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1949a7748839SVaclav Hapla 
1950a7748839SVaclav Hapla   Level: intermediate
1951a7748839SVaclav Hapla 
1952a7748839SVaclav Hapla   Notes:
195320f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective
19549ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
195520f4b53cSBarry Smith   However, `DMPlexInterpolate()` guarantees the result is the same on all.
19569ade3219SVaclav Hapla 
195720f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`.
1958a7748839SVaclav Hapla 
19599ade3219SVaclav Hapla   Developer Notes:
196020f4b53cSBarry Smith   Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`.
19619ade3219SVaclav Hapla 
196220f4b53cSBarry Smith   If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called.
19639ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
196420f4b53cSBarry Smith   `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`.
19659ade3219SVaclav Hapla 
196620f4b53cSBarry Smith   If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated.
19679ade3219SVaclav Hapla 
196820f4b53cSBarry Smith   `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`,
196920f4b53cSBarry Smith   and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
19709ade3219SVaclav Hapla 
197120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1972a7748839SVaclav Hapla @*/
1973d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1974d71ae5a4SJacob Faibussowitsch {
1975a7748839SVaclav Hapla   DM_Plex *plex = (DM_Plex *)dm->data;
1976a7748839SVaclav Hapla 
1977a7748839SVaclav Hapla   PetscFunctionBegin;
1978a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19794f572ea9SToby Isaac   PetscAssertPointer(interpolated, 2);
1980a7748839SVaclav Hapla   if (plex->interpolated < 0) {
19819566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
198276bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
1983a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1984a7748839SVaclav Hapla 
19859566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
1986c282ed06SStefano Zampini     PetscCheck(plex->tr || flg == plex->interpolated, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1987a7748839SVaclav Hapla   }
1988a7748839SVaclav Hapla   *interpolated = plex->interpolated;
19893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1990a7748839SVaclav Hapla }
1991a7748839SVaclav Hapla 
1992a7748839SVaclav Hapla /*@
199320f4b53cSBarry Smith   DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner).
1994a7748839SVaclav Hapla 
19952666ff3cSVaclav Hapla   Collective
1996a7748839SVaclav Hapla 
1997a7748839SVaclav Hapla   Input Parameter:
199820f4b53cSBarry Smith . dm - The `DMPLEX` object
1999a7748839SVaclav Hapla 
2000a7748839SVaclav Hapla   Output Parameter:
200120f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
2002a7748839SVaclav Hapla 
2003a7748839SVaclav Hapla   Level: intermediate
2004a7748839SVaclav Hapla 
2005a7748839SVaclav Hapla   Notes:
200620f4b53cSBarry Smith   Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks.
20079ade3219SVaclav Hapla 
200820f4b53cSBarry Smith   This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks.
20099ade3219SVaclav Hapla 
20109ade3219SVaclav Hapla   Developer Notes:
201120f4b53cSBarry Smith   Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`.
20129ade3219SVaclav Hapla 
201320f4b53cSBarry Smith   If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated.
201420f4b53cSBarry Smith   `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
201520f4b53cSBarry Smith   if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`,
20169ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
20179ade3219SVaclav Hapla 
201820f4b53cSBarry Smith   If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective.
2019a7748839SVaclav Hapla 
202020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
2021a7748839SVaclav Hapla @*/
2022d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
2023d71ae5a4SJacob Faibussowitsch {
2024a7748839SVaclav Hapla   DM_Plex  *plex  = (DM_Plex *)dm->data;
2025a7748839SVaclav Hapla   PetscBool debug = PETSC_FALSE;
2026a7748839SVaclav Hapla 
2027a7748839SVaclav Hapla   PetscFunctionBegin;
2028a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20294f572ea9SToby Isaac   PetscAssertPointer(interpolated, 2);
20309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
2031a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
2032a7748839SVaclav Hapla     DMPlexInterpolatedFlag min, max;
2033a7748839SVaclav Hapla     MPI_Comm               comm;
2034a7748839SVaclav Hapla 
20359566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
20369566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
2037712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
2038712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
2039a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
2040a7748839SVaclav Hapla     if (debug) {
2041a7748839SVaclav Hapla       PetscMPIInt rank;
2042a7748839SVaclav Hapla 
20439566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
20449566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
20459566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
2046a7748839SVaclav Hapla     }
2047a7748839SVaclav Hapla   }
2048a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
20493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2050a7748839SVaclav Hapla }
2051