xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 8e3a54c0662fee99ad69f33e814fb6a3f3eef16b)
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];
4989318fe57SMatthew G. Knepley   PetscInt      depth, d, pStart, Np, cStart, cEnd, c, 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));
506412e9a14SMatthew G. Knepley   /* Number new faces and save face vertices in hash table */
5079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
5086f5c9017SMatthew G. Knepley   {
5096f5c9017SMatthew G. Knepley     PetscInt opEnd;
5106f5c9017SMatthew G. Knepley 
5116f5c9017SMatthew G. Knepley     // We need to account for existing faces in non-manifold meshes
5126f5c9017SMatthew G. Knepley     PetscCall(DMPlexGetChart(dm, NULL, &opEnd));
5136f5c9017SMatthew G. Knepley     fStart = PetscMax(opEnd, fStart);
5146f5c9017SMatthew G. Knepley   }
515412e9a14SMatthew G. Knepley   fEnd = fStart;
516591a860aSStefano Zampini 
517a03d55ffSStefano Zampini   minCone = PETSC_MAX_INT;
518591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
519591a860aSStefano Zampini     const PetscInt *cone;
520591a860aSStefano Zampini     DMPolytopeType  ct;
521ed896b67SJose E. Roman     PetscInt        numFaces = 0, coneSize;
522591a860aSStefano Zampini 
523591a860aSStefano Zampini     PetscCall(DMPlexGetCellType(dm, c, &ct));
524591a860aSStefano Zampini     PetscCall(DMPlexGetCone(dm, c, &cone));
525a03d55ffSStefano Zampini     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
526a03d55ffSStefano Zampini     for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone);
5276f5c9017SMatthew G. Knepley     // Ignore faces since they are interpolated
5286f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL));
529591a860aSStefano Zampini     cntFaces += numFaces;
530591a860aSStefano Zampini   }
531a03d55ffSStefano Zampini   // Encode so that we can use 0 as an excluded value, instead of PETSC_MAX_INT
532a03d55ffSStefano Zampini   minCone = -(minCone - 1);
533591a860aSStefano Zampini 
534591a860aSStefano Zampini   PetscCall(PetscMalloc1(cntFaces, &facesId));
535591a860aSStefano Zampini 
536591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
537412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
538412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
539ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
540412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
54199836e0eSStefano Zampini 
5429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5446f5c9017SMatthew G. Knepley     // Ignore faces since they are interpolated
5456f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5476f5c9017SMatthew G. Knepley     } else {
5486f5c9017SMatthew G. Knepley       numFaces = 0;
5496f5c9017SMatthew G. Knepley     }
550412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
551412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
552412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
553412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
5549a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
555e8f14785SLisandro Dalcin       PetscHashIter        iter;
556e8f14785SLisandro Dalcin       PetscBool            missing;
5579f074e33SMatthew G Knepley 
5585f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
559a03d55ffSStefano Zampini       key.i = face[0] + minCone;
560a03d55ffSStefano Zampini       key.j = faceSize > 1 ? face[1] + minCone : 0;
561a03d55ffSStefano Zampini       key.k = faceSize > 2 ? face[2] + minCone : 0;
562a03d55ffSStefano Zampini       key.l = faceSize > 3 ? face[3] + minCone : 0;
5639566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
564a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
565e9fa77a1SMatthew G. Knepley       if (missing) {
566591a860aSStefano Zampini         facesId[cntFaces] = fEnd;
567a03d55ffSStefano Zampini         PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++));
568412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
569a03d55ffSStefano Zampini       } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
570591a860aSStefano Zampini       cntFaces++;
5719a5b13a2SMatthew G Knepley     }
5726f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
57399836e0eSStefano Zampini   }
574412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
575412e9a14SMatthew G. Knepley   {
576412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
57799836e0eSStefano Zampini 
5789371c9d4SSatish Balay     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5799371c9d4SSatish Balay       if (faceTypeNum[ct]) ++numFT;
5809371c9d4SSatish Balay       faceTypeStart[ct] = 0;
5819371c9d4SSatish Balay     }
582412e9a14SMatthew G. Knepley     if (numFT > 1) {
583a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLClear(faceTable));
584412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
585412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
586591a860aSStefano Zampini       for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
587412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
588412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
589ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
590412e9a14SMatthew G. Knepley         PetscInt              numFaces, cf, foff = 0;
59199836e0eSStefano Zampini 
5929566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
5939566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
5946f5c9017SMatthew G. Knepley         if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5959566063dSJacob Faibussowitsch           PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5966f5c9017SMatthew G. Knepley         } else {
5976f5c9017SMatthew G. Knepley           numFaces = 0;
5986f5c9017SMatthew G. Knepley         }
599412e9a14SMatthew G. Knepley         for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
600412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
601412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
602412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
60399836e0eSStefano Zampini           PetscHashIJKLKey     key;
60499836e0eSStefano Zampini           PetscHashIter        iter;
60599836e0eSStefano Zampini           PetscBool            missing;
60699836e0eSStefano Zampini 
607a03d55ffSStefano Zampini           key.i = face[0] + minCone;
608a03d55ffSStefano Zampini           key.j = faceSize > 1 ? face[1] + minCone : 0;
609a03d55ffSStefano Zampini           key.k = faceSize > 2 ? face[2] + minCone : 0;
610a03d55ffSStefano Zampini           key.l = faceSize > 3 ? face[3] + minCone : 0;
6119566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
612a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
613591a860aSStefano Zampini           if (missing) {
614591a860aSStefano Zampini             facesId[cntFaces] = faceTypeStart[faceType];
615a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
616a03d55ffSStefano Zampini           } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
617591a860aSStefano Zampini           cntFaces++;
61899836e0eSStefano Zampini         }
6196f5c9017SMatthew G. Knepley         if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
62099836e0eSStefano Zampini       }
621412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
6221dca8a05SBarry 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]);
6239a5b13a2SMatthew G Knepley       }
6249a5b13a2SMatthew G Knepley     }
625412e9a14SMatthew G. Knepley   }
626a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLDestroy(&faceTable));
627591a860aSStefano Zampini 
628412e9a14SMatthew G. Knepley   /* Add new points, always at the end of the numbering */
6299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
6309566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
6319a5b13a2SMatthew G Knepley   /* Set cone sizes */
632412e9a14SMatthew G. Knepley   /*   Must create the celltype label here so that we do not automatically try to compute the types */
6339566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
6349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
6359a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
636412e9a14SMatthew G. Knepley     DMPolytopeType ct;
637412e9a14SMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, p;
6389f074e33SMatthew G Knepley 
639412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
641412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
6429566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
6439566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, p, coneSize));
6449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
6459566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, p, ct));
6469f074e33SMatthew G Knepley     }
6479f074e33SMatthew G Knepley   }
648591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
649591a860aSStefano Zampini     const PetscInt       *cone, *faceSizes;
650412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
651412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
652591a860aSStefano Zampini     PetscInt              numFaces, cf;
653412e9a14SMatthew G. Knepley 
6549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
6566f5c9017SMatthew G. Knepley     if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
6576f5c9017SMatthew G. Knepley       PetscCall(DMPlexSetCellType(idm, c, ct));
6586f5c9017SMatthew G. Knepley       PetscCall(DMPlexSetConeSize(idm, c, 2));
6596f5c9017SMatthew G. Knepley       continue;
6606f5c9017SMatthew G. Knepley     }
661591a860aSStefano Zampini     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6629566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(idm, c, ct));
6639566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(idm, c, numFaces));
664591a860aSStefano Zampini     for (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));
675412e9a14SMatthew 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));
683412e9a14SMatthew G. Knepley     for (c = 0; c < csize; ++c) cones[c] = -1;
684412e9a14SMatthew G. Knepley   }
685412e9a14SMatthew G. Knepley   /* Set cones */
686412e9a14SMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
687412e9a14SMatthew G. Knepley     const PetscInt *cone;
688412e9a14SMatthew G. Knepley     PetscInt        pStart, pEnd, p;
689412e9a14SMatthew G. Knepley 
690412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
692412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
6939566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, p, &cone));
6949566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(idm, p, cone));
6959566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
6969566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeOrientation(idm, p, cone));
6979f074e33SMatthew G Knepley     }
6989a5b13a2SMatthew G Knepley   }
699591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
700412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
701412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
702ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
703412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
70499836e0eSStefano Zampini 
7059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
7069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
7076f5c9017SMatthew G. Knepley     if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
7086f5c9017SMatthew G. Knepley       PetscCall(DMPlexSetCone(idm, c, cone));
7096f5c9017SMatthew G. Knepley       PetscCall(DMPlexGetConeOrientation(dm, c, &cone));
7106f5c9017SMatthew G. Knepley       PetscCall(DMPlexSetConeOrientation(idm, c, cone));
7116f5c9017SMatthew G. Knepley       continue;
7126f5c9017SMatthew G. Knepley     }
7139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
714412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
715412e9a14SMatthew G. Knepley       DMPolytopeType  faceType = faceTypes[cf];
716412e9a14SMatthew G. Knepley       const PetscInt  faceSize = faceSizes[cf];
717591a860aSStefano Zampini       const PetscInt  f        = facesId[cntFaces];
718412e9a14SMatthew G. Knepley       const PetscInt *face     = &faces[foff];
719412e9a14SMatthew G. Knepley       const PetscInt *fcone;
7209f074e33SMatthew G Knepley 
7219566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertCone(idm, c, cf, f));
7229566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(idm, f, &fcone));
7239566063dSJacob Faibussowitsch       if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
724412e9a14SMatthew G. Knepley       {
725412e9a14SMatthew G. Knepley         const PetscInt *cone;
726412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
727a74221b0SStefano Zampini 
7289566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
7299566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &cone));
73063a3b9bcSJacob 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);
731d89e6e46SMatthew G. Knepley         /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
7329566063dSJacob Faibussowitsch         PetscCall(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt));
7339566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertConeOrientation(idm, c, cf, ornt));
73499836e0eSStefano Zampini       }
735591a860aSStefano Zampini       cntFaces++;
73699836e0eSStefano Zampini     }
7379566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
73899836e0eSStefano Zampini   }
739591a860aSStefano Zampini   PetscCall(PetscFree(facesId));
7409566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
7419566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
7423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7439f074e33SMatthew G Knepley }
7449f074e33SMatthew G Knepley 
745d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
746d71ae5a4SJacob Faibussowitsch {
747f80536cbSVaclav Hapla   PetscInt           nleaves;
748f80536cbSVaclav Hapla   PetscInt           nranks;
749a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks   = NULL;
750a0d42dbcSVaclav Hapla   const PetscInt    *roffset = NULL, *rmine = NULL, *rremote = NULL;
751f80536cbSVaclav Hapla   PetscInt           n, o, r;
752f80536cbSVaclav Hapla 
753f80536cbSVaclav Hapla   PetscFunctionBegin;
7549566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
755f80536cbSVaclav Hapla   nleaves = roffset[nranks];
7569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
757f80536cbSVaclav Hapla   for (r = 0; r < nranks; r++) {
758f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
759f80536cbSVaclav Hapla        - to unify order with the other side */
760f80536cbSVaclav Hapla     o = roffset[r];
761f80536cbSVaclav Hapla     n = roffset[r + 1] - o;
7629566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7639566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7649566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
765f80536cbSVaclav Hapla   }
7663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
767f80536cbSVaclav Hapla }
768f80536cbSVaclav Hapla 
769d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
770d71ae5a4SJacob Faibussowitsch {
771d89e6e46SMatthew G. Knepley   PetscSF            sf;
772d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
773d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
774d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
775d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
776d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
777d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
778d89e6e46SMatthew G. Knepley   PetscInt(*roots)[4], (*leaves)[4], mainCone[4];
779d89e6e46SMatthew G. Knepley   PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4];
7802e745bdaSMatthew G. Knepley   MPI_Comm    comm;
78127d0e99aSVaclav Hapla   PetscMPIInt rank, size;
7822e745bdaSMatthew G. Knepley   PetscInt    debug = 0;
7832e745bdaSMatthew G. Knepley 
7842e745bdaSMatthew G. Knepley   PetscFunctionBegin;
7859566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
7869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
7889566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
7899566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
790d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
7919566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
7923ba16761SJacob Faibussowitsch   if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS);
7939566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
7949566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
795d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
796d89e6e46SMatthew G. Knepley     PetscInt coneSize;
7979566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
798d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
799d89e6e46SMatthew G. Knepley   }
80063a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
8019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
8029e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
803d89e6e46SMatthew G. Knepley     const PetscInt *cone;
804d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
805d89e6e46SMatthew G. Knepley 
8069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8079566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
808d89e6e46SMatthew G. Knepley     /* Ignore vertices */
80927d0e99aSVaclav Hapla     if (coneSize < 2) {
810d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
81127d0e99aSVaclav Hapla         roots[p][c]      = -1;
81227d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
81327d0e99aSVaclav Hapla       }
81427d0e99aSVaclav Hapla       continue;
81527d0e99aSVaclav Hapla     }
8162e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
817d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
8189566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
8198a650c75SVaclav Hapla       if (ind0 < 0) {
8208a650c75SVaclav Hapla         roots[p][c]      = cone[c];
8218a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
822c8148b97SVaclav Hapla       } else {
8238a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
8248a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
8258a650c75SVaclav Hapla       }
8262e745bdaSMatthew G. Knepley     }
827d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
828d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
829d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
830d89e6e46SMatthew G. Knepley     }
8312e745bdaSMatthew G. Knepley   }
8329e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
833d89e6e46SMatthew G. Knepley     PetscInt c;
834d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
8358ccb905dSVaclav Hapla       leaves[p][c]      = -2;
8368ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
8378ccb905dSVaclav Hapla     }
838c8148b97SVaclav Hapla   }
8399566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8409566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
8419566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8429566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
843d89e6e46SMatthew G. Knepley   if (debug) {
8449566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
845c5853193SPierre Jolivet     if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
846d89e6e46SMatthew G. Knepley   }
8479566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8489e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
849d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
850d89e6e46SMatthew G. Knepley     const PetscInt *cone;
851d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
852d89e6e46SMatthew G. Knepley 
853d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
8549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
8559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
857d89e6e46SMatthew G. Knepley     if (debug) {
8589371c9d4SSatish 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]));
859d89e6e46SMatthew G. Knepley     }
8609371c9d4SSatish 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]) {
861d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
862d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
863d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
864d89e6e46SMatthew G. Knepley 
86527d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
866d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
8679dddd249SSatish Balay           mainCone[c] = leaves[p][c];
86827d0e99aSVaclav Hapla           continue;
86927d0e99aSVaclav Hapla         }
870f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
871f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
8729566063dSJacob Faibussowitsch         PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r));
87363a3b9bcSJacob 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]);
8741dca8a05SBarry 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]);
875f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
876d89e6e46SMatthew G. Knepley         rS = roffset[r];
877d89e6e46SMatthew G. Knepley         rN = roffset[r + 1] - rS;
8789566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
87963a3b9bcSJacob 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]);
880f80536cbSVaclav Hapla         /* Get the corresponding local point */
8815f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
882f80536cbSVaclav Hapla       }
88363a3b9bcSJacob 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]));
88427d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
8859566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
8869566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
8879566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
88823aaf07bSVaclav Hapla   }
88927d0e99aSVaclav Hapla   if (debug) {
8909566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
8919566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
8922e745bdaSMatthew G. Knepley   }
8939566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
8949566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
8959566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
8963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8972e745bdaSMatthew G. Knepley }
8982e745bdaSMatthew G. Knepley 
899d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
900d71ae5a4SJacob Faibussowitsch {
9012e72742cSMatthew G. Knepley   PetscInt    idx;
9022e72742cSMatthew G. Knepley   PetscMPIInt rank;
9032e72742cSMatthew G. Knepley   PetscBool   flg;
9047bffde78SMichael Lange 
9057bffde78SMichael Lange   PetscFunctionBegin;
9069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9073ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9099566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
91063a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
9119566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9132e72742cSMatthew G. Knepley }
9142e72742cSMatthew G. Knepley 
915d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
916d71ae5a4SJacob Faibussowitsch {
9172e72742cSMatthew G. Knepley   PetscInt    idx;
9182e72742cSMatthew G. Knepley   PetscMPIInt rank;
9192e72742cSMatthew G. Knepley   PetscBool   flg;
9202e72742cSMatthew G. Knepley 
9212e72742cSMatthew G. Knepley   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));
9262e72742cSMatthew G. Knepley   if (idxname) {
92763a3b9bcSJacob 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));
9282e72742cSMatthew G. Knepley   } else {
92963a3b9bcSJacob 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));
9302e72742cSMatthew G. Knepley   }
9319566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9332e72742cSMatthew G. Knepley }
9342e72742cSMatthew G. Knepley 
935d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
936d71ae5a4SJacob Faibussowitsch {
9373be36e83SMatthew G. Knepley   PetscSF         sf;
9383be36e83SMatthew G. Knepley   const PetscInt *locals;
9393be36e83SMatthew G. Knepley   PetscMPIInt     rank;
9402e72742cSMatthew G. Knepley 
9412e72742cSMatthew G. Knepley   PetscFunctionBegin;
9429566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9439566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9449566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
9455f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9462e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
9472e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
9482e72742cSMatthew G. Knepley   } else {
9492e72742cSMatthew G. Knepley     PetscHashIJKey key;
9503be36e83SMatthew G. Knepley     PetscInt       l;
9512e72742cSMatthew G. Knepley 
9522e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9532e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9549566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
9553be36e83SMatthew G. Knepley     if (l >= 0) {
9563be36e83SMatthew G. Knepley       *localPoint = locals[l];
9575f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
9582e72742cSMatthew G. Knepley   }
9593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9602e72742cSMatthew G. Knepley }
9612e72742cSMatthew G. Knepley 
962d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
963d71ae5a4SJacob Faibussowitsch {
9643be36e83SMatthew G. Knepley   PetscSF            sf;
9653be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9663be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9673be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9683be36e83SMatthew G. Knepley   PetscMPIInt        rank;
9693be36e83SMatthew G. Knepley 
9703be36e83SMatthew G. Knepley   PetscFunctionBegin;
9715f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9729566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9739566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9749566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
9753be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
9769566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9779566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9783be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
9799566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
9809371c9d4SSatish Balay   if (l < 0) {
9819371c9d4SSatish Balay     if (mapFailed) *mapFailed = PETSC_TRUE;
9829371c9d4SSatish Balay   } else *remotePoint = remotes[l];
9833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9843be36e83SMatthew G. Knepley owned:
9853be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
9863be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
9873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9883be36e83SMatthew G. Knepley }
9893be36e83SMatthew G. Knepley 
990d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
991d71ae5a4SJacob Faibussowitsch {
9923be36e83SMatthew G. Knepley   PetscSF         sf;
9933be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
9943be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
9953be36e83SMatthew G. Knepley 
9963be36e83SMatthew G. Knepley   PetscFunctionBegin;
9973be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
9989566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9999566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
10003ba16761SJacob Faibussowitsch   if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS);
10019566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
10029371c9d4SSatish Balay   if (idx >= 0) {
10039371c9d4SSatish Balay     *isShared = PETSC_TRUE;
10043ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
10059371c9d4SSatish Balay   }
10069566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
10079566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
10083be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
10093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10103be36e83SMatthew G. Knepley }
10113be36e83SMatthew G. Knepley 
1012d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
1013d71ae5a4SJacob Faibussowitsch {
10143be36e83SMatthew G. Knepley   const PetscInt *cone;
10153be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10163be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
10173be36e83SMatthew G. Knepley 
10183be36e83SMatthew G. Knepley   PetscFunctionBegin;
10199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10213be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10223be36e83SMatthew G. Knepley     PetscBool pointShared;
10233be36e83SMatthew G. Knepley 
10249566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
10253be36e83SMatthew G. Knepley     cShared = (PetscBool)(cShared && pointShared);
10263be36e83SMatthew G. Knepley   }
10273be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
10283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10293be36e83SMatthew G. Knepley }
10303be36e83SMatthew G. Knepley 
1031d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
1032d71ae5a4SJacob Faibussowitsch {
10333be36e83SMatthew G. Knepley   const PetscInt *cone;
10343be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10353be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
10363be36e83SMatthew G. Knepley 
10373be36e83SMatthew G. Knepley   PetscFunctionBegin;
10389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10403be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10413be36e83SMatthew G. Knepley     PetscSFNode rcp;
10425f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
10433be36e83SMatthew G. Knepley 
10449566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
10455f80ce2aSJacob Faibussowitsch     if (mapFailed) {
10463be36e83SMatthew G. Knepley       cmin = missing;
10473be36e83SMatthew G. Knepley     } else {
10483be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10493be36e83SMatthew G. Knepley     }
10503be36e83SMatthew G. Knepley   }
10513be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
10523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10533be36e83SMatthew G. Knepley }
10543be36e83SMatthew G. Knepley 
10553be36e83SMatthew G. Knepley /*
10563be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10573be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10583be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10593be36e83SMatthew G. Knepley */
1060d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
1061d71ae5a4SJacob Faibussowitsch {
10623be36e83SMatthew G. Knepley   MPI_Comm        comm;
10633be36e83SMatthew G. Knepley   const PetscInt *support;
1064cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10653be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10663be36e83SMatthew G. Knepley 
10673be36e83SMatthew G. Knepley   PetscFunctionBegin;
10689566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
10699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
10719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
10729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
1073cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight + 1) {
1074cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
107563a3b9bcSJacob 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));
10763ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1077cf4dc471SVaclav Hapla   }
10789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
10799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
10809566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
10813be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
10823be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
10833be36e83SMatthew G. Knepley     const PetscInt *cone;
10843be36e83SMatthew G. Knepley     PetscSFNode     cpmin = {-1, -1}, rp = {-1, -1};
10853be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
10863be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
10873be36e83SMatthew G. Knepley     PetscHashIJKey  key;
10883be36e83SMatthew G. Knepley 
10893be36e83SMatthew G. Knepley     /* Only add point once */
109063a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
10913be36e83SMatthew G. Knepley     key.i = p;
10923be36e83SMatthew G. Knepley     key.j = face;
10939566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
10943be36e83SMatthew G. Knepley     if (f >= 0) continue;
10959566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
10969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
10979566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
10983be36e83SMatthew G. Knepley     if (debug) {
109963a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
110063a3b9bcSJacob 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));
11013be36e83SMatthew G. Knepley     }
11023be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
11039566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
11043be36e83SMatthew G. Knepley       if (candidates) {
110563a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
11069566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11079566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
11083be36e83SMatthew G. Knepley         candidates[off + idx].rank    = -1;
11093be36e83SMatthew G. Knepley         candidates[off + idx++].index = coneSize - 1;
11103be36e83SMatthew G. Knepley         candidates[off + idx].rank    = rank;
11113be36e83SMatthew G. Knepley         candidates[off + idx++].index = face;
11123be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
11133be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
11143be36e83SMatthew G. Knepley 
11153be36e83SMatthew G. Knepley           if (cp == p) continue;
11169566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
111763a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
11183be36e83SMatthew G. Knepley           ++idx;
11193be36e83SMatthew G. Knepley         }
11209566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
11213be36e83SMatthew G. Knepley       } else {
11223be36e83SMatthew G. Knepley         /* Add cone size to section */
112363a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
11249566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11259566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
11269566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
11273be36e83SMatthew G. Knepley       }
11283be36e83SMatthew G. Knepley     }
11293be36e83SMatthew G. Knepley   }
11303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11313be36e83SMatthew G. Knepley }
11323be36e83SMatthew G. Knepley 
11332e72742cSMatthew G. Knepley /*@
113420f4b53cSBarry Smith   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation
11352e72742cSMatthew G. Knepley 
113620f4b53cSBarry Smith   Collective
11372e72742cSMatthew G. Knepley 
11382e72742cSMatthew G. Knepley   Input Parameters:
113920f4b53cSBarry Smith + dm      - The interpolated `DMPLEX`
114020f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points
11412e72742cSMatthew G. Knepley 
1142f0cfc026SVaclav Hapla   Level: developer
11432e72742cSMatthew G. Knepley 
114420f4b53cSBarry Smith   Note:
114520f4b53cSBarry 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`
11462e72742cSMatthew G. Knepley 
114720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()`
11482e72742cSMatthew G. Knepley @*/
1149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
1150d71ae5a4SJacob Faibussowitsch {
11513be36e83SMatthew G. Knepley   MPI_Comm           comm;
11523be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
11533be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
11543be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11553be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11562e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11572e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11583be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11593be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11603be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1161f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11622e72742cSMatthew G. Knepley 
11632e72742cSMatthew G. Knepley   PetscFunctionBegin;
1164f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1165064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11669566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
11673ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
11683be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
11699566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
11709566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11719566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
117328b400f6SJacob Faibussowitsch   PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
11749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
11759566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
11769566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
11779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
11783be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
11799566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
118008401ef6SPierre Jolivet   PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
11819566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
11823be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
11833be36e83SMatthew G. Knepley     PetscHashIJKey key;
11842e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
11852e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
11869566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
11877bffde78SMichael Lange   }
118866aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
11899566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
11909566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
11919566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
11923be36e83SMatthew G. Knepley   /*
11933be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
11943be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
11953be36e83SMatthew G. Knepley   \begin{itemize}
11963be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
11973be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
11983be36e83SMatthew G. Knepley   \end{itemize}
11993be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
12003be36e83SMatthew 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
12013be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
12023be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
12033be36e83SMatthew G. Knepley   */
12043be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
12053be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
1206da81f932SPierre Jolivet        The array holds candidate shared faces, each face is referred to by the leaf point */
12079566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
12089566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
12097bffde78SMichael Lange   {
12103be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
12112e72742cSMatthew G. Knepley 
12129566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
12133be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12143be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
12152e72742cSMatthew G. Knepley 
121663a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
12179566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
12182e72742cSMatthew G. Knepley     }
12199566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
12209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
12219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
12229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
12233be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12243be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
12252e72742cSMatthew G. Knepley 
122663a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
12279566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
12282e72742cSMatthew G. Knepley     }
12299566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
12309566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
12317bffde78SMichael Lange   }
12329566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
12339566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
12349566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
12353be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
12362e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
12377bffde78SMichael Lange   {
12387bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
12397bffde78SMichael Lange     PetscInt *remoteOffsets;
12402e72742cSMatthew G. Knepley 
12419566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
12429566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
12439566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
12449566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
12459566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
12469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
12479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
12489566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12499566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12509566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
12519566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
12529566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
12532e72742cSMatthew G. Knepley 
12549566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12559566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12569566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12577bffde78SMichael Lange   }
12583be36e83SMatthew 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 */
12597bffde78SMichael Lange   {
1260a03d55ffSStefano Zampini     PetscHMapIJKLRemote faceTable;
12613be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12623be36e83SMatthew G. Knepley 
1263a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteCreate(&faceTable));
12642e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12653be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12662e72742cSMatthew G. Knepley       PetscInt deg;
12673be36e83SMatthew G. Knepley 
12682e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
12692e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
12702e72742cSMatthew G. Knepley 
12719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
12729566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
12733be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12742e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12753be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
12763be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
12773be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx + 1];
12783be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
12793be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
12803be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
12812e72742cSMatthew G. Knepley           const PetscInt        *join = NULL;
1282a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
12833be36e83SMatthew G. Knepley           PetscHashIter          iter;
12845f80ce2aSJacob Faibussowitsch           PetscBool              missing, mapToLocalPointFailed = PETSC_FALSE;
12852e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
12862e72742cSMatthew G. Knepley 
12879371c9d4SSatish Balay           if (debug)
12889371c9d4SSatish 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,
12899371c9d4SSatish Balay                                               rface.index, r, idx, d, Np));
129063a3b9bcSJacob 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);
12913be36e83SMatthew G. Knepley           fcp0.rank  = rank;
12923be36e83SMatthew G. Knepley           fcp0.index = r;
12933be36e83SMatthew G. Knepley           d += Np;
12943be36e83SMatthew G. Knepley           /* Put remote face in hash table */
12953be36e83SMatthew G. Knepley           key.i = fcp0;
12963be36e83SMatthew G. Knepley           key.j = fcone[0];
12973be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
12983be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
12999566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
1300a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
13013be36e83SMatthew G. Knepley           if (missing) {
130263a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1303a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13043be36e83SMatthew G. Knepley           } else {
13053be36e83SMatthew G. Knepley             PetscSFNode oface;
13063be36e83SMatthew G. Knepley 
1307a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13083be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
130963a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1310a03d55ffSStefano Zampini               PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13113be36e83SMatthew G. Knepley             }
13123be36e83SMatthew G. Knepley           }
13133be36e83SMatthew G. Knepley           /* Check for local face */
13142e72742cSMatthew G. Knepley           points[0] = r;
13153be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
13169566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
13175f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
131863a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
13197bffde78SMichael Lange           }
13205f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
13219566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
13227bffde78SMichael Lange           if (joinSize == 1) {
13233be36e83SMatthew G. Knepley             PetscSFNode lface;
13243be36e83SMatthew G. Knepley             PetscSFNode oface;
13253be36e83SMatthew G. Knepley 
13263be36e83SMatthew G. Knepley             /* Always replace with local face */
13273be36e83SMatthew G. Knepley             lface.rank  = rank;
13283be36e83SMatthew G. Knepley             lface.index = join[0];
1329a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13309371c9d4SSatish Balay             if (debug)
13319371c9d4SSatish 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));
1332a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface));
13337bffde78SMichael Lange           }
13349566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
13353be36e83SMatthew G. Knepley         }
13363be36e83SMatthew G. Knepley       }
13373be36e83SMatthew G. Knepley       /* Put back faces for this root */
13383be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
13393be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
13403be36e83SMatthew G. Knepley 
13419566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
13429566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
13433be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
13443be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13453be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
13463be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13473be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13483be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
13493be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
1350a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
13513be36e83SMatthew G. Knepley           PetscHashIter          iter;
13523be36e83SMatthew G. Knepley           PetscBool              missing;
13533be36e83SMatthew G. Knepley 
135463a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
135563a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13563be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13573be36e83SMatthew G. Knepley           fcp0.index = r;
13583be36e83SMatthew G. Knepley           d += Np;
13593be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13603be36e83SMatthew G. Knepley           key.i = fcp0;
13613be36e83SMatthew G. Knepley           key.j = fcone[0];
13623be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13633be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13649566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13659371c9d4SSatish Balay           if (debug)
13669371c9d4SSatish 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,
13679371c9d4SSatish 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));
1368a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
136963a3b9bcSJacob Faibussowitsch           PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1370a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
13717bffde78SMichael Lange         }
13727bffde78SMichael Lange       }
13737bffde78SMichael Lange     }
13749566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
1375a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable));
13767bffde78SMichael Lange   }
13773be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
13787bffde78SMichael Lange   {
13797bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
13807bffde78SMichael Lange     PetscSFNode *remotePointsNew;
13812e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
13823be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
13832e72742cSMatthew G. Knepley 
13843be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
13859566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
13869566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
13879566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
13889566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
13899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
13909566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
13913be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
13929566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13939566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13949566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
13959566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
13969566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
13979566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
13989566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
13993be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
14003be36e83SMatthew 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 */
14019566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
14023be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
14033be36e83SMatthew G. Knepley       PetscInt dof, off, d;
14042e72742cSMatthew G. Knepley 
140563a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
14069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
14079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
14082e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
14093be36e83SMatthew G. Knepley         if (claims[off + d].rank >= 0) {
14103be36e83SMatthew G. Knepley           const PetscInt  faceInd = off + d;
14113be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off + d].index;
14122e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
14132e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
14142e72742cSMatthew G. Knepley 
141563a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
14163be36e83SMatthew G. Knepley           points[0] = r;
141763a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
14183be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
14199566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
142063a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c + 1]));
14212e72742cSMatthew G. Knepley           }
14229566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
14232e72742cSMatthew G. Knepley           if (joinSize == 1) {
14243be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
142563a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
14263be36e83SMatthew G. Knepley             } else {
142763a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
14289566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
14292e72742cSMatthew G. Knepley             }
14303be36e83SMatthew G. Knepley           } else {
14319566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
14323be36e83SMatthew G. Knepley           }
14339566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
14343be36e83SMatthew G. Knepley         } else {
143563a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
14363be36e83SMatthew G. Knepley           d += claims[off + d].index + 1;
14377bffde78SMichael Lange         }
14387bffde78SMichael Lange       }
14393be36e83SMatthew G. Knepley     }
14409566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
14413be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
14429566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
14439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14449566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
14459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
14463be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
14473be36e83SMatthew G. Knepley       localPointsNew[l]        = localPoints[l];
14483be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
14493be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
14507bffde78SMichael Lange     }
14513be36e83SMatthew G. Knepley     p = Nl;
14529566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
14533be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
1454*8e3a54c0SPierre Jolivet     PetscCall(PetscSortInt(NlNew, PetscSafePointerPlusOffset(localPointsNew, Nl)));
14553be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14563be36e83SMatthew G. Knepley       PetscInt off;
14579566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
14581dca8a05SBarry 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);
14593be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14607bffde78SMichael Lange     }
14619566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
14629566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14639566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
14649566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
14659566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1466d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
14679566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
14689566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
14697bffde78SMichael Lange   }
14709566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
14719566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
14729566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
14739566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
14749566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
14759566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
14769566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
14779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
14783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14797bffde78SMichael Lange }
14807bffde78SMichael Lange 
1481248eb259SVaclav Hapla /*@
148280330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
148380330477SMatthew G. Knepley 
148420f4b53cSBarry Smith   Collective
148580330477SMatthew G. Knepley 
148620f4b53cSBarry Smith   Input Parameter:
148720f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices
148880330477SMatthew G. Knepley 
148980330477SMatthew G. Knepley   Output Parameter:
149020f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object
149180330477SMatthew G. Knepley 
149280330477SMatthew G. Knepley   Level: intermediate
149380330477SMatthew G. Knepley 
149420f4b53cSBarry Smith   Note:
14957fb59074SVaclav Hapla   Labels and coordinates are copied.
149643eeeb2dSStefano Zampini 
149760225df5SJacob Faibussowitsch   Developer Notes:
149820f4b53cSBarry Smith   It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`.
14999ade3219SVaclav Hapla 
150020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
150180330477SMatthew G. Knepley @*/
1502d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
1503d71ae5a4SJacob Faibussowitsch {
1504a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
15059a5b13a2SMatthew G Knepley   DM                     idm, odm = dm;
15067bffde78SMichael Lange   PetscSF                sfPoint;
15072e1b13c2SMatthew G. Knepley   PetscInt               depth, dim, d;
150810a67516SMatthew G. Knepley   const char            *name;
1509b325530aSVaclav Hapla   PetscBool              flg = PETSC_TRUE;
15109f074e33SMatthew G Knepley 
15119f074e33SMatthew G Knepley   PetscFunctionBegin;
151210a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15134f572ea9SToby Isaac   PetscAssertPointer(dmInt, 2);
15149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
15159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
15169566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
15179566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
151808401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1519827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
15209566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
152176b791aaSMatthew G. Knepley     idm = dm;
1522b21b8912SMatthew G. Knepley   } else {
15239a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
15246f5c9017SMatthew G. Knepley       const char *prefix;
15256f5c9017SMatthew G. Knepley 
15269a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
15279566063dSJacob Faibussowitsch       PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
15289566063dSJacob Faibussowitsch       PetscCall(DMSetType(idm, DMPLEX));
15299566063dSJacob Faibussowitsch       PetscCall(DMSetDimension(idm, dim));
15306f5c9017SMatthew G. Knepley       PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
15316f5c9017SMatthew G. Knepley       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
15327bffde78SMichael Lange       if (depth > 0) {
15339566063dSJacob Faibussowitsch         PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
15349566063dSJacob Faibussowitsch         PetscCall(DMGetPointSF(odm, &sfPoint));
1535d7d32a9aSMatthew G. Knepley         if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
153694488200SVaclav Hapla         {
15373be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
153894488200SVaclav Hapla           PetscInt nroots;
15399566063dSJacob Faibussowitsch           PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
15409566063dSJacob Faibussowitsch           if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
154194488200SVaclav Hapla         }
15427bffde78SMichael Lange       }
15439566063dSJacob Faibussowitsch       if (odm != dm) PetscCall(DMDestroy(&odm));
15449a5b13a2SMatthew G Knepley       odm = idm;
15459f074e33SMatthew G Knepley     }
15469566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
15479566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)idm, name));
15489566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
15499566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
15509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
15519566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
155284699f70SSatish Balay   }
1553827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1554827c4036SVaclav Hapla   {
1555d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)idm->data;
1556827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1557827c4036SVaclav Hapla   }
15585de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
15599a5b13a2SMatthew G Knepley   *dmInt = idm;
15609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
15613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15629f074e33SMatthew G Knepley }
156307b0a1fcSMatthew G Knepley 
156480330477SMatthew G. Knepley /*@
156580330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
156680330477SMatthew G. Knepley 
156720f4b53cSBarry Smith   Collective
156880330477SMatthew G. Knepley 
156980330477SMatthew G. Knepley   Input Parameter:
157020f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates
157180330477SMatthew G. Knepley 
157280330477SMatthew G. Knepley   Output Parameter:
157320f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates
157480330477SMatthew G. Knepley 
157580330477SMatthew G. Knepley   Level: intermediate
157680330477SMatthew G. Knepley 
15776f5c9017SMatthew G. Knepley   Notes:
157820f4b53cSBarry Smith   This is typically used when adding pieces other than vertices to a mesh
157980330477SMatthew G. Knepley 
15806f5c9017SMatthew G. Knepley   This function does not copy localized coordinates.
15816f5c9017SMatthew G. Knepley 
158220f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
158380330477SMatthew G. Knepley @*/
1584d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
1585d71ae5a4SJacob Faibussowitsch {
158607b0a1fcSMatthew G Knepley   Vec          coordinatesA, coordinatesB;
158743eeeb2dSStefano Zampini   VecType      vtype;
158807b0a1fcSMatthew G Knepley   PetscSection coordSectionA, coordSectionB;
158907b0a1fcSMatthew G Knepley   PetscScalar *coordsA, *coordsB;
15900bedd6beSMatthew G. Knepley   PetscInt     spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
159190a8aa44SJed Brown   PetscInt     cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
159207b0a1fcSMatthew G Knepley 
159307b0a1fcSMatthew G Knepley   PetscFunctionBegin;
159443eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
159543eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
15963ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
15979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
15989566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
15999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
16009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
160163a3b9bcSJacob 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);
160261a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
160361a622f3SMatthew G. Knepley   {
160461a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
160561a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
160661a622f3SMatthew G. Knepley     PetscObject        objA, objB;
160761a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
160861a622f3SMatthew G. Knepley     const PetscScalar *constants;
160961a622f3SMatthew G. Knepley     PetscInt           cdim, Nc;
161061a622f3SMatthew G. Knepley 
16119566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
16129566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
16139566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
16149566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
16159566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
16169566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
161761a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
16189566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
16199566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
16209566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
16219566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
16229566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
16239566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
16249566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
16259566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
162661a622f3SMatthew G. Knepley     }
162761a622f3SMatthew G. Knepley   }
16289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
16299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
16309566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
16319566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
16323ba16761SJacob Faibussowitsch   if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS);
16339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
16343ba16761SJacob Faibussowitsch   if (!Nf) PetscFunctionReturn(PETSC_SUCCESS);
163563a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1636df26b574SMatthew G. Knepley   if (!coordSectionB) {
1637df26b574SMatthew G. Knepley     PetscInt dim;
1638df26b574SMatthew G. Knepley 
16399566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
16409566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
16419566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
16429566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1643df26b574SMatthew G. Knepley   }
16449566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
16459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
16469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
16479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
164843eeeb2dSStefano Zampini   cS = vStartB;
164943eeeb2dSStefano Zampini   cE = vEndB;
16509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
165107b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
16529566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
16539566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
165407b0a1fcSMatthew G Knepley   }
16559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
16569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
16579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
16589566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
16599566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
16609566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
16619566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
16629566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
16639566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
16649566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
16659566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
16669566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
166707b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB - vStartB; ++v) {
166843eeeb2dSStefano Zampini     PetscInt offA, offB;
166943eeeb2dSStefano Zampini 
16709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
16719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1672ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
167343eeeb2dSStefano Zampini   }
16749566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
16759566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
16769566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
16779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
16783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
167907b0a1fcSMatthew G Knepley }
16805c386225SMatthew G. Knepley 
16814e3744c5SMatthew G. Knepley /*@
16824e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
16834e3744c5SMatthew G. Knepley 
168420f4b53cSBarry Smith   Collective
16854e3744c5SMatthew G. Knepley 
16864e3744c5SMatthew G. Knepley   Input Parameter:
168720f4b53cSBarry Smith . dm - The complete `DMPLEX` object
16884e3744c5SMatthew G. Knepley 
16894e3744c5SMatthew G. Knepley   Output Parameter:
169020f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices
16914e3744c5SMatthew G. Knepley 
16924e3744c5SMatthew G. Knepley   Level: intermediate
16934e3744c5SMatthew G. Knepley 
169420f4b53cSBarry Smith   Note:
169595452b02SPatrick Sanan   It does not copy over the coordinates.
169643eeeb2dSStefano Zampini 
169760225df5SJacob Faibussowitsch   Developer Notes:
169820f4b53cSBarry Smith   Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
16999ade3219SVaclav Hapla 
170020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
17014e3744c5SMatthew G. Knepley @*/
1702d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
1703d71ae5a4SJacob Faibussowitsch {
1704827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
17054e3744c5SMatthew G. Knepley   DM                     udm;
1706412e9a14SMatthew G. Knepley   PetscInt               dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
17074e3744c5SMatthew G. Knepley 
17084e3744c5SMatthew G. Knepley   PetscFunctionBegin;
170943eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17104f572ea9SToby Isaac   PetscAssertPointer(dmUnint, 2);
1711172ee266SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0));
17129566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
17139566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
171408401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1715827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1716827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
17179566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1718595d4abbSMatthew G. Knepley     *dmUnint = dm;
17193ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
17204e3744c5SMatthew G. Knepley   }
17219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
17229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17239566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
17249566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
17259566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
17269566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
17274e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1728595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17294e3744c5SMatthew G. Knepley 
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17314e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17324e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17334e3744c5SMatthew G. Knepley 
17344e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
17354e3744c5SMatthew G. Knepley     }
17369566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17379566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1738595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
17394e3744c5SMatthew G. Knepley   }
17409566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
17419566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
17424e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1743595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17444e3744c5SMatthew G. Knepley 
17459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17464e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17474e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17484e3744c5SMatthew G. Knepley 
17494e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
17504e3744c5SMatthew G. Knepley     }
17519566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17529566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
17534e3744c5SMatthew G. Knepley   }
17549566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
17559566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
17569566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
17575c7de58aSMatthew G. Knepley   /* Reduce SF */
17585c7de58aSMatthew G. Knepley   {
17595c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
17605c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
17615c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
17625c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
17635c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
176422fd0ad9SVaclav Hapla     PetscInt           numRoots, numLeaves, l;
17655c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
17665c7de58aSMatthew G. Knepley 
17675c7de58aSMatthew G. Knepley     /* Get original SF information */
17689566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
1769d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
17709566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
17719566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
177222fd0ad9SVaclav Hapla     if (numRoots >= 0) {
17735c7de58aSMatthew G. Knepley       /* Allocate space for cells and vertices */
177422fd0ad9SVaclav Hapla       for (l = 0; l < numLeaves; ++l) {
177522fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
177622fd0ad9SVaclav Hapla 
177722fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
177822fd0ad9SVaclav Hapla       }
17795c7de58aSMatthew G. Knepley       /* Fill in leaves */
17809566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
17819566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
17825c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
178322fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
178422fd0ad9SVaclav Hapla 
178522fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
178622fd0ad9SVaclav Hapla           localPointsUn[n]        = p;
17875c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
17885c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
17895c7de58aSMatthew G. Knepley           ++n;
17905c7de58aSMatthew G. Knepley         }
17915c7de58aSMatthew G. Knepley       }
179263a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
179322fd0ad9SVaclav Hapla       PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
17945c7de58aSMatthew G. Knepley     }
17955c7de58aSMatthew G. Knepley   }
1796827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1797827c4036SVaclav Hapla   {
1798d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)udm->data;
1799827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1800827c4036SVaclav Hapla   }
18015de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1802d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
18034e3744c5SMatthew G. Knepley   *dmUnint = udm;
1804172ee266SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0));
18053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18064e3744c5SMatthew G. Knepley }
1807a7748839SVaclav Hapla 
1808d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1809d71ae5a4SJacob Faibussowitsch {
1810a7748839SVaclav Hapla   PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1811a7748839SVaclav Hapla   MPI_Comm comm;
1812a7748839SVaclav Hapla 
1813a7748839SVaclav Hapla   PetscFunctionBegin;
18149566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
18159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
18169566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1817a7748839SVaclav Hapla 
1818a7748839SVaclav Hapla   if (depth == dim) {
1819a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1820a7748839SVaclav Hapla     if (!dim) goto finish;
1821a7748839SVaclav Hapla 
1822a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
18239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1824a7748839SVaclav Hapla     for (p = pStart; p < pEnd; p++) {
18259566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1826a7748839SVaclav Hapla       if (coneSize) {
1827a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1828a7748839SVaclav Hapla         goto finish;
1829a7748839SVaclav Hapla       }
1830a7748839SVaclav Hapla     }
1831a7748839SVaclav Hapla 
1832a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1833a7748839SVaclav Hapla     for (h = 0; h < dim; h++) {
18349566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1835a7748839SVaclav Hapla       for (p = pStart; p < pEnd; p++) {
18369566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1837a7748839SVaclav Hapla         if (!coneSize) {
1838a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1839a7748839SVaclav Hapla           goto finish;
1840a7748839SVaclav Hapla         }
1841a7748839SVaclav Hapla       }
1842a7748839SVaclav Hapla     }
1843a7748839SVaclav Hapla   } else if (depth == 1) {
1844a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1845a7748839SVaclav Hapla   } else {
1846a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1847a7748839SVaclav Hapla   }
1848a7748839SVaclav Hapla finish:
18493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1850a7748839SVaclav Hapla }
1851a7748839SVaclav Hapla 
1852a7748839SVaclav Hapla /*@
185320f4b53cSBarry Smith   DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated.
1854a7748839SVaclav Hapla 
1855a7748839SVaclav Hapla   Not Collective
1856a7748839SVaclav Hapla 
1857a7748839SVaclav Hapla   Input Parameter:
185820f4b53cSBarry Smith . dm - The `DMPLEX` object
1859a7748839SVaclav Hapla 
1860a7748839SVaclav Hapla   Output Parameter:
186120f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1862a7748839SVaclav Hapla 
1863a7748839SVaclav Hapla   Level: intermediate
1864a7748839SVaclav Hapla 
1865a7748839SVaclav Hapla   Notes:
186620f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective
18679ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
186820f4b53cSBarry Smith   However, `DMPlexInterpolate()` guarantees the result is the same on all.
18699ade3219SVaclav Hapla 
187020f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`.
1871a7748839SVaclav Hapla 
18729ade3219SVaclav Hapla   Developer Notes:
187320f4b53cSBarry Smith   Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`.
18749ade3219SVaclav Hapla 
187520f4b53cSBarry Smith   If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called.
18769ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
187720f4b53cSBarry Smith   `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`.
18789ade3219SVaclav Hapla 
187920f4b53cSBarry Smith   If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated.
18809ade3219SVaclav Hapla 
188120f4b53cSBarry Smith   `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`,
188220f4b53cSBarry Smith   and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
18839ade3219SVaclav Hapla 
188420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1885a7748839SVaclav Hapla @*/
1886d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1887d71ae5a4SJacob Faibussowitsch {
1888a7748839SVaclav Hapla   DM_Plex *plex = (DM_Plex *)dm->data;
1889a7748839SVaclav Hapla 
1890a7748839SVaclav Hapla   PetscFunctionBegin;
1891a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18924f572ea9SToby Isaac   PetscAssertPointer(interpolated, 2);
1893a7748839SVaclav Hapla   if (plex->interpolated < 0) {
18949566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
189576bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
1896a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1897a7748839SVaclav Hapla 
18989566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
1899c282ed06SStefano 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]);
1900a7748839SVaclav Hapla   }
1901a7748839SVaclav Hapla   *interpolated = plex->interpolated;
19023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1903a7748839SVaclav Hapla }
1904a7748839SVaclav Hapla 
1905a7748839SVaclav Hapla /*@
190620f4b53cSBarry Smith   DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner).
1907a7748839SVaclav Hapla 
19082666ff3cSVaclav Hapla   Collective
1909a7748839SVaclav Hapla 
1910a7748839SVaclav Hapla   Input Parameter:
191120f4b53cSBarry Smith . dm - The `DMPLEX` object
1912a7748839SVaclav Hapla 
1913a7748839SVaclav Hapla   Output Parameter:
191420f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1915a7748839SVaclav Hapla 
1916a7748839SVaclav Hapla   Level: intermediate
1917a7748839SVaclav Hapla 
1918a7748839SVaclav Hapla   Notes:
191920f4b53cSBarry Smith   Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks.
19209ade3219SVaclav Hapla 
192120f4b53cSBarry Smith   This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks.
19229ade3219SVaclav Hapla 
19239ade3219SVaclav Hapla   Developer Notes:
192420f4b53cSBarry Smith   Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`.
19259ade3219SVaclav Hapla 
192620f4b53cSBarry Smith   If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated.
192720f4b53cSBarry Smith   `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
192820f4b53cSBarry Smith   if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`,
19299ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
19309ade3219SVaclav Hapla 
193120f4b53cSBarry Smith   If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective.
1932a7748839SVaclav Hapla 
193320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
1934a7748839SVaclav Hapla @*/
1935d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1936d71ae5a4SJacob Faibussowitsch {
1937a7748839SVaclav Hapla   DM_Plex  *plex  = (DM_Plex *)dm->data;
1938a7748839SVaclav Hapla   PetscBool debug = PETSC_FALSE;
1939a7748839SVaclav Hapla 
1940a7748839SVaclav Hapla   PetscFunctionBegin;
1941a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19424f572ea9SToby Isaac   PetscAssertPointer(interpolated, 2);
19439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
1944a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1945a7748839SVaclav Hapla     DMPlexInterpolatedFlag min, max;
1946a7748839SVaclav Hapla     MPI_Comm               comm;
1947a7748839SVaclav Hapla 
19489566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19499566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
1950712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
1951712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
1952a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1953a7748839SVaclav Hapla     if (debug) {
1954a7748839SVaclav Hapla       PetscMPIInt rank;
1955a7748839SVaclav Hapla 
19569566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
19579566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
19589566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
1959a7748839SVaclav Hapla     }
1960a7748839SVaclav Hapla   }
1961a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
19623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1963a7748839SVaclav Hapla }
1964