xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 5c2c0cec56e8aa8a299512cc9470ae7abc677dc1)
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*5c2c0cecSMatthew G. Knepley   PetscInt      depth, pStart, Np, cStart, cEnd, fStart, fEnd;
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));
5059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
506*5c2c0cecSMatthew G. Knepley   // Number new faces and save face vertices in hash table
5079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
508412e9a14SMatthew G. Knepley   fEnd = fStart;
509591a860aSStefano Zampini 
510a03d55ffSStefano Zampini   minCone  = PETSC_MAX_INT;
511*5c2c0cecSMatthew G. Knepley   cntFaces = 0;
512*5c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
513591a860aSStefano Zampini     const PetscInt *cone;
514591a860aSStefano Zampini     DMPolytopeType  ct;
515ed896b67SJose E. Roman     PetscInt        numFaces = 0, coneSize;
516591a860aSStefano Zampini 
517591a860aSStefano Zampini     PetscCall(DMPlexGetCellType(dm, c, &ct));
518591a860aSStefano Zampini     PetscCall(DMPlexGetCone(dm, c, &cone));
519a03d55ffSStefano Zampini     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
520a03d55ffSStefano Zampini     for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone);
5216f5c9017SMatthew G. Knepley     // Ignore faces since they are interpolated
5226f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL));
523591a860aSStefano Zampini     cntFaces += numFaces;
524591a860aSStefano Zampini   }
525a03d55ffSStefano Zampini   // Encode so that we can use 0 as an excluded value, instead of PETSC_MAX_INT
526a03d55ffSStefano Zampini   minCone = -(minCone - 1);
527591a860aSStefano Zampini 
528591a860aSStefano Zampini   PetscCall(PetscMalloc1(cntFaces, &facesId));
529591a860aSStefano Zampini 
530*5c2c0cecSMatthew G. Knepley   cntFaces = 0;
531*5c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
532412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
533412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
534ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
535*5c2c0cecSMatthew G. Knepley     PetscInt              numFaces, foff = 0;
53699836e0eSStefano Zampini 
5379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5396f5c9017SMatthew G. Knepley     // Ignore faces since they are interpolated
5406f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5419566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5426f5c9017SMatthew G. Knepley     } else {
5436f5c9017SMatthew G. Knepley       numFaces = 0;
5446f5c9017SMatthew G. Knepley     }
545*5c2c0cecSMatthew G. Knepley     for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
546412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
547412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
548412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
5499a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
550e8f14785SLisandro Dalcin       PetscHashIter        iter;
551e8f14785SLisandro Dalcin       PetscBool            missing;
5529f074e33SMatthew G Knepley 
5535f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
554a03d55ffSStefano Zampini       key.i = face[0] + minCone;
555a03d55ffSStefano Zampini       key.j = faceSize > 1 ? face[1] + minCone : 0;
556a03d55ffSStefano Zampini       key.k = faceSize > 2 ? face[2] + minCone : 0;
557a03d55ffSStefano Zampini       key.l = faceSize > 3 ? face[3] + minCone : 0;
5589566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
559a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
560e9fa77a1SMatthew G. Knepley       if (missing) {
561591a860aSStefano Zampini         facesId[cntFaces] = fEnd;
562a03d55ffSStefano Zampini         PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++));
563412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
564a03d55ffSStefano Zampini       } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
565591a860aSStefano Zampini       cntFaces++;
5669a5b13a2SMatthew G Knepley     }
5676f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
56899836e0eSStefano Zampini   }
569412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
570412e9a14SMatthew G. Knepley   {
571412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
57299836e0eSStefano Zampini 
5739371c9d4SSatish Balay     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5749371c9d4SSatish Balay       if (faceTypeNum[ct]) ++numFT;
5759371c9d4SSatish Balay       faceTypeStart[ct] = 0;
5769371c9d4SSatish Balay     }
577412e9a14SMatthew G. Knepley     if (numFT > 1) {
578a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLClear(faceTable));
579412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
580412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
581*5c2c0cecSMatthew G. Knepley       cntFaces = 0;
582*5c2c0cecSMatthew G. Knepley       for (PetscInt c = cStart; c < cEnd; ++c) {
583412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
584412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
585ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
586*5c2c0cecSMatthew G. Knepley         PetscInt              numFaces, foff = 0;
58799836e0eSStefano Zampini 
5889566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
5899566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
5906f5c9017SMatthew G. Knepley         if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5919566063dSJacob Faibussowitsch           PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5926f5c9017SMatthew G. Knepley         } else {
5936f5c9017SMatthew G. Knepley           numFaces = 0;
5946f5c9017SMatthew G. Knepley         }
595*5c2c0cecSMatthew G. Knepley         for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
596412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
597412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
598412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
59999836e0eSStefano Zampini           PetscHashIJKLKey     key;
60099836e0eSStefano Zampini           PetscHashIter        iter;
60199836e0eSStefano Zampini           PetscBool            missing;
60299836e0eSStefano Zampini 
603a03d55ffSStefano Zampini           key.i = face[0] + minCone;
604a03d55ffSStefano Zampini           key.j = faceSize > 1 ? face[1] + minCone : 0;
605a03d55ffSStefano Zampini           key.k = faceSize > 2 ? face[2] + minCone : 0;
606a03d55ffSStefano Zampini           key.l = faceSize > 3 ? face[3] + minCone : 0;
6079566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
608a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
609591a860aSStefano Zampini           if (missing) {
610591a860aSStefano Zampini             facesId[cntFaces] = faceTypeStart[faceType];
611a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
612a03d55ffSStefano Zampini           } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
613591a860aSStefano Zampini           cntFaces++;
61499836e0eSStefano Zampini         }
6156f5c9017SMatthew G. Knepley         if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
61699836e0eSStefano Zampini       }
617412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
6181dca8a05SBarry 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]);
6199a5b13a2SMatthew G Knepley       }
6209a5b13a2SMatthew G Knepley     }
621412e9a14SMatthew G. Knepley   }
622a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLDestroy(&faceTable));
623591a860aSStefano Zampini 
624*5c2c0cecSMatthew G. Knepley   // Add new points, perhaps inserting into the numbering
6259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
6269566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
627*5c2c0cecSMatthew G. Knepley   // Set cone sizes
628*5c2c0cecSMatthew G. Knepley   //   Must create the celltype label here so that we do not automatically try to compute the types
6299566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
6309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
631*5c2c0cecSMatthew G. Knepley   for (PetscInt d = 0; d <= depth; ++d) {
632412e9a14SMatthew G. Knepley     DMPolytopeType ct;
633*5c2c0cecSMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, poff = 0;
6349f074e33SMatthew G Knepley 
635412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
637*5c2c0cecSMatthew G. Knepley     // Account for insertion
638*5c2c0cecSMatthew G. Knepley     if (pStart >= fStart) poff = fEnd - fStart;
639*5c2c0cecSMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
6409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
641*5c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetConeSize(idm, p + poff, coneSize));
6429566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
643*5c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetCellType(idm, p + poff, ct));
6449f074e33SMatthew G Knepley     }
6459f074e33SMatthew G Knepley   }
646*5c2c0cecSMatthew G. Knepley   cntFaces = 0;
647*5c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
648591a860aSStefano Zampini     const PetscInt       *cone, *faceSizes;
649412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
650412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
651*5c2c0cecSMatthew G. Knepley     PetscInt              numFaces, poff = 0;
652412e9a14SMatthew G. Knepley 
6539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
655*5c2c0cecSMatthew G. Knepley     if (c >= fStart) poff = fEnd - fStart;
6566f5c9017SMatthew G. Knepley     if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
657*5c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetCellType(idm, c + poff, ct));
658*5c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetConeSize(idm, c + poff, 2));
6596f5c9017SMatthew G. Knepley       continue;
6606f5c9017SMatthew G. Knepley     }
661591a860aSStefano Zampini     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
662*5c2c0cecSMatthew G. Knepley     PetscCall(DMPlexSetCellType(idm, c + poff, ct));
663*5c2c0cecSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(idm, c + poff, numFaces));
664*5c2c0cecSMatthew G. Knepley     for (PetscInt cf = 0; cf < numFaces; ++cf) {
665591a860aSStefano Zampini       const PetscInt f        = facesId[cntFaces];
666591a860aSStefano Zampini       DMPolytopeType faceType = faceTypes[cf];
667412e9a14SMatthew G. Knepley       const PetscInt faceSize = faceSizes[cf];
6689566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, f, faceSize));
6699566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, f, faceType));
670591a860aSStefano Zampini       cntFaces++;
671412e9a14SMatthew G. Knepley     }
672591a860aSStefano Zampini     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6739f074e33SMatthew G Knepley   }
6749566063dSJacob Faibussowitsch   PetscCall(DMSetUp(idm));
675*5c2c0cecSMatthew G. Knepley   // Initialize cones so we do not need the bash table to tell us that a cone has been set
676412e9a14SMatthew G. Knepley   {
677412e9a14SMatthew G. Knepley     PetscSection cs;
678412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
6799a5b13a2SMatthew G Knepley 
6809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSection(idm, &cs));
6819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCones(idm, &cones));
6829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(cs, &csize));
683*5c2c0cecSMatthew G. Knepley     for (PetscInt c = 0; c < csize; ++c) cones[c] = -1;
684412e9a14SMatthew G. Knepley   }
685*5c2c0cecSMatthew G. Knepley   // Set cones
686*5c2c0cecSMatthew G. Knepley   {
687*5c2c0cecSMatthew G. Knepley     PetscInt *icone;
688*5c2c0cecSMatthew G. Knepley     PetscInt  maxConeSize;
689*5c2c0cecSMatthew G. Knepley 
690*5c2c0cecSMatthew G. Knepley     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL));
691*5c2c0cecSMatthew G. Knepley     PetscCall(PetscMalloc1(maxConeSize, &icone));
692*5c2c0cecSMatthew G. Knepley     for (PetscInt d = 0; d <= depth; ++d) {
693412e9a14SMatthew G. Knepley       const PetscInt *cone;
694*5c2c0cecSMatthew G. Knepley       PetscInt        pStart, pEnd, poff = 0, coneSize;
695412e9a14SMatthew G. Knepley 
696412e9a14SMatthew G. Knepley       if (d == cellDepth) continue;
6979566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
698*5c2c0cecSMatthew G. Knepley       // Account for insertion
699*5c2c0cecSMatthew G. Knepley       if (pStart >= fStart) poff = fEnd - fStart;
700*5c2c0cecSMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
7019566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
702*5c2c0cecSMatthew G. Knepley         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
703*5c2c0cecSMatthew G. Knepley         for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0);
704*5c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetCone(idm, p + poff, icone));
7059566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
706*5c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetConeOrientation(idm, p + poff, cone));
7079f074e33SMatthew G Knepley       }
7089a5b13a2SMatthew G Knepley     }
709*5c2c0cecSMatthew G. Knepley     cntFaces = 0;
710*5c2c0cecSMatthew G. Knepley     for (PetscInt c = cStart; c < cEnd; ++c) {
711412e9a14SMatthew G. Knepley       const PetscInt       *cone, *faceSizes, *faces;
712412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
713ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
714*5c2c0cecSMatthew G. Knepley       PetscInt              coneSize, numFaces, foff = 0, poff = 0;
71599836e0eSStefano Zampini 
7169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
7179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
718*5c2c0cecSMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
719*5c2c0cecSMatthew G. Knepley       if (c >= fStart) poff = fEnd - fStart;
7206f5c9017SMatthew G. Knepley       if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
721*5c2c0cecSMatthew G. Knepley         for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0);
722*5c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetCone(idm, c + poff, icone));
7236f5c9017SMatthew G. Knepley         PetscCall(DMPlexGetConeOrientation(dm, c, &cone));
724*5c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetConeOrientation(idm, c + poff, cone));
7256f5c9017SMatthew G. Knepley         continue;
7266f5c9017SMatthew G. Knepley       }
7279566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
728*5c2c0cecSMatthew G. Knepley       for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
729412e9a14SMatthew G. Knepley         DMPolytopeType  faceType = faceTypes[cf];
730412e9a14SMatthew G. Knepley         const PetscInt  faceSize = faceSizes[cf];
731591a860aSStefano Zampini         const PetscInt  f        = facesId[cntFaces];
732412e9a14SMatthew G. Knepley         const PetscInt *face     = &faces[foff];
733412e9a14SMatthew G. Knepley         const PetscInt *fcone;
7349f074e33SMatthew G Knepley 
7359566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertCone(idm, c, cf, f));
7369566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &fcone));
7379566063dSJacob Faibussowitsch         if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
738412e9a14SMatthew G. Knepley         {
739*5c2c0cecSMatthew G. Knepley           const PetscInt *fcone;
740*5c2c0cecSMatthew G. Knepley           PetscInt        ornt;
741a74221b0SStefano Zampini 
7429566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
743*5c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetCone(idm, f, &fcone));
74463a3b9bcSJacob 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);
745d89e6e46SMatthew G. Knepley           /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
746*5c2c0cecSMatthew G. Knepley           PetscCall(DMPolytopeGetVertexOrientation(faceType, fcone, face, &ornt));
747*5c2c0cecSMatthew G. Knepley           PetscCall(DMPlexInsertConeOrientation(idm, c + poff, cf, ornt));
74899836e0eSStefano Zampini         }
749591a860aSStefano Zampini         cntFaces++;
75099836e0eSStefano Zampini       }
7519566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
75299836e0eSStefano Zampini     }
753*5c2c0cecSMatthew G. Knepley     PetscCall(PetscFree(icone));
754*5c2c0cecSMatthew G. Knepley   }
755591a860aSStefano Zampini   PetscCall(PetscFree(facesId));
7569566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
7579566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
7583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7599f074e33SMatthew G Knepley }
7609f074e33SMatthew G Knepley 
761d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
762d71ae5a4SJacob Faibussowitsch {
763f80536cbSVaclav Hapla   PetscInt           nleaves;
764f80536cbSVaclav Hapla   PetscInt           nranks;
765a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks   = NULL;
766a0d42dbcSVaclav Hapla   const PetscInt    *roffset = NULL, *rmine = NULL, *rremote = NULL;
767f80536cbSVaclav Hapla   PetscInt           n, o, r;
768f80536cbSVaclav Hapla 
769f80536cbSVaclav Hapla   PetscFunctionBegin;
7709566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
771f80536cbSVaclav Hapla   nleaves = roffset[nranks];
7729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
773f80536cbSVaclav Hapla   for (r = 0; r < nranks; r++) {
774f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
775f80536cbSVaclav Hapla        - to unify order with the other side */
776f80536cbSVaclav Hapla     o = roffset[r];
777f80536cbSVaclav Hapla     n = roffset[r + 1] - o;
7789566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7799566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7809566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
781f80536cbSVaclav Hapla   }
7823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
783f80536cbSVaclav Hapla }
784f80536cbSVaclav Hapla 
785d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
786d71ae5a4SJacob Faibussowitsch {
787d89e6e46SMatthew G. Knepley   PetscSF            sf;
788d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
789d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
790d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
791d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
792d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
793d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
794d89e6e46SMatthew G. Knepley   PetscInt(*roots)[4], (*leaves)[4], mainCone[4];
795d89e6e46SMatthew G. Knepley   PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4];
7962e745bdaSMatthew G. Knepley   MPI_Comm    comm;
79727d0e99aSVaclav Hapla   PetscMPIInt rank, size;
7982e745bdaSMatthew G. Knepley   PetscInt    debug = 0;
7992e745bdaSMatthew G. Knepley 
8002e745bdaSMatthew G. Knepley   PetscFunctionBegin;
8019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
8049566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
8059566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
806d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
8079566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
8083ba16761SJacob Faibussowitsch   if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS);
8099566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
8109566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
811d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
812d89e6e46SMatthew G. Knepley     PetscInt coneSize;
8139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
814d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
815d89e6e46SMatthew G. Knepley   }
81663a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
8179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
8189e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
819d89e6e46SMatthew G. Knepley     const PetscInt *cone;
820d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
821d89e6e46SMatthew G. Knepley 
8229566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
824d89e6e46SMatthew G. Knepley     /* Ignore vertices */
82527d0e99aSVaclav Hapla     if (coneSize < 2) {
826d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
82727d0e99aSVaclav Hapla         roots[p][c]      = -1;
82827d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
82927d0e99aSVaclav Hapla       }
83027d0e99aSVaclav Hapla       continue;
83127d0e99aSVaclav Hapla     }
8322e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
833d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
8349566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
8358a650c75SVaclav Hapla       if (ind0 < 0) {
8368a650c75SVaclav Hapla         roots[p][c]      = cone[c];
8378a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
838c8148b97SVaclav Hapla       } else {
8398a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
8408a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
8418a650c75SVaclav Hapla       }
8422e745bdaSMatthew G. Knepley     }
843d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
844d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
845d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
846d89e6e46SMatthew G. Knepley     }
8472e745bdaSMatthew G. Knepley   }
8489e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
849d89e6e46SMatthew G. Knepley     PetscInt c;
850d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
8518ccb905dSVaclav Hapla       leaves[p][c]      = -2;
8528ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
8538ccb905dSVaclav Hapla     }
854c8148b97SVaclav Hapla   }
8559566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8569566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
8579566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8589566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
859d89e6e46SMatthew G. Knepley   if (debug) {
8609566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
861c5853193SPierre Jolivet     if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
862d89e6e46SMatthew G. Knepley   }
8639566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8649e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
865d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
866d89e6e46SMatthew G. Knepley     const PetscInt *cone;
867d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
868d89e6e46SMatthew G. Knepley 
869d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
8709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
8719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
873d89e6e46SMatthew G. Knepley     if (debug) {
8749371c9d4SSatish 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]));
875d89e6e46SMatthew G. Knepley     }
8769371c9d4SSatish 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]) {
877d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
878d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
879d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
880d89e6e46SMatthew G. Knepley 
88127d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
882d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
8839dddd249SSatish Balay           mainCone[c] = leaves[p][c];
88427d0e99aSVaclav Hapla           continue;
88527d0e99aSVaclav Hapla         }
886f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
887f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
8889566063dSJacob Faibussowitsch         PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r));
88963a3b9bcSJacob 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]);
8901dca8a05SBarry 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]);
891f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
892d89e6e46SMatthew G. Knepley         rS = roffset[r];
893d89e6e46SMatthew G. Knepley         rN = roffset[r + 1] - rS;
8949566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
89563a3b9bcSJacob 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]);
896f80536cbSVaclav Hapla         /* Get the corresponding local point */
8975f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
898f80536cbSVaclav Hapla       }
89963a3b9bcSJacob 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]));
90027d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
9019566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
9029566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
9039566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
90423aaf07bSVaclav Hapla   }
90527d0e99aSVaclav Hapla   if (debug) {
9069566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
9079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
9082e745bdaSMatthew G. Knepley   }
9099566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
9109566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
9119566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
9123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9132e745bdaSMatthew G. Knepley }
9142e745bdaSMatthew G. Knepley 
915d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
916d71ae5a4SJacob Faibussowitsch {
9172e72742cSMatthew G. Knepley   PetscInt    idx;
9182e72742cSMatthew G. Knepley   PetscMPIInt rank;
9192e72742cSMatthew G. Knepley   PetscBool   flg;
9207bffde78SMichael Lange 
9217bffde78SMichael Lange   PetscFunctionBegin;
9229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9233ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9259566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
92663a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
9279566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9292e72742cSMatthew G. Knepley }
9302e72742cSMatthew G. Knepley 
931d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
932d71ae5a4SJacob Faibussowitsch {
9332e72742cSMatthew G. Knepley   PetscInt    idx;
9342e72742cSMatthew G. Knepley   PetscMPIInt rank;
9352e72742cSMatthew G. Knepley   PetscBool   flg;
9362e72742cSMatthew G. Knepley 
9372e72742cSMatthew G. Knepley   PetscFunctionBegin;
9389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9393ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9419566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
9422e72742cSMatthew G. Knepley   if (idxname) {
94363a3b9bcSJacob 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));
9442e72742cSMatthew G. Knepley   } else {
94563a3b9bcSJacob 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));
9462e72742cSMatthew G. Knepley   }
9479566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9492e72742cSMatthew G. Knepley }
9502e72742cSMatthew G. Knepley 
951d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
952d71ae5a4SJacob Faibussowitsch {
9533be36e83SMatthew G. Knepley   PetscSF         sf;
9543be36e83SMatthew G. Knepley   const PetscInt *locals;
9553be36e83SMatthew G. Knepley   PetscMPIInt     rank;
9562e72742cSMatthew G. Knepley 
9572e72742cSMatthew G. Knepley   PetscFunctionBegin;
9589566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9599566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9609566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
9615f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9622e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
9632e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
9642e72742cSMatthew G. Knepley   } else {
9652e72742cSMatthew G. Knepley     PetscHashIJKey key;
9663be36e83SMatthew G. Knepley     PetscInt       l;
9672e72742cSMatthew G. Knepley 
9682e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9692e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9709566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
9713be36e83SMatthew G. Knepley     if (l >= 0) {
9723be36e83SMatthew G. Knepley       *localPoint = locals[l];
9735f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
9742e72742cSMatthew G. Knepley   }
9753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9762e72742cSMatthew G. Knepley }
9772e72742cSMatthew G. Knepley 
978d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
979d71ae5a4SJacob Faibussowitsch {
9803be36e83SMatthew G. Knepley   PetscSF            sf;
9813be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9823be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9833be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9843be36e83SMatthew G. Knepley   PetscMPIInt        rank;
9853be36e83SMatthew G. Knepley 
9863be36e83SMatthew G. Knepley   PetscFunctionBegin;
9875f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9899566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9909566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
9913be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
9929566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9939566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9943be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
9959566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
9969371c9d4SSatish Balay   if (l < 0) {
9979371c9d4SSatish Balay     if (mapFailed) *mapFailed = PETSC_TRUE;
9989371c9d4SSatish Balay   } else *remotePoint = remotes[l];
9993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10003be36e83SMatthew G. Knepley owned:
10013be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
10023be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
10033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10043be36e83SMatthew G. Knepley }
10053be36e83SMatthew G. Knepley 
1006d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
1007d71ae5a4SJacob Faibussowitsch {
10083be36e83SMatthew G. Knepley   PetscSF         sf;
10093be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
10103be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
10113be36e83SMatthew G. Knepley 
10123be36e83SMatthew G. Knepley   PetscFunctionBegin;
10133be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
10149566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
10159566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
10163ba16761SJacob Faibussowitsch   if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS);
10179566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
10189371c9d4SSatish Balay   if (idx >= 0) {
10199371c9d4SSatish Balay     *isShared = PETSC_TRUE;
10203ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
10219371c9d4SSatish Balay   }
10229566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
10239566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
10243be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
10253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10263be36e83SMatthew G. Knepley }
10273be36e83SMatthew G. Knepley 
1028d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
1029d71ae5a4SJacob Faibussowitsch {
10303be36e83SMatthew G. Knepley   const PetscInt *cone;
10313be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10323be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
10333be36e83SMatthew G. Knepley 
10343be36e83SMatthew G. Knepley   PetscFunctionBegin;
10359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10373be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10383be36e83SMatthew G. Knepley     PetscBool pointShared;
10393be36e83SMatthew G. Knepley 
10409566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
10413be36e83SMatthew G. Knepley     cShared = (PetscBool)(cShared && pointShared);
10423be36e83SMatthew G. Knepley   }
10433be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
10443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10453be36e83SMatthew G. Knepley }
10463be36e83SMatthew G. Knepley 
1047d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
1048d71ae5a4SJacob Faibussowitsch {
10493be36e83SMatthew G. Knepley   const PetscInt *cone;
10503be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10513be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
10523be36e83SMatthew G. Knepley 
10533be36e83SMatthew G. Knepley   PetscFunctionBegin;
10549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10563be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10573be36e83SMatthew G. Knepley     PetscSFNode rcp;
10585f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
10593be36e83SMatthew G. Knepley 
10609566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
10615f80ce2aSJacob Faibussowitsch     if (mapFailed) {
10623be36e83SMatthew G. Knepley       cmin = missing;
10633be36e83SMatthew G. Knepley     } else {
10643be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10653be36e83SMatthew G. Knepley     }
10663be36e83SMatthew G. Knepley   }
10673be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
10683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10693be36e83SMatthew G. Knepley }
10703be36e83SMatthew G. Knepley 
10713be36e83SMatthew G. Knepley /*
10723be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10733be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10743be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10753be36e83SMatthew G. Knepley */
1076d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
1077d71ae5a4SJacob Faibussowitsch {
10783be36e83SMatthew G. Knepley   MPI_Comm        comm;
10793be36e83SMatthew G. Knepley   const PetscInt *support;
1080cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10813be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10823be36e83SMatthew G. Knepley 
10833be36e83SMatthew G. Knepley   PetscFunctionBegin;
10849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
10859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
10879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
10889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
1089cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight + 1) {
1090cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
109163a3b9bcSJacob 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));
10923ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1093cf4dc471SVaclav Hapla   }
10949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
10959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
10969566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
10973be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
10983be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
10993be36e83SMatthew G. Knepley     const PetscInt *cone;
11003be36e83SMatthew G. Knepley     PetscSFNode     cpmin = {-1, -1}, rp = {-1, -1};
11013be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
11023be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
11033be36e83SMatthew G. Knepley     PetscHashIJKey  key;
11043be36e83SMatthew G. Knepley 
11053be36e83SMatthew G. Knepley     /* Only add point once */
110663a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
11073be36e83SMatthew G. Knepley     key.i = p;
11083be36e83SMatthew G. Knepley     key.j = face;
11099566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
11103be36e83SMatthew G. Knepley     if (f >= 0) continue;
11119566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
11129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
11139566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
11143be36e83SMatthew G. Knepley     if (debug) {
111563a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
111663a3b9bcSJacob 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));
11173be36e83SMatthew G. Knepley     }
11183be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
11199566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
11203be36e83SMatthew G. Knepley       if (candidates) {
112163a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
11229566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11239566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
11243be36e83SMatthew G. Knepley         candidates[off + idx].rank    = -1;
11253be36e83SMatthew G. Knepley         candidates[off + idx++].index = coneSize - 1;
11263be36e83SMatthew G. Knepley         candidates[off + idx].rank    = rank;
11273be36e83SMatthew G. Knepley         candidates[off + idx++].index = face;
11283be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
11293be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
11303be36e83SMatthew G. Knepley 
11313be36e83SMatthew G. Knepley           if (cp == p) continue;
11329566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
113363a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
11343be36e83SMatthew G. Knepley           ++idx;
11353be36e83SMatthew G. Knepley         }
11369566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
11373be36e83SMatthew G. Knepley       } else {
11383be36e83SMatthew G. Knepley         /* Add cone size to section */
113963a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
11409566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11419566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
11429566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
11433be36e83SMatthew G. Knepley       }
11443be36e83SMatthew G. Knepley     }
11453be36e83SMatthew G. Knepley   }
11463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11473be36e83SMatthew G. Knepley }
11483be36e83SMatthew G. Knepley 
11492e72742cSMatthew G. Knepley /*@
115020f4b53cSBarry Smith   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation
11512e72742cSMatthew G. Knepley 
115220f4b53cSBarry Smith   Collective
11532e72742cSMatthew G. Knepley 
11542e72742cSMatthew G. Knepley   Input Parameters:
115520f4b53cSBarry Smith + dm      - The interpolated `DMPLEX`
115620f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points
11572e72742cSMatthew G. Knepley 
1158f0cfc026SVaclav Hapla   Level: developer
11592e72742cSMatthew G. Knepley 
116020f4b53cSBarry Smith   Note:
116120f4b53cSBarry 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`
11622e72742cSMatthew G. Knepley 
116320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()`
11642e72742cSMatthew G. Knepley @*/
1165d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
1166d71ae5a4SJacob Faibussowitsch {
11673be36e83SMatthew G. Knepley   MPI_Comm           comm;
11683be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
11693be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
11703be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11713be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11722e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11732e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11743be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11753be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11763be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1177f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11782e72742cSMatthew G. Knepley 
11792e72742cSMatthew G. Knepley   PetscFunctionBegin;
1180f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1181064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11829566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
11833ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
11843be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
11859566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
11869566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
118928b400f6SJacob Faibussowitsch   PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
11909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
11919566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
11929566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
11939566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
11943be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
11959566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
119608401ef6SPierre Jolivet   PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
11979566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
11983be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
11993be36e83SMatthew G. Knepley     PetscHashIJKey key;
12002e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
12012e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
12029566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
12037bffde78SMichael Lange   }
120466aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
12059566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
12069566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
12079566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
12083be36e83SMatthew G. Knepley   /*
12093be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
12103be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
12113be36e83SMatthew G. Knepley   \begin{itemize}
12123be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
12133be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
12143be36e83SMatthew G. Knepley   \end{itemize}
12153be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
12163be36e83SMatthew 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
12173be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
12183be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
12193be36e83SMatthew G. Knepley   */
12203be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
12213be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
1222da81f932SPierre Jolivet        The array holds candidate shared faces, each face is referred to by the leaf point */
12239566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
12249566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
12257bffde78SMichael Lange   {
12263be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
12272e72742cSMatthew G. Knepley 
12289566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
12293be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12303be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
12312e72742cSMatthew G. Knepley 
123263a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
12339566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
12342e72742cSMatthew G. Knepley     }
12359566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
12369566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
12379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
12389566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
12393be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12403be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
12412e72742cSMatthew G. Knepley 
124263a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
12439566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
12442e72742cSMatthew G. Knepley     }
12459566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
12469566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
12477bffde78SMichael Lange   }
12489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
12499566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
12509566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
12513be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
12522e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
12537bffde78SMichael Lange   {
12547bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
12557bffde78SMichael Lange     PetscInt *remoteOffsets;
12562e72742cSMatthew G. Knepley 
12579566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
12589566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
12599566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
12609566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
12619566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
12629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
12639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
12649566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12659566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12669566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
12679566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
12689566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
12692e72742cSMatthew G. Knepley 
12709566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12719566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12729566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12737bffde78SMichael Lange   }
12743be36e83SMatthew 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 */
12757bffde78SMichael Lange   {
1276a03d55ffSStefano Zampini     PetscHMapIJKLRemote faceTable;
12773be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12783be36e83SMatthew G. Knepley 
1279a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteCreate(&faceTable));
12802e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12813be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12822e72742cSMatthew G. Knepley       PetscInt deg;
12833be36e83SMatthew G. Knepley 
12842e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
12852e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
12862e72742cSMatthew G. Knepley 
12879566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
12889566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
12893be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12902e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12913be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
12923be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
12933be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx + 1];
12943be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
12953be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
12963be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
12972e72742cSMatthew G. Knepley           const PetscInt        *join = NULL;
1298a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
12993be36e83SMatthew G. Knepley           PetscHashIter          iter;
13005f80ce2aSJacob Faibussowitsch           PetscBool              missing, mapToLocalPointFailed = PETSC_FALSE;
13012e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
13022e72742cSMatthew G. Knepley 
13039371c9d4SSatish Balay           if (debug)
13049371c9d4SSatish 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,
13059371c9d4SSatish Balay                                               rface.index, r, idx, d, Np));
130663a3b9bcSJacob 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);
13073be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13083be36e83SMatthew G. Knepley           fcp0.index = r;
13093be36e83SMatthew G. Knepley           d += Np;
13103be36e83SMatthew G. Knepley           /* Put remote face in hash table */
13113be36e83SMatthew G. Knepley           key.i = fcp0;
13123be36e83SMatthew G. Knepley           key.j = fcone[0];
13133be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13143be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13159566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
1316a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
13173be36e83SMatthew G. Knepley           if (missing) {
131863a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1319a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13203be36e83SMatthew G. Knepley           } else {
13213be36e83SMatthew G. Knepley             PetscSFNode oface;
13223be36e83SMatthew G. Knepley 
1323a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13243be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
132563a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1326a03d55ffSStefano Zampini               PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13273be36e83SMatthew G. Knepley             }
13283be36e83SMatthew G. Knepley           }
13293be36e83SMatthew G. Knepley           /* Check for local face */
13302e72742cSMatthew G. Knepley           points[0] = r;
13313be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
13329566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
13335f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
133463a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
13357bffde78SMichael Lange           }
13365f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
13379566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
13387bffde78SMichael Lange           if (joinSize == 1) {
13393be36e83SMatthew G. Knepley             PetscSFNode lface;
13403be36e83SMatthew G. Knepley             PetscSFNode oface;
13413be36e83SMatthew G. Knepley 
13423be36e83SMatthew G. Knepley             /* Always replace with local face */
13433be36e83SMatthew G. Knepley             lface.rank  = rank;
13443be36e83SMatthew G. Knepley             lface.index = join[0];
1345a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13469371c9d4SSatish Balay             if (debug)
13479371c9d4SSatish 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));
1348a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface));
13497bffde78SMichael Lange           }
13509566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
13513be36e83SMatthew G. Knepley         }
13523be36e83SMatthew G. Knepley       }
13533be36e83SMatthew G. Knepley       /* Put back faces for this root */
13543be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
13553be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
13563be36e83SMatthew G. Knepley 
13579566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
13589566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
13593be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
13603be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13613be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
13623be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13633be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13643be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
13653be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
1366a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
13673be36e83SMatthew G. Knepley           PetscHashIter          iter;
13683be36e83SMatthew G. Knepley           PetscBool              missing;
13693be36e83SMatthew G. Knepley 
137063a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
137163a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13723be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13733be36e83SMatthew G. Knepley           fcp0.index = r;
13743be36e83SMatthew G. Knepley           d += Np;
13753be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13763be36e83SMatthew G. Knepley           key.i = fcp0;
13773be36e83SMatthew G. Knepley           key.j = fcone[0];
13783be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13793be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13809566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13819371c9d4SSatish Balay           if (debug)
13829371c9d4SSatish 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,
13839371c9d4SSatish 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));
1384a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
138563a3b9bcSJacob Faibussowitsch           PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1386a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
13877bffde78SMichael Lange         }
13887bffde78SMichael Lange       }
13897bffde78SMichael Lange     }
13909566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
1391a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable));
13927bffde78SMichael Lange   }
13933be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
13947bffde78SMichael Lange   {
13957bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
13967bffde78SMichael Lange     PetscSFNode *remotePointsNew;
13972e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
13983be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
13992e72742cSMatthew G. Knepley 
14003be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
14019566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
14029566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
14039566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
14049566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
14059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
14069566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
14073be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
14089566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
14099566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
14109566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
14119566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
14129566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
14139566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
14149566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
14153be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
14163be36e83SMatthew 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 */
14179566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
14183be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
14193be36e83SMatthew G. Knepley       PetscInt dof, off, d;
14202e72742cSMatthew G. Knepley 
142163a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
14229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
14239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
14242e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
14253be36e83SMatthew G. Knepley         if (claims[off + d].rank >= 0) {
14263be36e83SMatthew G. Knepley           const PetscInt  faceInd = off + d;
14273be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off + d].index;
14282e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
14292e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
14302e72742cSMatthew G. Knepley 
143163a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
14323be36e83SMatthew G. Knepley           points[0] = r;
143363a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
14343be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
14359566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
143663a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c + 1]));
14372e72742cSMatthew G. Knepley           }
14389566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
14392e72742cSMatthew G. Knepley           if (joinSize == 1) {
14403be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
144163a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
14423be36e83SMatthew G. Knepley             } else {
144363a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
14449566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
14452e72742cSMatthew G. Knepley             }
14463be36e83SMatthew G. Knepley           } else {
14479566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
14483be36e83SMatthew G. Knepley           }
14499566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
14503be36e83SMatthew G. Knepley         } else {
145163a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
14523be36e83SMatthew G. Knepley           d += claims[off + d].index + 1;
14537bffde78SMichael Lange         }
14547bffde78SMichael Lange       }
14553be36e83SMatthew G. Knepley     }
14569566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
14573be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
14589566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
14599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
14619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
14623be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
14633be36e83SMatthew G. Knepley       localPointsNew[l]        = localPoints[l];
14643be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
14653be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
14667bffde78SMichael Lange     }
14673be36e83SMatthew G. Knepley     p = Nl;
14689566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
14693be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
14708e3a54c0SPierre Jolivet     PetscCall(PetscSortInt(NlNew, PetscSafePointerPlusOffset(localPointsNew, Nl)));
14713be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14723be36e83SMatthew G. Knepley       PetscInt off;
14739566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
14741dca8a05SBarry 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);
14753be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14767bffde78SMichael Lange     }
14779566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
14789566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14799566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
14809566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
14819566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1482d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
14839566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
14849566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
14857bffde78SMichael Lange   }
14869566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
14879566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
14889566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
14899566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
14909566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
14919566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
14929566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
14939566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
14943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14957bffde78SMichael Lange }
14967bffde78SMichael Lange 
1497248eb259SVaclav Hapla /*@
149880330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
149980330477SMatthew G. Knepley 
150020f4b53cSBarry Smith   Collective
150180330477SMatthew G. Knepley 
150220f4b53cSBarry Smith   Input Parameter:
150320f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices
150480330477SMatthew G. Knepley 
150580330477SMatthew G. Knepley   Output Parameter:
150620f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object
150780330477SMatthew G. Knepley 
150880330477SMatthew G. Knepley   Level: intermediate
150980330477SMatthew G. Knepley 
151020f4b53cSBarry Smith   Note:
15117fb59074SVaclav Hapla   Labels and coordinates are copied.
151243eeeb2dSStefano Zampini 
151360225df5SJacob Faibussowitsch   Developer Notes:
151420f4b53cSBarry Smith   It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`.
15159ade3219SVaclav Hapla 
151620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
151780330477SMatthew G. Knepley @*/
1518d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
1519d71ae5a4SJacob Faibussowitsch {
1520a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
15219a5b13a2SMatthew G Knepley   DM                     idm, odm = dm;
15227bffde78SMichael Lange   PetscSF                sfPoint;
15232e1b13c2SMatthew G. Knepley   PetscInt               depth, dim, d;
152410a67516SMatthew G. Knepley   const char            *name;
1525b325530aSVaclav Hapla   PetscBool              flg = PETSC_TRUE;
15269f074e33SMatthew G Knepley 
15279f074e33SMatthew G Knepley   PetscFunctionBegin;
152810a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15294f572ea9SToby Isaac   PetscAssertPointer(dmInt, 2);
15309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
15319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
15329566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
15339566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
153408401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1535827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
15369566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
153776b791aaSMatthew G. Knepley     idm = dm;
1538b21b8912SMatthew G. Knepley   } else {
1539*5c2c0cecSMatthew G. Knepley     PetscBool nonmanifold = PETSC_FALSE;
1540*5c2c0cecSMatthew G. Knepley 
1541*5c2c0cecSMatthew G. Knepley     PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &nonmanifold, NULL));
1542*5c2c0cecSMatthew G. Knepley     if (nonmanifold) {
1543*5c2c0cecSMatthew G. Knepley       do {
1544*5c2c0cecSMatthew G. Knepley         const char *prefix;
1545*5c2c0cecSMatthew G. Knepley         PetscInt    pStart, pEnd, pdepth;
1546*5c2c0cecSMatthew G. Knepley         PetscBool   done = PETSC_TRUE;
1547*5c2c0cecSMatthew G. Knepley 
1548*5c2c0cecSMatthew G. Knepley         // Find a point which is not correctly interpolated
1549*5c2c0cecSMatthew G. Knepley         PetscCall(DMPlexGetChart(odm, &pStart, &pEnd));
1550*5c2c0cecSMatthew G. Knepley         for (PetscInt p = pStart; p < pEnd; ++p) {
1551*5c2c0cecSMatthew G. Knepley           DMPolytopeType  ct;
1552*5c2c0cecSMatthew G. Knepley           const PetscInt *cone;
1553*5c2c0cecSMatthew G. Knepley           PetscInt        coneSize, cdepth;
1554*5c2c0cecSMatthew G. Knepley 
1555*5c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetPointDepth(odm, p, &pdepth));
1556*5c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetCellType(odm, p, &ct));
1557*5c2c0cecSMatthew G. Knepley           // Check against celltype
1558*5c2c0cecSMatthew G. Knepley           if (pdepth != DMPolytopeTypeGetDim(ct)) {
1559*5c2c0cecSMatthew G. Knepley             done = PETSC_FALSE;
1560*5c2c0cecSMatthew G. Knepley             break;
1561*5c2c0cecSMatthew G. Knepley           }
1562*5c2c0cecSMatthew G. Knepley           // Check against boundary
1563*5c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetCone(odm, p, &cone));
1564*5c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetConeSize(odm, p, &coneSize));
1565*5c2c0cecSMatthew G. Knepley           for (PetscInt c = 0; c < coneSize; ++c) {
1566*5c2c0cecSMatthew G. Knepley             PetscCall(DMPlexGetPointDepth(odm, cone[c], &cdepth));
1567*5c2c0cecSMatthew G. Knepley             if (cdepth != pdepth - 1) {
1568*5c2c0cecSMatthew G. Knepley               done = PETSC_FALSE;
1569*5c2c0cecSMatthew G. Knepley               p    = pEnd;
1570*5c2c0cecSMatthew G. Knepley               break;
1571*5c2c0cecSMatthew G. Knepley             }
1572*5c2c0cecSMatthew G. Knepley           }
1573*5c2c0cecSMatthew G. Knepley         }
1574*5c2c0cecSMatthew G. Knepley         if (done) break;
1575*5c2c0cecSMatthew G. Knepley         /* Create interpolated mesh */
1576*5c2c0cecSMatthew G. Knepley         PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
1577*5c2c0cecSMatthew G. Knepley         PetscCall(DMSetType(idm, DMPLEX));
1578*5c2c0cecSMatthew G. Knepley         PetscCall(DMSetDimension(idm, dim));
1579*5c2c0cecSMatthew G. Knepley         PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
1580*5c2c0cecSMatthew G. Knepley         PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
1581*5c2c0cecSMatthew G. Knepley         if (depth > 0) {
1582*5c2c0cecSMatthew G. Knepley           PetscCall(DMPlexInterpolateFaces_Internal(odm, pdepth, idm));
1583*5c2c0cecSMatthew G. Knepley           PetscCall(DMGetPointSF(odm, &sfPoint));
1584*5c2c0cecSMatthew G. Knepley           if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
1585*5c2c0cecSMatthew G. Knepley           {
1586*5c2c0cecSMatthew G. Knepley             /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
1587*5c2c0cecSMatthew G. Knepley             PetscInt nroots;
1588*5c2c0cecSMatthew G. Knepley             PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
1589*5c2c0cecSMatthew G. Knepley             if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
1590*5c2c0cecSMatthew G. Knepley           }
1591*5c2c0cecSMatthew G. Knepley         }
1592*5c2c0cecSMatthew G. Knepley         if (odm != dm) PetscCall(DMDestroy(&odm));
1593*5c2c0cecSMatthew G. Knepley         odm = idm;
1594*5c2c0cecSMatthew G. Knepley       } while (1);
1595*5c2c0cecSMatthew G. Knepley     } else {
15969a5b13a2SMatthew G Knepley       for (d = 1; d < dim; ++d) {
15976f5c9017SMatthew G. Knepley         const char *prefix;
15986f5c9017SMatthew G. Knepley 
15999a5b13a2SMatthew G Knepley         /* Create interpolated mesh */
16009566063dSJacob Faibussowitsch         PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
16019566063dSJacob Faibussowitsch         PetscCall(DMSetType(idm, DMPLEX));
16029566063dSJacob Faibussowitsch         PetscCall(DMSetDimension(idm, dim));
16036f5c9017SMatthew G. Knepley         PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
16046f5c9017SMatthew G. Knepley         PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
16057bffde78SMichael Lange         if (depth > 0) {
16069566063dSJacob Faibussowitsch           PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
16079566063dSJacob Faibussowitsch           PetscCall(DMGetPointSF(odm, &sfPoint));
1608d7d32a9aSMatthew G. Knepley           if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
160994488200SVaclav Hapla           {
16103be36e83SMatthew G. Knepley             /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
161194488200SVaclav Hapla             PetscInt nroots;
16129566063dSJacob Faibussowitsch             PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
16139566063dSJacob Faibussowitsch             if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
161494488200SVaclav Hapla           }
16157bffde78SMichael Lange         }
16169566063dSJacob Faibussowitsch         if (odm != dm) PetscCall(DMDestroy(&odm));
16179a5b13a2SMatthew G Knepley         odm = idm;
16189f074e33SMatthew G Knepley       }
1619*5c2c0cecSMatthew G. Knepley     }
16209566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
16219566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)idm, name));
16229566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
16239566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
16249566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
16259566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
162684699f70SSatish Balay   }
1627827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1628827c4036SVaclav Hapla   {
1629d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)idm->data;
1630827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1631827c4036SVaclav Hapla   }
16325de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
16339a5b13a2SMatthew G Knepley   *dmInt = idm;
16349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
16353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16369f074e33SMatthew G Knepley }
163707b0a1fcSMatthew G Knepley 
163880330477SMatthew G. Knepley /*@
163980330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
164080330477SMatthew G. Knepley 
164120f4b53cSBarry Smith   Collective
164280330477SMatthew G. Knepley 
164380330477SMatthew G. Knepley   Input Parameter:
164420f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates
164580330477SMatthew G. Knepley 
164680330477SMatthew G. Knepley   Output Parameter:
164720f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates
164880330477SMatthew G. Knepley 
164980330477SMatthew G. Knepley   Level: intermediate
165080330477SMatthew G. Knepley 
16516f5c9017SMatthew G. Knepley   Notes:
165220f4b53cSBarry Smith   This is typically used when adding pieces other than vertices to a mesh
165380330477SMatthew G. Knepley 
16546f5c9017SMatthew G. Knepley   This function does not copy localized coordinates.
16556f5c9017SMatthew G. Knepley 
165620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
165780330477SMatthew G. Knepley @*/
1658d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
1659d71ae5a4SJacob Faibussowitsch {
166007b0a1fcSMatthew G Knepley   Vec          coordinatesA, coordinatesB;
166143eeeb2dSStefano Zampini   VecType      vtype;
166207b0a1fcSMatthew G Knepley   PetscSection coordSectionA, coordSectionB;
166307b0a1fcSMatthew G Knepley   PetscScalar *coordsA, *coordsB;
16640bedd6beSMatthew G. Knepley   PetscInt     spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
166590a8aa44SJed Brown   PetscInt     cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
166607b0a1fcSMatthew G Knepley 
166707b0a1fcSMatthew G Knepley   PetscFunctionBegin;
166843eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
166943eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
16703ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
16719566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
16729566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
16739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
16749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
167563a3b9bcSJacob 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);
167661a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
167761a622f3SMatthew G. Knepley   {
167861a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
167961a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
168061a622f3SMatthew G. Knepley     PetscObject        objA, objB;
168161a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
168261a622f3SMatthew G. Knepley     const PetscScalar *constants;
168361a622f3SMatthew G. Knepley     PetscInt           cdim, Nc;
168461a622f3SMatthew G. Knepley 
16859566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
16869566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
16879566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
16889566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
16899566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
16909566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
169161a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
16929566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
16939566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
16949566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
16959566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
16969566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
16979566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
16989566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
16999566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
170061a622f3SMatthew G. Knepley     }
170161a622f3SMatthew G. Knepley   }
17029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
17039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
17049566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
17059566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
17063ba16761SJacob Faibussowitsch   if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS);
17079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
17083ba16761SJacob Faibussowitsch   if (!Nf) PetscFunctionReturn(PETSC_SUCCESS);
170963a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1710df26b574SMatthew G. Knepley   if (!coordSectionB) {
1711df26b574SMatthew G. Knepley     PetscInt dim;
1712df26b574SMatthew G. Knepley 
17139566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
17149566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
17159566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
17169566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1717df26b574SMatthew G. Knepley   }
17189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
17199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
17209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
17219566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
172243eeeb2dSStefano Zampini   cS = vStartB;
172343eeeb2dSStefano Zampini   cE = vEndB;
17249566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
172507b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
17269566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
17279566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
172807b0a1fcSMatthew G Knepley   }
17299566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
17309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
17319566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
17329566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
17339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
17349566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
17359566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
17369566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
17379566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
17389566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
17399566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
17409566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
174107b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB - vStartB; ++v) {
174243eeeb2dSStefano Zampini     PetscInt offA, offB;
174343eeeb2dSStefano Zampini 
17449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
17459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1746ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
174743eeeb2dSStefano Zampini   }
17489566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
17499566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
17509566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
17519566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
17523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
175307b0a1fcSMatthew G Knepley }
17545c386225SMatthew G. Knepley 
17554e3744c5SMatthew G. Knepley /*@
17564e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
17574e3744c5SMatthew G. Knepley 
175820f4b53cSBarry Smith   Collective
17594e3744c5SMatthew G. Knepley 
17604e3744c5SMatthew G. Knepley   Input Parameter:
176120f4b53cSBarry Smith . dm - The complete `DMPLEX` object
17624e3744c5SMatthew G. Knepley 
17634e3744c5SMatthew G. Knepley   Output Parameter:
176420f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices
17654e3744c5SMatthew G. Knepley 
17664e3744c5SMatthew G. Knepley   Level: intermediate
17674e3744c5SMatthew G. Knepley 
176820f4b53cSBarry Smith   Note:
176995452b02SPatrick Sanan   It does not copy over the coordinates.
177043eeeb2dSStefano Zampini 
177160225df5SJacob Faibussowitsch   Developer Notes:
177220f4b53cSBarry Smith   Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
17739ade3219SVaclav Hapla 
177420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
17754e3744c5SMatthew G. Knepley @*/
1776d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
1777d71ae5a4SJacob Faibussowitsch {
1778827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
17794e3744c5SMatthew G. Knepley   DM                     udm;
1780412e9a14SMatthew G. Knepley   PetscInt               dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
17814e3744c5SMatthew G. Knepley 
17824e3744c5SMatthew G. Knepley   PetscFunctionBegin;
178343eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17844f572ea9SToby Isaac   PetscAssertPointer(dmUnint, 2);
1785172ee266SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0));
17869566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
17879566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
178808401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1789827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1790827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
17919566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1792595d4abbSMatthew G. Knepley     *dmUnint = dm;
17933ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
17944e3744c5SMatthew G. Knepley   }
17959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
17969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17979566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
17989566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
17999566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
18009566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
18014e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1802595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
18034e3744c5SMatthew G. Knepley 
18049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18054e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
18064e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
18074e3744c5SMatthew G. Knepley 
18084e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
18094e3744c5SMatthew G. Knepley     }
18109566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18119566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1812595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
18134e3744c5SMatthew G. Knepley   }
18149566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
18159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
18164e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1817595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
18184e3744c5SMatthew G. Knepley 
18199566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18204e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
18214e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
18224e3744c5SMatthew G. Knepley 
18234e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
18244e3744c5SMatthew G. Knepley     }
18259566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18269566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
18274e3744c5SMatthew G. Knepley   }
18289566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
18299566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
18309566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
18315c7de58aSMatthew G. Knepley   /* Reduce SF */
18325c7de58aSMatthew G. Knepley   {
18335c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
18345c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
18355c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
18365c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
18375c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
183822fd0ad9SVaclav Hapla     PetscInt           numRoots, numLeaves, l;
18395c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
18405c7de58aSMatthew G. Knepley 
18415c7de58aSMatthew G. Knepley     /* Get original SF information */
18429566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
1843d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
18449566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
18459566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
184622fd0ad9SVaclav Hapla     if (numRoots >= 0) {
18475c7de58aSMatthew G. Knepley       /* Allocate space for cells and vertices */
184822fd0ad9SVaclav Hapla       for (l = 0; l < numLeaves; ++l) {
184922fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
185022fd0ad9SVaclav Hapla 
185122fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
185222fd0ad9SVaclav Hapla       }
18535c7de58aSMatthew G. Knepley       /* Fill in leaves */
18549566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
18559566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
18565c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
185722fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
185822fd0ad9SVaclav Hapla 
185922fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
186022fd0ad9SVaclav Hapla           localPointsUn[n]        = p;
18615c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
18625c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
18635c7de58aSMatthew G. Knepley           ++n;
18645c7de58aSMatthew G. Knepley         }
18655c7de58aSMatthew G. Knepley       }
186663a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
186722fd0ad9SVaclav Hapla       PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
18685c7de58aSMatthew G. Knepley     }
18695c7de58aSMatthew G. Knepley   }
1870827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1871827c4036SVaclav Hapla   {
1872d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)udm->data;
1873827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1874827c4036SVaclav Hapla   }
18755de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1876d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
18774e3744c5SMatthew G. Knepley   *dmUnint = udm;
1878172ee266SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0));
18793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18804e3744c5SMatthew G. Knepley }
1881a7748839SVaclav Hapla 
1882d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1883d71ae5a4SJacob Faibussowitsch {
1884a7748839SVaclav Hapla   PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1885a7748839SVaclav Hapla   MPI_Comm comm;
1886a7748839SVaclav Hapla 
1887a7748839SVaclav Hapla   PetscFunctionBegin;
18889566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
18899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
18909566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1891a7748839SVaclav Hapla 
1892a7748839SVaclav Hapla   if (depth == dim) {
1893a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1894a7748839SVaclav Hapla     if (!dim) goto finish;
1895a7748839SVaclav Hapla 
1896a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
18979566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1898a7748839SVaclav Hapla     for (p = pStart; p < pEnd; p++) {
18999566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1900a7748839SVaclav Hapla       if (coneSize) {
1901a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1902a7748839SVaclav Hapla         goto finish;
1903a7748839SVaclav Hapla       }
1904a7748839SVaclav Hapla     }
1905a7748839SVaclav Hapla 
1906a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1907a7748839SVaclav Hapla     for (h = 0; h < dim; h++) {
19089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1909a7748839SVaclav Hapla       for (p = pStart; p < pEnd; p++) {
19109566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1911a7748839SVaclav Hapla         if (!coneSize) {
1912a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1913a7748839SVaclav Hapla           goto finish;
1914a7748839SVaclav Hapla         }
1915a7748839SVaclav Hapla       }
1916a7748839SVaclav Hapla     }
1917a7748839SVaclav Hapla   } else if (depth == 1) {
1918a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1919a7748839SVaclav Hapla   } else {
1920a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1921a7748839SVaclav Hapla   }
1922a7748839SVaclav Hapla finish:
19233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1924a7748839SVaclav Hapla }
1925a7748839SVaclav Hapla 
1926a7748839SVaclav Hapla /*@
192720f4b53cSBarry Smith   DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated.
1928a7748839SVaclav Hapla 
1929a7748839SVaclav Hapla   Not Collective
1930a7748839SVaclav Hapla 
1931a7748839SVaclav Hapla   Input Parameter:
193220f4b53cSBarry Smith . dm - The `DMPLEX` object
1933a7748839SVaclav Hapla 
1934a7748839SVaclav Hapla   Output Parameter:
193520f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1936a7748839SVaclav Hapla 
1937a7748839SVaclav Hapla   Level: intermediate
1938a7748839SVaclav Hapla 
1939a7748839SVaclav Hapla   Notes:
194020f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective
19419ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
194220f4b53cSBarry Smith   However, `DMPlexInterpolate()` guarantees the result is the same on all.
19439ade3219SVaclav Hapla 
194420f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`.
1945a7748839SVaclav Hapla 
19469ade3219SVaclav Hapla   Developer Notes:
194720f4b53cSBarry Smith   Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`.
19489ade3219SVaclav Hapla 
194920f4b53cSBarry Smith   If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called.
19509ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
195120f4b53cSBarry Smith   `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`.
19529ade3219SVaclav Hapla 
195320f4b53cSBarry Smith   If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated.
19549ade3219SVaclav Hapla 
195520f4b53cSBarry Smith   `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`,
195620f4b53cSBarry Smith   and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
19579ade3219SVaclav Hapla 
195820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1959a7748839SVaclav Hapla @*/
1960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1961d71ae5a4SJacob Faibussowitsch {
1962a7748839SVaclav Hapla   DM_Plex *plex = (DM_Plex *)dm->data;
1963a7748839SVaclav Hapla 
1964a7748839SVaclav Hapla   PetscFunctionBegin;
1965a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19664f572ea9SToby Isaac   PetscAssertPointer(interpolated, 2);
1967a7748839SVaclav Hapla   if (plex->interpolated < 0) {
19689566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
196976bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
1970a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1971a7748839SVaclav Hapla 
19729566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
1973c282ed06SStefano 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]);
1974a7748839SVaclav Hapla   }
1975a7748839SVaclav Hapla   *interpolated = plex->interpolated;
19763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1977a7748839SVaclav Hapla }
1978a7748839SVaclav Hapla 
1979a7748839SVaclav Hapla /*@
198020f4b53cSBarry Smith   DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner).
1981a7748839SVaclav Hapla 
19822666ff3cSVaclav Hapla   Collective
1983a7748839SVaclav Hapla 
1984a7748839SVaclav Hapla   Input Parameter:
198520f4b53cSBarry Smith . dm - The `DMPLEX` object
1986a7748839SVaclav Hapla 
1987a7748839SVaclav Hapla   Output Parameter:
198820f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1989a7748839SVaclav Hapla 
1990a7748839SVaclav Hapla   Level: intermediate
1991a7748839SVaclav Hapla 
1992a7748839SVaclav Hapla   Notes:
199320f4b53cSBarry Smith   Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks.
19949ade3219SVaclav Hapla 
199520f4b53cSBarry Smith   This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks.
19969ade3219SVaclav Hapla 
19979ade3219SVaclav Hapla   Developer Notes:
199820f4b53cSBarry Smith   Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`.
19999ade3219SVaclav Hapla 
200020f4b53cSBarry Smith   If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated.
200120f4b53cSBarry Smith   `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
200220f4b53cSBarry Smith   if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`,
20039ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
20049ade3219SVaclav Hapla 
200520f4b53cSBarry Smith   If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective.
2006a7748839SVaclav Hapla 
200720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
2008a7748839SVaclav Hapla @*/
2009d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
2010d71ae5a4SJacob Faibussowitsch {
2011a7748839SVaclav Hapla   DM_Plex  *plex  = (DM_Plex *)dm->data;
2012a7748839SVaclav Hapla   PetscBool debug = PETSC_FALSE;
2013a7748839SVaclav Hapla 
2014a7748839SVaclav Hapla   PetscFunctionBegin;
2015a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20164f572ea9SToby Isaac   PetscAssertPointer(interpolated, 2);
20179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
2018a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
2019a7748839SVaclav Hapla     DMPlexInterpolatedFlag min, max;
2020a7748839SVaclav Hapla     MPI_Comm               comm;
2021a7748839SVaclav Hapla 
20229566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
20239566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
2024712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
2025712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
2026a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
2027a7748839SVaclav Hapla     if (debug) {
2028a7748839SVaclav Hapla       PetscMPIInt rank;
2029a7748839SVaclav Hapla 
20309566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
20319566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
20329566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
2033a7748839SVaclav Hapla     }
2034a7748839SVaclav Hapla   }
2035a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
20363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2037a7748839SVaclav Hapla }
2038