xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision ed896b6766bdc77fa6f7a777723eb06026bbe3e8)
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);
56ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(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;
75ba2698f1SMatthew G. Knepley     break;
76ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
77412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 2;
78412e9a14SMatthew G. Knepley     if (faceTypes) {
799371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
809371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
81412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
82412e9a14SMatthew G. Knepley     }
83412e9a14SMatthew G. Knepley     if (faceSizes) {
849371c9d4SSatish Balay       sizesTmp[0] = 1;
859371c9d4SSatish Balay       sizesTmp[1] = 1;
86412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
87412e9a14SMatthew G. Knepley     }
88c49d9212SMatthew G. Knepley     if (faces) {
899371c9d4SSatish Balay       facesTmp[0] = cone[0];
909371c9d4SSatish Balay       facesTmp[1] = cone[1];
91c49d9212SMatthew G. Knepley       *faces      = facesTmp;
92c49d9212SMatthew G. Knepley     }
93412e9a14SMatthew G. Knepley     break;
94412e9a14SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
95c49d9212SMatthew G. Knepley     if (numFaces) *numFaces = 2;
96412e9a14SMatthew G. Knepley     if (faceTypes) {
979371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
989371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
99412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
100412e9a14SMatthew G. Knepley     }
101412e9a14SMatthew G. Knepley     if (faceSizes) {
1029371c9d4SSatish Balay       sizesTmp[0] = 1;
1039371c9d4SSatish Balay       sizesTmp[1] = 1;
104412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
105412e9a14SMatthew G. Knepley     }
106412e9a14SMatthew G. Knepley     if (faces) {
1079371c9d4SSatish Balay       facesTmp[0] = cone[0];
1089371c9d4SSatish Balay       facesTmp[1] = cone[1];
109412e9a14SMatthew G. Knepley       *faces      = facesTmp;
110412e9a14SMatthew G. Knepley     }
111c49d9212SMatthew G. Knepley     break;
112ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
113412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 3;
114412e9a14SMatthew G. Knepley     if (faceTypes) {
1159371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1169371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1179371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
118412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
119412e9a14SMatthew G. Knepley     }
120412e9a14SMatthew G. Knepley     if (faceSizes) {
1219371c9d4SSatish Balay       sizesTmp[0] = 2;
1229371c9d4SSatish Balay       sizesTmp[1] = 2;
1239371c9d4SSatish Balay       sizesTmp[2] = 2;
124412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
125412e9a14SMatthew G. Knepley     }
1269a5b13a2SMatthew G Knepley     if (faces) {
1279371c9d4SSatish Balay       facesTmp[0] = cone[0];
1289371c9d4SSatish Balay       facesTmp[1] = cone[1];
1299371c9d4SSatish Balay       facesTmp[2] = cone[1];
1309371c9d4SSatish Balay       facesTmp[3] = cone[2];
1319371c9d4SSatish Balay       facesTmp[4] = cone[2];
1329371c9d4SSatish Balay       facesTmp[5] = cone[0];
1339a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1349a5b13a2SMatthew G Knepley     }
1359f074e33SMatthew G Knepley     break;
136ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
1379a5b13a2SMatthew G Knepley     /* Vertices follow right hand rule */
138412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
139412e9a14SMatthew G. Knepley     if (faceTypes) {
1409371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1419371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1429371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
1439371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEGMENT;
144412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
145412e9a14SMatthew G. Knepley     }
146412e9a14SMatthew G. Knepley     if (faceSizes) {
1479371c9d4SSatish Balay       sizesTmp[0] = 2;
1489371c9d4SSatish Balay       sizesTmp[1] = 2;
1499371c9d4SSatish Balay       sizesTmp[2] = 2;
1509371c9d4SSatish Balay       sizesTmp[3] = 2;
151412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
152412e9a14SMatthew G. Knepley     }
1539a5b13a2SMatthew G Knepley     if (faces) {
1549371c9d4SSatish Balay       facesTmp[0] = cone[0];
1559371c9d4SSatish Balay       facesTmp[1] = cone[1];
1569371c9d4SSatish Balay       facesTmp[2] = cone[1];
1579371c9d4SSatish Balay       facesTmp[3] = cone[2];
1589371c9d4SSatish Balay       facesTmp[4] = cone[2];
1599371c9d4SSatish Balay       facesTmp[5] = cone[3];
1609371c9d4SSatish Balay       facesTmp[6] = cone[3];
1619371c9d4SSatish Balay       facesTmp[7] = cone[0];
1629a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1639a5b13a2SMatthew G Knepley     }
164412e9a14SMatthew G. Knepley     break;
165412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
1669a5b13a2SMatthew G Knepley     if (numFaces) *numFaces = 4;
167412e9a14SMatthew G. Knepley     if (faceTypes) {
1689371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1699371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1709371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1719371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
172412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
173412e9a14SMatthew G. Knepley     }
174412e9a14SMatthew G. Knepley     if (faceSizes) {
1759371c9d4SSatish Balay       sizesTmp[0] = 2;
1769371c9d4SSatish Balay       sizesTmp[1] = 2;
1779371c9d4SSatish Balay       sizesTmp[2] = 2;
1789371c9d4SSatish Balay       sizesTmp[3] = 2;
179412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
180412e9a14SMatthew G. Knepley     }
181412e9a14SMatthew G. Knepley     if (faces) {
1829371c9d4SSatish Balay       facesTmp[0] = cone[0];
1839371c9d4SSatish Balay       facesTmp[1] = cone[1];
1849371c9d4SSatish Balay       facesTmp[2] = cone[2];
1859371c9d4SSatish Balay       facesTmp[3] = cone[3];
1869371c9d4SSatish Balay       facesTmp[4] = cone[0];
1879371c9d4SSatish Balay       facesTmp[5] = cone[2];
1889371c9d4SSatish Balay       facesTmp[6] = cone[1];
1899371c9d4SSatish Balay       facesTmp[7] = cone[3];
190412e9a14SMatthew G. Knepley       *faces      = facesTmp;
191412e9a14SMatthew G. Knepley     }
1929f074e33SMatthew G Knepley     break;
193ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
1942e1b13c2SMatthew G. Knepley     /* Vertices of first face follow right hand rule and normal points away from last vertex */
195412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
196412e9a14SMatthew G. Knepley     if (faceTypes) {
1979371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
1989371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
1999371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
2009371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
201412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
202412e9a14SMatthew G. Knepley     }
203412e9a14SMatthew G. Knepley     if (faceSizes) {
2049371c9d4SSatish Balay       sizesTmp[0] = 3;
2059371c9d4SSatish Balay       sizesTmp[1] = 3;
2069371c9d4SSatish Balay       sizesTmp[2] = 3;
2079371c9d4SSatish Balay       sizesTmp[3] = 3;
208412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
209412e9a14SMatthew G. Knepley     }
2109a5b13a2SMatthew G Knepley     if (faces) {
2119371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2129371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2139371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2149371c9d4SSatish Balay       facesTmp[3]  = cone[0];
2159371c9d4SSatish Balay       facesTmp[4]  = cone[3];
2169371c9d4SSatish Balay       facesTmp[5]  = cone[1];
2179371c9d4SSatish Balay       facesTmp[6]  = cone[0];
2189371c9d4SSatish Balay       facesTmp[7]  = cone[2];
2199371c9d4SSatish Balay       facesTmp[8]  = cone[3];
2209371c9d4SSatish Balay       facesTmp[9]  = cone[2];
2219371c9d4SSatish Balay       facesTmp[10] = cone[1];
2229371c9d4SSatish Balay       facesTmp[11] = cone[3];
2239a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2249a5b13a2SMatthew G Knepley     }
2259a5b13a2SMatthew G Knepley     break;
226ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
227e368ef20SMatthew G. Knepley     /*  7--------6
228e368ef20SMatthew G. Knepley          /|       /|
229e368ef20SMatthew G. Knepley         / |      / |
230e368ef20SMatthew G. Knepley        4--------5  |
231e368ef20SMatthew G. Knepley        |  |     |  |
232e368ef20SMatthew G. Knepley        |  |     |  |
233e368ef20SMatthew G. Knepley        |  1--------2
234e368ef20SMatthew G. Knepley        | /      | /
235e368ef20SMatthew G. Knepley        |/       |/
236e368ef20SMatthew G. Knepley        0--------3
237e368ef20SMatthew G. Knepley        */
238412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
239412e9a14SMatthew G. Knepley     if (faceTypes) {
2409371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
2419371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
2429371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2439371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2449371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
2459371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
246412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
247412e9a14SMatthew G. Knepley     }
248412e9a14SMatthew G. Knepley     if (faceSizes) {
2499371c9d4SSatish Balay       sizesTmp[0] = 4;
2509371c9d4SSatish Balay       sizesTmp[1] = 4;
2519371c9d4SSatish Balay       sizesTmp[2] = 4;
2529371c9d4SSatish Balay       sizesTmp[3] = 4;
2539371c9d4SSatish Balay       sizesTmp[4] = 4;
2549371c9d4SSatish Balay       sizesTmp[5] = 4;
255412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
256412e9a14SMatthew G. Knepley     }
2579a5b13a2SMatthew G Knepley     if (faces) {
2589371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2599371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2609371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2619371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
2629371c9d4SSatish Balay       facesTmp[4]  = cone[4];
2639371c9d4SSatish Balay       facesTmp[5]  = cone[5];
2649371c9d4SSatish Balay       facesTmp[6]  = cone[6];
2659371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
2669371c9d4SSatish Balay       facesTmp[8]  = cone[0];
2679371c9d4SSatish Balay       facesTmp[9]  = cone[3];
2689371c9d4SSatish Balay       facesTmp[10] = cone[5];
2699371c9d4SSatish Balay       facesTmp[11] = cone[4]; /* Front */
2709371c9d4SSatish Balay       facesTmp[12] = cone[2];
2719371c9d4SSatish Balay       facesTmp[13] = cone[1];
2729371c9d4SSatish Balay       facesTmp[14] = cone[7];
2739371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Back */
2749371c9d4SSatish Balay       facesTmp[16] = cone[3];
2759371c9d4SSatish Balay       facesTmp[17] = cone[2];
2769371c9d4SSatish Balay       facesTmp[18] = cone[6];
2779371c9d4SSatish Balay       facesTmp[19] = cone[5]; /* Right */
2789371c9d4SSatish Balay       facesTmp[20] = cone[0];
2799371c9d4SSatish Balay       facesTmp[21] = cone[4];
2809371c9d4SSatish Balay       facesTmp[22] = cone[7];
2819371c9d4SSatish Balay       facesTmp[23] = cone[1]; /* Left */
2829a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2839a5b13a2SMatthew G Knepley     }
28499836e0eSStefano Zampini     break;
285ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM:
286412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
287412e9a14SMatthew G. Knepley     if (faceTypes) {
2889371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2899371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2909371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2919371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2929371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
293412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
294412e9a14SMatthew G. Knepley     }
295412e9a14SMatthew G. Knepley     if (faceSizes) {
2969371c9d4SSatish Balay       sizesTmp[0] = 3;
2979371c9d4SSatish Balay       sizesTmp[1] = 3;
2989371c9d4SSatish Balay       sizesTmp[2] = 4;
2999371c9d4SSatish Balay       sizesTmp[3] = 4;
3009371c9d4SSatish Balay       sizesTmp[4] = 4;
301412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
302412e9a14SMatthew G. Knepley     }
303ba2698f1SMatthew G. Knepley     if (faces) {
3049371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3059371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3069371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3079371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3089371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3099371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3109371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3119371c9d4SSatish Balay       facesTmp[7]  = cone[2];
3129371c9d4SSatish Balay       facesTmp[8]  = cone[4];
3139371c9d4SSatish Balay       facesTmp[9]  = cone[3]; /* Back left */
3149371c9d4SSatish Balay       facesTmp[10] = cone[2];
3159371c9d4SSatish Balay       facesTmp[11] = cone[1];
3169371c9d4SSatish Balay       facesTmp[12] = cone[5];
3179371c9d4SSatish Balay       facesTmp[13] = cone[4]; /* Front */
3189371c9d4SSatish Balay       facesTmp[14] = cone[1];
3199371c9d4SSatish Balay       facesTmp[15] = cone[0];
3209371c9d4SSatish Balay       facesTmp[16] = cone[3];
3219371c9d4SSatish Balay       facesTmp[17] = cone[5]; /* Back right */
322ba2698f1SMatthew G. Knepley       *faces       = facesTmp;
32399836e0eSStefano Zampini     }
32499836e0eSStefano Zampini     break;
325ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
326412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
327412e9a14SMatthew G. Knepley     if (faceTypes) {
3289371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
3299371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
3309371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3319371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3329371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
333412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
334412e9a14SMatthew G. Knepley     }
335412e9a14SMatthew G. Knepley     if (faceSizes) {
3369371c9d4SSatish Balay       sizesTmp[0] = 3;
3379371c9d4SSatish Balay       sizesTmp[1] = 3;
3389371c9d4SSatish Balay       sizesTmp[2] = 4;
3399371c9d4SSatish Balay       sizesTmp[3] = 4;
3409371c9d4SSatish Balay       sizesTmp[4] = 4;
341412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
342412e9a14SMatthew G. Knepley     }
34399836e0eSStefano Zampini     if (faces) {
3449371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3459371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3469371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3479371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3489371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3499371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3509371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3519371c9d4SSatish Balay       facesTmp[7]  = cone[1];
3529371c9d4SSatish Balay       facesTmp[8]  = cone[3];
3539371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Back left */
3549371c9d4SSatish Balay       facesTmp[10] = cone[1];
3559371c9d4SSatish Balay       facesTmp[11] = cone[2];
3569371c9d4SSatish Balay       facesTmp[12] = cone[4];
3579371c9d4SSatish Balay       facesTmp[13] = cone[5]; /* Back right */
3589371c9d4SSatish Balay       facesTmp[14] = cone[2];
3599371c9d4SSatish Balay       facesTmp[15] = cone[0];
3609371c9d4SSatish Balay       facesTmp[16] = cone[5];
3619371c9d4SSatish Balay       facesTmp[17] = cone[3]; /* Front */
36299836e0eSStefano Zampini       *faces       = facesTmp;
36399836e0eSStefano Zampini     }
364412e9a14SMatthew G. Knepley     break;
365412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
366412e9a14SMatthew G. Knepley     /*  7--------6
367412e9a14SMatthew G. Knepley          /|       /|
368412e9a14SMatthew G. Knepley         / |      / |
369412e9a14SMatthew G. Knepley        4--------5  |
370412e9a14SMatthew G. Knepley        |  |     |  |
371412e9a14SMatthew G. Knepley        |  |     |  |
372412e9a14SMatthew G. Knepley        |  3--------2
373412e9a14SMatthew G. Knepley        | /      | /
374412e9a14SMatthew G. Knepley        |/       |/
375412e9a14SMatthew G. Knepley        0--------1
376412e9a14SMatthew G. Knepley        */
377412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
378412e9a14SMatthew G. Knepley     if (faceTypes) {
3799371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
3809371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
3819371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3829371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3839371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3849371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
385412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
386412e9a14SMatthew G. Knepley     }
387412e9a14SMatthew G. Knepley     if (faceSizes) {
3889371c9d4SSatish Balay       sizesTmp[0] = 4;
3899371c9d4SSatish Balay       sizesTmp[1] = 4;
3909371c9d4SSatish Balay       sizesTmp[2] = 4;
3919371c9d4SSatish Balay       sizesTmp[3] = 4;
3929371c9d4SSatish Balay       sizesTmp[4] = 4;
3939371c9d4SSatish Balay       sizesTmp[5] = 4;
394412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
395412e9a14SMatthew G. Knepley     }
396412e9a14SMatthew G. Knepley     if (faces) {
3979371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3989371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3999371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4009371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4019371c9d4SSatish Balay       facesTmp[4]  = cone[4];
4029371c9d4SSatish Balay       facesTmp[5]  = cone[5];
4039371c9d4SSatish Balay       facesTmp[6]  = cone[6];
4049371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
4059371c9d4SSatish Balay       facesTmp[8]  = cone[0];
4069371c9d4SSatish Balay       facesTmp[9]  = cone[1];
4079371c9d4SSatish Balay       facesTmp[10] = cone[4];
4089371c9d4SSatish Balay       facesTmp[11] = cone[5]; /* Front */
4099371c9d4SSatish Balay       facesTmp[12] = cone[1];
4109371c9d4SSatish Balay       facesTmp[13] = cone[2];
4119371c9d4SSatish Balay       facesTmp[14] = cone[5];
4129371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Right */
4139371c9d4SSatish Balay       facesTmp[16] = cone[2];
4149371c9d4SSatish Balay       facesTmp[17] = cone[3];
4159371c9d4SSatish Balay       facesTmp[18] = cone[6];
4169371c9d4SSatish Balay       facesTmp[19] = cone[7]; /* Back */
4179371c9d4SSatish Balay       facesTmp[20] = cone[3];
4189371c9d4SSatish Balay       facesTmp[21] = cone[0];
4199371c9d4SSatish Balay       facesTmp[22] = cone[7];
4209371c9d4SSatish Balay       facesTmp[23] = cone[4]; /* Left */
421412e9a14SMatthew G. Knepley       *faces       = facesTmp;
422412e9a14SMatthew G. Knepley     }
42399836e0eSStefano Zampini     break;
424da9060c4SMatthew G. Knepley   case DM_POLYTOPE_PYRAMID:
425da9060c4SMatthew G. Knepley     /*
426da9060c4SMatthew G. Knepley        4----
427da9060c4SMatthew G. Knepley        |\-\ \-----
428da9060c4SMatthew G. Knepley        | \ -\     \
429da9060c4SMatthew G. Knepley        |  1--\-----2
430da9060c4SMatthew G. Knepley        | /    \   /
431da9060c4SMatthew G. Knepley        |/      \ /
432da9060c4SMatthew G. Knepley        0--------3
433da9060c4SMatthew G. Knepley        */
434da9060c4SMatthew G. Knepley     if (numFaces) *numFaces = 5;
435da9060c4SMatthew G. Knepley     if (faceTypes) {
436da9060c4SMatthew G. Knepley       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
4379371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
4389371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
4399371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
4409371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_TRIANGLE;
441da9060c4SMatthew G. Knepley       *faceTypes  = typesTmp;
442da9060c4SMatthew G. Knepley     }
443da9060c4SMatthew G. Knepley     if (faceSizes) {
444da9060c4SMatthew G. Knepley       sizesTmp[0] = 4;
4459371c9d4SSatish Balay       sizesTmp[1] = 3;
4469371c9d4SSatish Balay       sizesTmp[2] = 3;
4479371c9d4SSatish Balay       sizesTmp[3] = 3;
4489371c9d4SSatish Balay       sizesTmp[4] = 3;
449da9060c4SMatthew G. Knepley       *faceSizes  = sizesTmp;
450da9060c4SMatthew G. Knepley     }
451da9060c4SMatthew G. Knepley     if (faces) {
4529371c9d4SSatish Balay       facesTmp[0]  = cone[0];
4539371c9d4SSatish Balay       facesTmp[1]  = cone[1];
4549371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4559371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4569371c9d4SSatish Balay       facesTmp[4]  = cone[0];
4579371c9d4SSatish Balay       facesTmp[5]  = cone[3];
4589371c9d4SSatish Balay       facesTmp[6]  = cone[4]; /* Front */
4599371c9d4SSatish Balay       facesTmp[7]  = cone[3];
4609371c9d4SSatish Balay       facesTmp[8]  = cone[2];
4619371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Right */
4629371c9d4SSatish Balay       facesTmp[10] = cone[2];
4639371c9d4SSatish Balay       facesTmp[11] = cone[1];
4649371c9d4SSatish Balay       facesTmp[12] = cone[4]; /* Back */
4659371c9d4SSatish Balay       facesTmp[13] = cone[1];
4669371c9d4SSatish Balay       facesTmp[14] = cone[0];
4679371c9d4SSatish Balay       facesTmp[15] = cone[4]; /* Left */
468da9060c4SMatthew G. Knepley       *faces       = facesTmp;
469da9060c4SMatthew G. Knepley     }
470da9060c4SMatthew G. Knepley     break;
471d71ae5a4SJacob Faibussowitsch   default:
472d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
47399836e0eSStefano Zampini   }
4743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47599836e0eSStefano Zampini }
47699836e0eSStefano Zampini 
477d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
478d71ae5a4SJacob Faibussowitsch {
47999836e0eSStefano Zampini   PetscFunctionBegin;
4809566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes));
481442f3b32SStefano Zampini   else if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes));
482442f3b32SStefano Zampini   else if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces));
483442f3b32SStefano Zampini   if (faceTypes) *faceTypes = NULL;
484442f3b32SStefano Zampini   if (faceSizes) *faceSizes = NULL;
485442f3b32SStefano Zampini   if (faces) *faces = NULL;
4863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48799836e0eSStefano Zampini }
48899836e0eSStefano Zampini 
4899a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
490d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
491d71ae5a4SJacob Faibussowitsch {
492412e9a14SMatthew G. Knepley   DMLabel       ctLabel;
493a03d55ffSStefano Zampini   PetscHMapIJKL faceTable;
494412e9a14SMatthew G. Knepley   PetscInt      faceTypeNum[DM_NUM_POLYTOPES];
4959318fe57SMatthew G. Knepley   PetscInt      depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd;
496a03d55ffSStefano Zampini   PetscInt      cntFaces, *facesId, minCone;
4979f074e33SMatthew G Knepley 
4989f074e33SMatthew G Knepley   PetscFunctionBegin;
4999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
500a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLCreate(&faceTable));
5019566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
5029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
503412e9a14SMatthew G. Knepley   /* Number new faces and save face vertices in hash table */
5049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
505412e9a14SMatthew G. Knepley   fEnd = fStart;
506591a860aSStefano Zampini 
507a03d55ffSStefano Zampini   minCone = PETSC_MAX_INT;
508591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
509591a860aSStefano Zampini     const PetscInt *cone;
510591a860aSStefano Zampini     DMPolytopeType  ct;
511*ed896b67SJose E. Roman     PetscInt        numFaces = 0, coneSize;
512591a860aSStefano Zampini 
513591a860aSStefano Zampini     PetscCall(DMPlexGetCellType(dm, c, &ct));
514591a860aSStefano Zampini     PetscCall(DMPlexGetCone(dm, c, &cone));
515a03d55ffSStefano Zampini     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
516a03d55ffSStefano Zampini     for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone);
517591a860aSStefano Zampini     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL));
518591a860aSStefano Zampini     cntFaces += numFaces;
519591a860aSStefano Zampini   }
520a03d55ffSStefano Zampini   // Encode so that we can use 0 as an excluded value, instead of PETSC_MAX_INT
521a03d55ffSStefano Zampini   minCone = -(minCone - 1);
522591a860aSStefano Zampini 
523591a860aSStefano Zampini   PetscCall(PetscMalloc1(cntFaces, &facesId));
524591a860aSStefano Zampini 
525591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
526412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
527412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
528ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
529412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
53099836e0eSStefano Zampini 
5319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
534412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
535412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
536412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
537412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
5389a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
539e8f14785SLisandro Dalcin       PetscHashIter        iter;
540e8f14785SLisandro Dalcin       PetscBool            missing;
5419f074e33SMatthew G Knepley 
5425f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
543a03d55ffSStefano Zampini       key.i = face[0] + minCone;
544a03d55ffSStefano Zampini       key.j = faceSize > 1 ? face[1] + minCone : 0;
545a03d55ffSStefano Zampini       key.k = faceSize > 2 ? face[2] + minCone : 0;
546a03d55ffSStefano Zampini       key.l = faceSize > 3 ? face[3] + minCone : 0;
5479566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
548a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
549e9fa77a1SMatthew G. Knepley       if (missing) {
550591a860aSStefano Zampini         facesId[cntFaces] = fEnd;
551a03d55ffSStefano Zampini         PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++));
552412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
553a03d55ffSStefano Zampini       } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
554591a860aSStefano Zampini       cntFaces++;
5559a5b13a2SMatthew G Knepley     }
5569566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
55799836e0eSStefano Zampini   }
558412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
559412e9a14SMatthew G. Knepley   {
560412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
56199836e0eSStefano Zampini 
5629371c9d4SSatish Balay     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5639371c9d4SSatish Balay       if (faceTypeNum[ct]) ++numFT;
5649371c9d4SSatish Balay       faceTypeStart[ct] = 0;
5659371c9d4SSatish Balay     }
566412e9a14SMatthew G. Knepley     if (numFT > 1) {
567a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLClear(faceTable));
568412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
569412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
570591a860aSStefano Zampini       for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
571412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
572412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
573ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
574412e9a14SMatthew G. Knepley         PetscInt              numFaces, cf, foff = 0;
57599836e0eSStefano Zampini 
5769566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
5779566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
5789566063dSJacob Faibussowitsch         PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
579412e9a14SMatthew G. Knepley         for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
580412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
581412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
582412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
58399836e0eSStefano Zampini           PetscHashIJKLKey     key;
58499836e0eSStefano Zampini           PetscHashIter        iter;
58599836e0eSStefano Zampini           PetscBool            missing;
58699836e0eSStefano Zampini 
587a03d55ffSStefano Zampini           key.i = face[0] + minCone;
588a03d55ffSStefano Zampini           key.j = faceSize > 1 ? face[1] + minCone : 0;
589a03d55ffSStefano Zampini           key.k = faceSize > 2 ? face[2] + minCone : 0;
590a03d55ffSStefano Zampini           key.l = faceSize > 3 ? face[3] + minCone : 0;
5919566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
592a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
593591a860aSStefano Zampini           if (missing) {
594591a860aSStefano Zampini             facesId[cntFaces] = faceTypeStart[faceType];
595a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
596a03d55ffSStefano Zampini           } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
597591a860aSStefano Zampini           cntFaces++;
59899836e0eSStefano Zampini         }
5999566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
60099836e0eSStefano Zampini       }
601412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
6021dca8a05SBarry 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]);
6039a5b13a2SMatthew G Knepley       }
6049a5b13a2SMatthew G Knepley     }
605412e9a14SMatthew G. Knepley   }
606a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLDestroy(&faceTable));
607591a860aSStefano Zampini 
608412e9a14SMatthew G. Knepley   /* Add new points, always at the end of the numbering */
6099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
6109566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
6119a5b13a2SMatthew G Knepley   /* Set cone sizes */
612412e9a14SMatthew G. Knepley   /*   Must create the celltype label here so that we do not automatically try to compute the types */
6139566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
6149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
6159a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
616412e9a14SMatthew G. Knepley     DMPolytopeType ct;
617412e9a14SMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, p;
6189f074e33SMatthew G Knepley 
619412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6209566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
621412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
6229566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
6239566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, p, coneSize));
6249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
6259566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, p, ct));
6269f074e33SMatthew G Knepley     }
6279f074e33SMatthew G Knepley   }
628591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
629591a860aSStefano Zampini     const PetscInt       *cone, *faceSizes;
630412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
631412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
632591a860aSStefano Zampini     PetscInt              numFaces, cf;
633412e9a14SMatthew G. Knepley 
6349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
636591a860aSStefano Zampini     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6379566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(idm, c, ct));
6389566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(idm, c, numFaces));
639591a860aSStefano Zampini     for (cf = 0; cf < numFaces; ++cf) {
640591a860aSStefano Zampini       const PetscInt f        = facesId[cntFaces];
641591a860aSStefano Zampini       DMPolytopeType faceType = faceTypes[cf];
642412e9a14SMatthew G. Knepley       const PetscInt faceSize = faceSizes[cf];
6439566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, f, faceSize));
6449566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, f, faceType));
645591a860aSStefano Zampini       cntFaces++;
646412e9a14SMatthew G. Knepley     }
647591a860aSStefano Zampini     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6489f074e33SMatthew G Knepley   }
6499566063dSJacob Faibussowitsch   PetscCall(DMSetUp(idm));
650412e9a14SMatthew G. Knepley   /* Initialize cones so we do not need the bash table to tell us that a cone has been set */
651412e9a14SMatthew G. Knepley   {
652412e9a14SMatthew G. Knepley     PetscSection cs;
653412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
6549a5b13a2SMatthew G Knepley 
6559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSection(idm, &cs));
6569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCones(idm, &cones));
6579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(cs, &csize));
658412e9a14SMatthew G. Knepley     for (c = 0; c < csize; ++c) cones[c] = -1;
659412e9a14SMatthew G. Knepley   }
660412e9a14SMatthew G. Knepley   /* Set cones */
661412e9a14SMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
662412e9a14SMatthew G. Knepley     const PetscInt *cone;
663412e9a14SMatthew G. Knepley     PetscInt        pStart, pEnd, p;
664412e9a14SMatthew G. Knepley 
665412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
667412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
6689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, p, &cone));
6699566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(idm, p, cone));
6709566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
6719566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeOrientation(idm, p, cone));
6729f074e33SMatthew G Knepley     }
6739a5b13a2SMatthew G Knepley   }
674591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
675412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
676412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
677ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
678412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
67999836e0eSStefano Zampini 
6809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
6829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
683412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
684412e9a14SMatthew G. Knepley       DMPolytopeType  faceType = faceTypes[cf];
685412e9a14SMatthew G. Knepley       const PetscInt  faceSize = faceSizes[cf];
686591a860aSStefano Zampini       const PetscInt  f        = facesId[cntFaces];
687412e9a14SMatthew G. Knepley       const PetscInt *face     = &faces[foff];
688412e9a14SMatthew G. Knepley       const PetscInt *fcone;
6899f074e33SMatthew G Knepley 
6909566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertCone(idm, c, cf, f));
6919566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(idm, f, &fcone));
6929566063dSJacob Faibussowitsch       if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
693412e9a14SMatthew G. Knepley       {
694412e9a14SMatthew G. Knepley         const PetscInt *cone;
695412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
696a74221b0SStefano Zampini 
6979566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
6989566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &cone));
69963a3b9bcSJacob 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);
700d89e6e46SMatthew G. Knepley         /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
7019566063dSJacob Faibussowitsch         PetscCall(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt));
7029566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertConeOrientation(idm, c, cf, ornt));
70399836e0eSStefano Zampini       }
704591a860aSStefano Zampini       cntFaces++;
70599836e0eSStefano Zampini     }
7069566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
70799836e0eSStefano Zampini   }
708591a860aSStefano Zampini   PetscCall(PetscFree(facesId));
7099566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
7109566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
7113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7129f074e33SMatthew G Knepley }
7139f074e33SMatthew G Knepley 
714d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
715d71ae5a4SJacob Faibussowitsch {
716f80536cbSVaclav Hapla   PetscInt           nleaves;
717f80536cbSVaclav Hapla   PetscInt           nranks;
718a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks   = NULL;
719a0d42dbcSVaclav Hapla   const PetscInt    *roffset = NULL, *rmine = NULL, *rremote = NULL;
720f80536cbSVaclav Hapla   PetscInt           n, o, r;
721f80536cbSVaclav Hapla 
722f80536cbSVaclav Hapla   PetscFunctionBegin;
7239566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
724f80536cbSVaclav Hapla   nleaves = roffset[nranks];
7259566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
726f80536cbSVaclav Hapla   for (r = 0; r < nranks; r++) {
727f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
728f80536cbSVaclav Hapla        - to unify order with the other side */
729f80536cbSVaclav Hapla     o = roffset[r];
730f80536cbSVaclav Hapla     n = roffset[r + 1] - o;
7319566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7329566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7339566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
734f80536cbSVaclav Hapla   }
7353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
736f80536cbSVaclav Hapla }
737f80536cbSVaclav Hapla 
738d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
739d71ae5a4SJacob Faibussowitsch {
740d89e6e46SMatthew G. Knepley   PetscSF            sf;
741d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
742d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
743d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
744d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
745d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
746d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
747d89e6e46SMatthew G. Knepley   PetscInt(*roots)[4], (*leaves)[4], mainCone[4];
748d89e6e46SMatthew G. Knepley   PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4];
7492e745bdaSMatthew G. Knepley   MPI_Comm    comm;
75027d0e99aSVaclav Hapla   PetscMPIInt rank, size;
7512e745bdaSMatthew G. Knepley   PetscInt    debug = 0;
7522e745bdaSMatthew G. Knepley 
7532e745bdaSMatthew G. Knepley   PetscFunctionBegin;
7549566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
7559566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7569566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
7579566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
7589566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
759d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
7609566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
7613ba16761SJacob Faibussowitsch   if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS);
7629566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
7639566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
764d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
765d89e6e46SMatthew G. Knepley     PetscInt coneSize;
7669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
767d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
768d89e6e46SMatthew G. Knepley   }
76963a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
7709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
7719e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
772d89e6e46SMatthew G. Knepley     const PetscInt *cone;
773d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
774d89e6e46SMatthew G. Knepley 
7759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
7769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
777d89e6e46SMatthew G. Knepley     /* Ignore vertices */
77827d0e99aSVaclav Hapla     if (coneSize < 2) {
779d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
78027d0e99aSVaclav Hapla         roots[p][c]      = -1;
78127d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
78227d0e99aSVaclav Hapla       }
78327d0e99aSVaclav Hapla       continue;
78427d0e99aSVaclav Hapla     }
7852e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
786d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
7879566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
7888a650c75SVaclav Hapla       if (ind0 < 0) {
7898a650c75SVaclav Hapla         roots[p][c]      = cone[c];
7908a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
791c8148b97SVaclav Hapla       } else {
7928a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
7938a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
7948a650c75SVaclav Hapla       }
7952e745bdaSMatthew G. Knepley     }
796d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
797d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
798d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
799d89e6e46SMatthew G. Knepley     }
8002e745bdaSMatthew G. Knepley   }
8019e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
802d89e6e46SMatthew G. Knepley     PetscInt c;
803d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
8048ccb905dSVaclav Hapla       leaves[p][c]      = -2;
8058ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
8068ccb905dSVaclav Hapla     }
807c8148b97SVaclav Hapla   }
8089566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8099566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
8109566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8119566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
812d89e6e46SMatthew G. Knepley   if (debug) {
8139566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
814c5853193SPierre Jolivet     if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
815d89e6e46SMatthew G. Knepley   }
8169566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8179e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
818d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
819d89e6e46SMatthew G. Knepley     const PetscInt *cone;
820d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
821d89e6e46SMatthew G. Knepley 
822d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
8239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
8249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
826d89e6e46SMatthew G. Knepley     if (debug) {
8279371c9d4SSatish 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]));
828d89e6e46SMatthew G. Knepley     }
8299371c9d4SSatish 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]) {
830d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
831d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
832d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
833d89e6e46SMatthew G. Knepley 
83427d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
835d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
8369dddd249SSatish Balay           mainCone[c] = leaves[p][c];
83727d0e99aSVaclav Hapla           continue;
83827d0e99aSVaclav Hapla         }
839f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
840f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
8419566063dSJacob Faibussowitsch         PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r));
84263a3b9bcSJacob 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]);
8431dca8a05SBarry 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]);
844f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
845d89e6e46SMatthew G. Knepley         rS = roffset[r];
846d89e6e46SMatthew G. Knepley         rN = roffset[r + 1] - rS;
8479566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
84863a3b9bcSJacob 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]);
849f80536cbSVaclav Hapla         /* Get the corresponding local point */
8505f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
851f80536cbSVaclav Hapla       }
85263a3b9bcSJacob 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]));
85327d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
8549566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
8559566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
8569566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
85723aaf07bSVaclav Hapla   }
85827d0e99aSVaclav Hapla   if (debug) {
8599566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
8609566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
8612e745bdaSMatthew G. Knepley   }
8629566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
8639566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
8649566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
8653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8662e745bdaSMatthew G. Knepley }
8672e745bdaSMatthew G. Knepley 
868d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
869d71ae5a4SJacob Faibussowitsch {
8702e72742cSMatthew G. Knepley   PetscInt    idx;
8712e72742cSMatthew G. Knepley   PetscMPIInt rank;
8722e72742cSMatthew G. Knepley   PetscBool   flg;
8737bffde78SMichael Lange 
8747bffde78SMichael Lange   PetscFunctionBegin;
8759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
8763ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
8779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8789566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
87963a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
8809566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
8813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8822e72742cSMatthew G. Knepley }
8832e72742cSMatthew G. Knepley 
884d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
885d71ae5a4SJacob Faibussowitsch {
8862e72742cSMatthew G. Knepley   PetscInt    idx;
8872e72742cSMatthew G. Knepley   PetscMPIInt rank;
8882e72742cSMatthew G. Knepley   PetscBool   flg;
8892e72742cSMatthew G. Knepley 
8902e72742cSMatthew G. Knepley   PetscFunctionBegin;
8919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
8923ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
8939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8949566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
8952e72742cSMatthew G. Knepley   if (idxname) {
89663a3b9bcSJacob 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));
8972e72742cSMatthew G. Knepley   } else {
89863a3b9bcSJacob 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));
8992e72742cSMatthew G. Knepley   }
9009566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9022e72742cSMatthew G. Knepley }
9032e72742cSMatthew G. Knepley 
904d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
905d71ae5a4SJacob Faibussowitsch {
9063be36e83SMatthew G. Knepley   PetscSF         sf;
9073be36e83SMatthew G. Knepley   const PetscInt *locals;
9083be36e83SMatthew G. Knepley   PetscMPIInt     rank;
9092e72742cSMatthew G. Knepley 
9102e72742cSMatthew G. Knepley   PetscFunctionBegin;
9119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9129566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9139566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
9145f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9152e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
9162e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
9172e72742cSMatthew G. Knepley   } else {
9182e72742cSMatthew G. Knepley     PetscHashIJKey key;
9193be36e83SMatthew G. Knepley     PetscInt       l;
9202e72742cSMatthew G. Knepley 
9212e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9222e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9239566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
9243be36e83SMatthew G. Knepley     if (l >= 0) {
9253be36e83SMatthew G. Knepley       *localPoint = locals[l];
9265f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
9272e72742cSMatthew G. Knepley   }
9283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9292e72742cSMatthew G. Knepley }
9302e72742cSMatthew G. Knepley 
931d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
932d71ae5a4SJacob Faibussowitsch {
9333be36e83SMatthew G. Knepley   PetscSF            sf;
9343be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9353be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9363be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9373be36e83SMatthew G. Knepley   PetscMPIInt        rank;
9383be36e83SMatthew G. Knepley 
9393be36e83SMatthew G. Knepley   PetscFunctionBegin;
9405f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9429566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9439566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
9443be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
9459566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9469566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9473be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
9489566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
9499371c9d4SSatish Balay   if (l < 0) {
9509371c9d4SSatish Balay     if (mapFailed) *mapFailed = PETSC_TRUE;
9519371c9d4SSatish Balay   } else *remotePoint = remotes[l];
9523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9533be36e83SMatthew G. Knepley owned:
9543be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
9553be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
9563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9573be36e83SMatthew G. Knepley }
9583be36e83SMatthew G. Knepley 
959d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
960d71ae5a4SJacob Faibussowitsch {
9613be36e83SMatthew G. Knepley   PetscSF         sf;
9623be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
9633be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
9643be36e83SMatthew G. Knepley 
9653be36e83SMatthew G. Knepley   PetscFunctionBegin;
9663be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
9679566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9689566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
9693ba16761SJacob Faibussowitsch   if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS);
9709566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
9719371c9d4SSatish Balay   if (idx >= 0) {
9729371c9d4SSatish Balay     *isShared = PETSC_TRUE;
9733ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9749371c9d4SSatish Balay   }
9759566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9769566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9773be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
9783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9793be36e83SMatthew G. Knepley }
9803be36e83SMatthew G. Knepley 
981d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
982d71ae5a4SJacob Faibussowitsch {
9833be36e83SMatthew G. Knepley   const PetscInt *cone;
9843be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9853be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
9863be36e83SMatthew G. Knepley 
9873be36e83SMatthew G. Knepley   PetscFunctionBegin;
9889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
9899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
9903be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
9913be36e83SMatthew G. Knepley     PetscBool pointShared;
9923be36e83SMatthew G. Knepley 
9939566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
9943be36e83SMatthew G. Knepley     cShared = (PetscBool)(cShared && pointShared);
9953be36e83SMatthew G. Knepley   }
9963be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
9973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9983be36e83SMatthew G. Knepley }
9993be36e83SMatthew G. Knepley 
1000d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
1001d71ae5a4SJacob Faibussowitsch {
10023be36e83SMatthew G. Knepley   const PetscInt *cone;
10033be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10043be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
10053be36e83SMatthew G. Knepley 
10063be36e83SMatthew G. Knepley   PetscFunctionBegin;
10079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10093be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10103be36e83SMatthew G. Knepley     PetscSFNode rcp;
10115f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
10123be36e83SMatthew G. Knepley 
10139566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
10145f80ce2aSJacob Faibussowitsch     if (mapFailed) {
10153be36e83SMatthew G. Knepley       cmin = missing;
10163be36e83SMatthew G. Knepley     } else {
10173be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10183be36e83SMatthew G. Knepley     }
10193be36e83SMatthew G. Knepley   }
10203be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
10213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10223be36e83SMatthew G. Knepley }
10233be36e83SMatthew G. Knepley 
10243be36e83SMatthew G. Knepley /*
10253be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10263be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10273be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10283be36e83SMatthew G. Knepley */
1029d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
1030d71ae5a4SJacob Faibussowitsch {
10313be36e83SMatthew G. Knepley   MPI_Comm        comm;
10323be36e83SMatthew G. Knepley   const PetscInt *support;
1033cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10343be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10353be36e83SMatthew G. Knepley 
10363be36e83SMatthew G. Knepley   PetscFunctionBegin;
10379566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
10389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
10409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
10419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
1042cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight + 1) {
1043cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
104463a3b9bcSJacob 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));
10453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1046cf4dc471SVaclav Hapla   }
10479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
10489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
10499566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
10503be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
10513be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
10523be36e83SMatthew G. Knepley     const PetscInt *cone;
10533be36e83SMatthew G. Knepley     PetscSFNode     cpmin = {-1, -1}, rp = {-1, -1};
10543be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
10553be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
10563be36e83SMatthew G. Knepley     PetscHashIJKey  key;
10573be36e83SMatthew G. Knepley 
10583be36e83SMatthew G. Knepley     /* Only add point once */
105963a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
10603be36e83SMatthew G. Knepley     key.i = p;
10613be36e83SMatthew G. Knepley     key.j = face;
10629566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
10633be36e83SMatthew G. Knepley     if (f >= 0) continue;
10649566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
10659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
10669566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
10673be36e83SMatthew G. Knepley     if (debug) {
106863a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
106963a3b9bcSJacob 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));
10703be36e83SMatthew G. Knepley     }
10713be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
10729566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
10733be36e83SMatthew G. Knepley       if (candidates) {
107463a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
10759566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
10769566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
10773be36e83SMatthew G. Knepley         candidates[off + idx].rank    = -1;
10783be36e83SMatthew G. Knepley         candidates[off + idx++].index = coneSize - 1;
10793be36e83SMatthew G. Knepley         candidates[off + idx].rank    = rank;
10803be36e83SMatthew G. Knepley         candidates[off + idx++].index = face;
10813be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
10823be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
10833be36e83SMatthew G. Knepley 
10843be36e83SMatthew G. Knepley           if (cp == p) continue;
10859566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
108663a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
10873be36e83SMatthew G. Knepley           ++idx;
10883be36e83SMatthew G. Knepley         }
10899566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
10903be36e83SMatthew G. Knepley       } else {
10913be36e83SMatthew G. Knepley         /* Add cone size to section */
109263a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
10939566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
10949566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
10959566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
10963be36e83SMatthew G. Knepley       }
10973be36e83SMatthew G. Knepley     }
10983be36e83SMatthew G. Knepley   }
10993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11003be36e83SMatthew G. Knepley }
11013be36e83SMatthew G. Knepley 
11022e72742cSMatthew G. Knepley /*@
110320f4b53cSBarry Smith   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation
11042e72742cSMatthew G. Knepley 
110520f4b53cSBarry Smith   Collective
11062e72742cSMatthew G. Knepley 
11072e72742cSMatthew G. Knepley   Input Parameters:
110820f4b53cSBarry Smith + dm      - The interpolated `DMPLEX`
110920f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points
11102e72742cSMatthew G. Knepley 
1111f0cfc026SVaclav Hapla   Level: developer
11122e72742cSMatthew G. Knepley 
111320f4b53cSBarry Smith    Note:
111420f4b53cSBarry 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`
11152e72742cSMatthew G. Knepley 
111620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()`
11172e72742cSMatthew G. Knepley @*/
1118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
1119d71ae5a4SJacob Faibussowitsch {
11203be36e83SMatthew G. Knepley   MPI_Comm           comm;
11213be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
11223be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
11233be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11243be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11252e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11262e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11273be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11283be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11293be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1130f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11312e72742cSMatthew G. Knepley 
11322e72742cSMatthew G. Knepley   PetscFunctionBegin;
1133f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1134064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11359566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
11363ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
11373be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
11389566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
11399566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
114228b400f6SJacob Faibussowitsch   PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
11439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
11449566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
11459566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
11469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
11473be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
11489566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
114908401ef6SPierre Jolivet   PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
11509566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
11513be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
11523be36e83SMatthew G. Knepley     PetscHashIJKey key;
11532e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
11542e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
11559566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
11567bffde78SMichael Lange   }
115766aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
11589566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
11599566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
11609566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
11613be36e83SMatthew G. Knepley   /*
11623be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
11633be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
11643be36e83SMatthew G. Knepley   \begin{itemize}
11653be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
11663be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
11673be36e83SMatthew G. Knepley   \end{itemize}
11683be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
11693be36e83SMatthew 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
11703be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
11713be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
11723be36e83SMatthew G. Knepley   */
11733be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
11743be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
1175da81f932SPierre Jolivet        The array holds candidate shared faces, each face is referred to by the leaf point */
11769566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
11779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
11787bffde78SMichael Lange   {
11793be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
11802e72742cSMatthew G. Knepley 
11819566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
11823be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11833be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11842e72742cSMatthew G. Knepley 
118563a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
11869566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
11872e72742cSMatthew G. Knepley     }
11889566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
11899566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
11909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
11919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
11923be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11933be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11942e72742cSMatthew G. Knepley 
119563a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
11969566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
11972e72742cSMatthew G. Knepley     }
11989566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
11999566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
12007bffde78SMichael Lange   }
12019566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
12029566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
12039566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
12043be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
12052e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
12067bffde78SMichael Lange   {
12077bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
12087bffde78SMichael Lange     PetscInt *remoteOffsets;
12092e72742cSMatthew G. Knepley 
12109566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
12119566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
12129566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
12139566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
12149566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
12159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
12169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
12179566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12189566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12199566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
12209566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
12219566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
12222e72742cSMatthew G. Knepley 
12239566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12249566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12259566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12267bffde78SMichael Lange   }
12273be36e83SMatthew 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 */
12287bffde78SMichael Lange   {
1229a03d55ffSStefano Zampini     PetscHMapIJKLRemote faceTable;
12303be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12313be36e83SMatthew G. Knepley 
1232a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteCreate(&faceTable));
12332e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12343be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12352e72742cSMatthew G. Knepley       PetscInt deg;
12363be36e83SMatthew G. Knepley 
12372e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
12382e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
12392e72742cSMatthew G. Knepley 
12409566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
12419566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
12423be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12432e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12443be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
12453be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
12463be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx + 1];
12473be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
12483be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
12493be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
12502e72742cSMatthew G. Knepley           const PetscInt        *join = NULL;
1251a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
12523be36e83SMatthew G. Knepley           PetscHashIter          iter;
12535f80ce2aSJacob Faibussowitsch           PetscBool              missing, mapToLocalPointFailed = PETSC_FALSE;
12542e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
12552e72742cSMatthew G. Knepley 
12569371c9d4SSatish Balay           if (debug)
12579371c9d4SSatish 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,
12589371c9d4SSatish Balay                                               rface.index, r, idx, d, Np));
125963a3b9bcSJacob 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);
12603be36e83SMatthew G. Knepley           fcp0.rank  = rank;
12613be36e83SMatthew G. Knepley           fcp0.index = r;
12623be36e83SMatthew G. Knepley           d += Np;
12633be36e83SMatthew G. Knepley           /* Put remote face in hash table */
12643be36e83SMatthew G. Knepley           key.i = fcp0;
12653be36e83SMatthew G. Knepley           key.j = fcone[0];
12663be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
12673be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
12689566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
1269a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
12703be36e83SMatthew G. Knepley           if (missing) {
127163a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1272a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
12733be36e83SMatthew G. Knepley           } else {
12743be36e83SMatthew G. Knepley             PetscSFNode oface;
12753be36e83SMatthew G. Knepley 
1276a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
12773be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
127863a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1279a03d55ffSStefano Zampini               PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
12803be36e83SMatthew G. Knepley             }
12813be36e83SMatthew G. Knepley           }
12823be36e83SMatthew G. Knepley           /* Check for local face */
12832e72742cSMatthew G. Knepley           points[0] = r;
12843be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
12859566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
12865f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
128763a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
12887bffde78SMichael Lange           }
12895f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
12909566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
12917bffde78SMichael Lange           if (joinSize == 1) {
12923be36e83SMatthew G. Knepley             PetscSFNode lface;
12933be36e83SMatthew G. Knepley             PetscSFNode oface;
12943be36e83SMatthew G. Knepley 
12953be36e83SMatthew G. Knepley             /* Always replace with local face */
12963be36e83SMatthew G. Knepley             lface.rank  = rank;
12973be36e83SMatthew G. Knepley             lface.index = join[0];
1298a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
12999371c9d4SSatish Balay             if (debug)
13009371c9d4SSatish 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));
1301a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface));
13027bffde78SMichael Lange           }
13039566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
13043be36e83SMatthew G. Knepley         }
13053be36e83SMatthew G. Knepley       }
13063be36e83SMatthew G. Knepley       /* Put back faces for this root */
13073be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
13083be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
13093be36e83SMatthew G. Knepley 
13109566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
13119566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
13123be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
13133be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13143be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
13153be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13163be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13173be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
13183be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
1319a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
13203be36e83SMatthew G. Knepley           PetscHashIter          iter;
13213be36e83SMatthew G. Knepley           PetscBool              missing;
13223be36e83SMatthew G. Knepley 
132363a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
132463a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13253be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13263be36e83SMatthew G. Knepley           fcp0.index = r;
13273be36e83SMatthew G. Knepley           d += Np;
13283be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13293be36e83SMatthew G. Knepley           key.i = fcp0;
13303be36e83SMatthew G. Knepley           key.j = fcone[0];
13313be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13323be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13339566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13349371c9d4SSatish Balay           if (debug)
13359371c9d4SSatish 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,
13369371c9d4SSatish 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));
1337a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
133863a3b9bcSJacob Faibussowitsch           PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1339a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
13407bffde78SMichael Lange         }
13417bffde78SMichael Lange       }
13427bffde78SMichael Lange     }
13439566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
1344a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable));
13457bffde78SMichael Lange   }
13463be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
13477bffde78SMichael Lange   {
13487bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
13497bffde78SMichael Lange     PetscSFNode *remotePointsNew;
13502e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
13513be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
13522e72742cSMatthew G. Knepley 
13533be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
13549566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
13559566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
13569566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
13579566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
13589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
13599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
13603be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
13619566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13629566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13639566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
13649566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
13659566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
13669566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
13679566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
13683be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
13693be36e83SMatthew 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 */
13709566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
13713be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
13723be36e83SMatthew G. Knepley       PetscInt dof, off, d;
13732e72742cSMatthew G. Knepley 
137463a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
13759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
13769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
13772e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
13783be36e83SMatthew G. Knepley         if (claims[off + d].rank >= 0) {
13793be36e83SMatthew G. Knepley           const PetscInt  faceInd = off + d;
13803be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off + d].index;
13812e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
13822e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
13832e72742cSMatthew G. Knepley 
138463a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
13853be36e83SMatthew G. Knepley           points[0] = r;
138663a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
13873be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
13889566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
138963a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c + 1]));
13902e72742cSMatthew G. Knepley           }
13919566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
13922e72742cSMatthew G. Knepley           if (joinSize == 1) {
13933be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
139463a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
13953be36e83SMatthew G. Knepley             } else {
139663a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
13979566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
13982e72742cSMatthew G. Knepley             }
13993be36e83SMatthew G. Knepley           } else {
14009566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
14013be36e83SMatthew G. Knepley           }
14029566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
14033be36e83SMatthew G. Knepley         } else {
140463a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
14053be36e83SMatthew G. Knepley           d += claims[off + d].index + 1;
14067bffde78SMichael Lange         }
14077bffde78SMichael Lange       }
14083be36e83SMatthew G. Knepley     }
14099566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
14103be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
14119566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
14129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14139566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
14149566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
14153be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
14163be36e83SMatthew G. Knepley       localPointsNew[l]        = localPoints[l];
14173be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
14183be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
14197bffde78SMichael Lange     }
14203be36e83SMatthew G. Knepley     p = Nl;
14219566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
14223be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
14239566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(NlNew, &localPointsNew[Nl]));
14243be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14253be36e83SMatthew G. Knepley       PetscInt off;
14269566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
14271dca8a05SBarry 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);
14283be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14297bffde78SMichael Lange     }
14309566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
14319566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14329566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
14339566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
14349566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1435d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
14369566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
14379566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
14387bffde78SMichael Lange   }
14399566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
14409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
14419566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
14429566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
14439566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
14449566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
14459566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
14469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
14473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14487bffde78SMichael Lange }
14497bffde78SMichael Lange 
1450248eb259SVaclav Hapla /*@
145180330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
145280330477SMatthew G. Knepley 
145320f4b53cSBarry Smith   Collective
145480330477SMatthew G. Knepley 
145520f4b53cSBarry Smith   Input Parameter:
145620f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices
145780330477SMatthew G. Knepley 
145880330477SMatthew G. Knepley   Output Parameter:
145920f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object
146080330477SMatthew G. Knepley 
146180330477SMatthew G. Knepley   Level: intermediate
146280330477SMatthew G. Knepley 
146320f4b53cSBarry Smith   Note:
14647fb59074SVaclav Hapla     Labels and coordinates are copied.
146543eeeb2dSStefano Zampini 
146620f4b53cSBarry Smith   Developer Note:
146720f4b53cSBarry Smith     It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`.
14689ade3219SVaclav Hapla 
146920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
147080330477SMatthew G. Knepley @*/
1471d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
1472d71ae5a4SJacob Faibussowitsch {
1473a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
14749a5b13a2SMatthew G Knepley   DM                     idm, odm = dm;
14757bffde78SMichael Lange   PetscSF                sfPoint;
14762e1b13c2SMatthew G. Knepley   PetscInt               depth, dim, d;
147710a67516SMatthew G. Knepley   const char            *name;
1478b325530aSVaclav Hapla   PetscBool              flg = PETSC_TRUE;
14799f074e33SMatthew G Knepley 
14809f074e33SMatthew G Knepley   PetscFunctionBegin;
148110a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
148210a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
14839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
14849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
14859566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
14869566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
148708401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1488827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
14899566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
149076b791aaSMatthew G. Knepley     idm = dm;
1491b21b8912SMatthew G. Knepley   } else {
14929a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
14939a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
14949566063dSJacob Faibussowitsch       PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
14959566063dSJacob Faibussowitsch       PetscCall(DMSetType(idm, DMPLEX));
14969566063dSJacob Faibussowitsch       PetscCall(DMSetDimension(idm, dim));
14977bffde78SMichael Lange       if (depth > 0) {
14989566063dSJacob Faibussowitsch         PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
14999566063dSJacob Faibussowitsch         PetscCall(DMGetPointSF(odm, &sfPoint));
1500d7d32a9aSMatthew G. Knepley         if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
150194488200SVaclav Hapla         {
15023be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
150394488200SVaclav Hapla           PetscInt nroots;
15049566063dSJacob Faibussowitsch           PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
15059566063dSJacob Faibussowitsch           if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
150694488200SVaclav Hapla         }
15077bffde78SMichael Lange       }
15089566063dSJacob Faibussowitsch       if (odm != dm) PetscCall(DMDestroy(&odm));
15099a5b13a2SMatthew G Knepley       odm = idm;
15109f074e33SMatthew G Knepley     }
15119566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
15129566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)idm, name));
15139566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
15149566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
15159566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
15169566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
151784699f70SSatish Balay   }
1518827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1519827c4036SVaclav Hapla   {
1520d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)idm->data;
1521827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1522827c4036SVaclav Hapla   }
15235de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
15249a5b13a2SMatthew G Knepley   *dmInt = idm;
15259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
15263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15279f074e33SMatthew G Knepley }
152807b0a1fcSMatthew G Knepley 
152980330477SMatthew G. Knepley /*@
153080330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
153180330477SMatthew G. Knepley 
153220f4b53cSBarry Smith   Collective
153380330477SMatthew G. Knepley 
153480330477SMatthew G. Knepley   Input Parameter:
153520f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates
153680330477SMatthew G. Knepley 
153780330477SMatthew G. Knepley   Output Parameter:
153820f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates
153980330477SMatthew G. Knepley 
154080330477SMatthew G. Knepley   Level: intermediate
154180330477SMatthew G. Knepley 
154220f4b53cSBarry Smith   Note:
154320f4b53cSBarry Smith   This is typically used when adding pieces other than vertices to a mesh
154480330477SMatthew G. Knepley 
154520f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
154680330477SMatthew G. Knepley @*/
1547d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
1548d71ae5a4SJacob Faibussowitsch {
154907b0a1fcSMatthew G Knepley   Vec          coordinatesA, coordinatesB;
155043eeeb2dSStefano Zampini   VecType      vtype;
155107b0a1fcSMatthew G Knepley   PetscSection coordSectionA, coordSectionB;
155207b0a1fcSMatthew G Knepley   PetscScalar *coordsA, *coordsB;
15530bedd6beSMatthew G. Knepley   PetscInt     spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
155490a8aa44SJed Brown   PetscInt     cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
155543eeeb2dSStefano Zampini   PetscBool    lc = PETSC_FALSE;
155607b0a1fcSMatthew G Knepley 
155707b0a1fcSMatthew G Knepley   PetscFunctionBegin;
155843eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
155943eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
15603ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
15619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
15629566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
15639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
15649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
156563a3b9bcSJacob 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);
156661a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
156761a622f3SMatthew G. Knepley   {
156861a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
156961a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
157061a622f3SMatthew G. Knepley     PetscObject        objA, objB;
157161a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
157261a622f3SMatthew G. Knepley     const PetscScalar *constants;
157361a622f3SMatthew G. Knepley     PetscInt           cdim, Nc;
157461a622f3SMatthew G. Knepley 
15759566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
15769566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
15779566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
15789566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
15799566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
15809566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
158161a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
15829566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
15839566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
15849566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
15859566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
15869566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
15879566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
15889566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
15899566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
159061a622f3SMatthew G. Knepley     }
159161a622f3SMatthew G. Knepley   }
15929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
15939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
15949566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
15959566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
15963ba16761SJacob Faibussowitsch   if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS);
15979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
15983ba16761SJacob Faibussowitsch   if (!Nf) PetscFunctionReturn(PETSC_SUCCESS);
159963a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1600df26b574SMatthew G. Knepley   if (!coordSectionB) {
1601df26b574SMatthew G. Knepley     PetscInt dim;
1602df26b574SMatthew G. Knepley 
16039566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
16049566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
16059566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
16069566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1607df26b574SMatthew G. Knepley   }
16089566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
16099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
16109566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
16119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
161243eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
161363a3b9bcSJacob Faibussowitsch     PetscCheck((cEndA - cStartA) == (cEndB - cStartB), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %" PetscInt_FMT " != %" PetscInt_FMT " in the second DM", cEndA - cStartA, cEndB - cStartB);
161443eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
161543eeeb2dSStefano Zampini     cE = vEndB;
161643eeeb2dSStefano Zampini     lc = PETSC_TRUE;
161743eeeb2dSStefano Zampini   } else {
161843eeeb2dSStefano Zampini     cS = vStartB;
161943eeeb2dSStefano Zampini     cE = vEndB;
162043eeeb2dSStefano Zampini   }
16219566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
162207b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
16239566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
16249566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
162507b0a1fcSMatthew G Knepley   }
162643eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
162743eeeb2dSStefano Zampini     PetscInt c;
162843eeeb2dSStefano Zampini 
162943eeeb2dSStefano Zampini     for (c = cS - cStartB; c < cEndB - cStartB; c++) {
163043eeeb2dSStefano Zampini       PetscInt dof;
163143eeeb2dSStefano Zampini 
16329566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
16339566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSectionB, c + cStartB, dof));
16349566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof));
163543eeeb2dSStefano Zampini     }
163643eeeb2dSStefano Zampini   }
16379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
16389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
16399566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
16409566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
16419566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
16429566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
16439566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
16449566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
16459566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
16469566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
16479566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
16489566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
164907b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB - vStartB; ++v) {
165043eeeb2dSStefano Zampini     PetscInt offA, offB;
165143eeeb2dSStefano Zampini 
16529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
16539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1654ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
165543eeeb2dSStefano Zampini   }
165643eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
165743eeeb2dSStefano Zampini     PetscInt c;
165843eeeb2dSStefano Zampini 
165943eeeb2dSStefano Zampini     for (c = cS - cStartB; c < cEndB - cStartB; c++) {
166043eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
166143eeeb2dSStefano Zampini 
16629566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA));
16639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB));
16649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
16659566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(coordsB + offB, coordsA + offA, dof));
166607b0a1fcSMatthew G Knepley     }
166707b0a1fcSMatthew G Knepley   }
16689566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
16699566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
16709566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
16719566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
16723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
167307b0a1fcSMatthew G Knepley }
16745c386225SMatthew G. Knepley 
16754e3744c5SMatthew G. Knepley /*@
16764e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
16774e3744c5SMatthew G. Knepley 
167820f4b53cSBarry Smith   Collective
16794e3744c5SMatthew G. Knepley 
16804e3744c5SMatthew G. Knepley   Input Parameter:
168120f4b53cSBarry Smith . dm - The complete `DMPLEX` object
16824e3744c5SMatthew G. Knepley 
16834e3744c5SMatthew G. Knepley   Output Parameter:
168420f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices
16854e3744c5SMatthew G. Knepley 
16864e3744c5SMatthew G. Knepley   Level: intermediate
16874e3744c5SMatthew G. Knepley 
168820f4b53cSBarry Smith   Note:
168995452b02SPatrick Sanan     It does not copy over the coordinates.
169043eeeb2dSStefano Zampini 
169120f4b53cSBarry Smith   Developer Note:
169220f4b53cSBarry Smith   Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
16939ade3219SVaclav Hapla 
169420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
16954e3744c5SMatthew G. Knepley @*/
1696d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
1697d71ae5a4SJacob Faibussowitsch {
1698827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
16994e3744c5SMatthew G. Knepley   DM                     udm;
1700412e9a14SMatthew G. Knepley   PetscInt               dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
17014e3744c5SMatthew G. Knepley 
17024e3744c5SMatthew G. Knepley   PetscFunctionBegin;
170343eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
170443eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
1705172ee266SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0));
17069566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
17079566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
170808401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1709827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1710827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
17119566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1712595d4abbSMatthew G. Knepley     *dmUnint = dm;
17133ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
17144e3744c5SMatthew G. Knepley   }
17159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
17169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17179566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
17189566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
17199566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
17209566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
17214e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1722595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17234e3744c5SMatthew G. Knepley 
17249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17254e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17264e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17274e3744c5SMatthew G. Knepley 
17284e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
17294e3744c5SMatthew G. Knepley     }
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17319566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1732595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
17334e3744c5SMatthew G. Knepley   }
17349566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
17359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
17364e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1737595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17384e3744c5SMatthew G. Knepley 
17399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17404e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17414e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17424e3744c5SMatthew G. Knepley 
17434e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
17444e3744c5SMatthew G. Knepley     }
17459566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17469566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
17474e3744c5SMatthew G. Knepley   }
17489566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
17499566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
17509566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
17515c7de58aSMatthew G. Knepley   /* Reduce SF */
17525c7de58aSMatthew G. Knepley   {
17535c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
17545c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
17555c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
17565c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
17575c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
175822fd0ad9SVaclav Hapla     PetscInt           numRoots, numLeaves, l;
17595c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
17605c7de58aSMatthew G. Knepley 
17615c7de58aSMatthew G. Knepley     /* Get original SF information */
17629566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
1763d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
17649566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
17659566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
176622fd0ad9SVaclav Hapla     if (numRoots >= 0) {
17675c7de58aSMatthew G. Knepley       /* Allocate space for cells and vertices */
176822fd0ad9SVaclav Hapla       for (l = 0; l < numLeaves; ++l) {
176922fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
177022fd0ad9SVaclav Hapla 
177122fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
177222fd0ad9SVaclav Hapla       }
17735c7de58aSMatthew G. Knepley       /* Fill in leaves */
17749566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
17759566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
17765c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
177722fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
177822fd0ad9SVaclav Hapla 
177922fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
178022fd0ad9SVaclav Hapla           localPointsUn[n]        = p;
17815c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
17825c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
17835c7de58aSMatthew G. Knepley           ++n;
17845c7de58aSMatthew G. Knepley         }
17855c7de58aSMatthew G. Knepley       }
178663a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
178722fd0ad9SVaclav Hapla       PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
17885c7de58aSMatthew G. Knepley     }
17895c7de58aSMatthew G. Knepley   }
1790827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1791827c4036SVaclav Hapla   {
1792d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)udm->data;
1793827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1794827c4036SVaclav Hapla   }
17955de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1796d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
17974e3744c5SMatthew G. Knepley   *dmUnint = udm;
1798172ee266SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0));
17993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18004e3744c5SMatthew G. Knepley }
1801a7748839SVaclav Hapla 
1802d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1803d71ae5a4SJacob Faibussowitsch {
1804a7748839SVaclav Hapla   PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1805a7748839SVaclav Hapla   MPI_Comm comm;
1806a7748839SVaclav Hapla 
1807a7748839SVaclav Hapla   PetscFunctionBegin;
18089566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
18099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
18109566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1811a7748839SVaclav Hapla 
1812a7748839SVaclav Hapla   if (depth == dim) {
1813a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1814a7748839SVaclav Hapla     if (!dim) goto finish;
1815a7748839SVaclav Hapla 
1816a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
18179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1818a7748839SVaclav Hapla     for (p = pStart; p < pEnd; p++) {
18199566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1820a7748839SVaclav Hapla       if (coneSize) {
1821a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1822a7748839SVaclav Hapla         goto finish;
1823a7748839SVaclav Hapla       }
1824a7748839SVaclav Hapla     }
1825a7748839SVaclav Hapla 
1826a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1827a7748839SVaclav Hapla     for (h = 0; h < dim; h++) {
18289566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1829a7748839SVaclav Hapla       for (p = pStart; p < pEnd; p++) {
18309566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1831a7748839SVaclav Hapla         if (!coneSize) {
1832a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1833a7748839SVaclav Hapla           goto finish;
1834a7748839SVaclav Hapla         }
1835a7748839SVaclav Hapla       }
1836a7748839SVaclav Hapla     }
1837a7748839SVaclav Hapla   } else if (depth == 1) {
1838a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1839a7748839SVaclav Hapla   } else {
1840a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1841a7748839SVaclav Hapla   }
1842a7748839SVaclav Hapla finish:
18433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1844a7748839SVaclav Hapla }
1845a7748839SVaclav Hapla 
1846a7748839SVaclav Hapla /*@
184720f4b53cSBarry Smith   DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated.
1848a7748839SVaclav Hapla 
1849a7748839SVaclav Hapla   Not Collective
1850a7748839SVaclav Hapla 
1851a7748839SVaclav Hapla   Input Parameter:
185220f4b53cSBarry Smith . dm      - The `DMPLEX` object
1853a7748839SVaclav Hapla 
1854a7748839SVaclav Hapla   Output Parameter:
185520f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1856a7748839SVaclav Hapla 
1857a7748839SVaclav Hapla   Level: intermediate
1858a7748839SVaclav Hapla 
1859a7748839SVaclav Hapla   Notes:
186020f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective
18619ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
186220f4b53cSBarry Smith   However, `DMPlexInterpolate()` guarantees the result is the same on all.
18639ade3219SVaclav Hapla 
186420f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`.
1865a7748839SVaclav Hapla 
18669ade3219SVaclav Hapla   Developer Notes:
186720f4b53cSBarry Smith   Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`.
18689ade3219SVaclav Hapla 
186920f4b53cSBarry Smith   If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called.
18709ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
187120f4b53cSBarry Smith   `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`.
18729ade3219SVaclav Hapla 
187320f4b53cSBarry Smith   If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated.
18749ade3219SVaclav Hapla 
187520f4b53cSBarry Smith   `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`,
187620f4b53cSBarry Smith   and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
18779ade3219SVaclav Hapla 
187820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1879a7748839SVaclav Hapla @*/
1880d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1881d71ae5a4SJacob Faibussowitsch {
1882a7748839SVaclav Hapla   DM_Plex *plex = (DM_Plex *)dm->data;
1883a7748839SVaclav Hapla 
1884a7748839SVaclav Hapla   PetscFunctionBegin;
1885a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1886a7748839SVaclav Hapla   PetscValidPointer(interpolated, 2);
1887a7748839SVaclav Hapla   if (plex->interpolated < 0) {
18889566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
188976bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
1890a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1891a7748839SVaclav Hapla 
18929566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
1893c282ed06SStefano 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]);
1894a7748839SVaclav Hapla   }
1895a7748839SVaclav Hapla   *interpolated = plex->interpolated;
18963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1897a7748839SVaclav Hapla }
1898a7748839SVaclav Hapla 
1899a7748839SVaclav Hapla /*@
190020f4b53cSBarry Smith   DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner).
1901a7748839SVaclav Hapla 
19022666ff3cSVaclav Hapla   Collective
1903a7748839SVaclav Hapla 
1904a7748839SVaclav Hapla   Input Parameter:
190520f4b53cSBarry Smith . dm      - The `DMPLEX` object
1906a7748839SVaclav Hapla 
1907a7748839SVaclav Hapla   Output Parameter:
190820f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1909a7748839SVaclav Hapla 
1910a7748839SVaclav Hapla   Level: intermediate
1911a7748839SVaclav Hapla 
1912a7748839SVaclav Hapla   Notes:
191320f4b53cSBarry Smith   Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks.
19149ade3219SVaclav Hapla 
191520f4b53cSBarry Smith   This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks.
19169ade3219SVaclav Hapla 
19179ade3219SVaclav Hapla   Developer Notes:
191820f4b53cSBarry Smith   Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`.
19199ade3219SVaclav Hapla 
192020f4b53cSBarry Smith   If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated.
192120f4b53cSBarry Smith   `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
192220f4b53cSBarry Smith   if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`,
19239ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
19249ade3219SVaclav Hapla 
192520f4b53cSBarry Smith   If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective.
1926a7748839SVaclav Hapla 
192720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
1928a7748839SVaclav Hapla @*/
1929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1930d71ae5a4SJacob Faibussowitsch {
1931a7748839SVaclav Hapla   DM_Plex  *plex  = (DM_Plex *)dm->data;
1932a7748839SVaclav Hapla   PetscBool debug = PETSC_FALSE;
1933a7748839SVaclav Hapla 
1934a7748839SVaclav Hapla   PetscFunctionBegin;
1935a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1936a7748839SVaclav Hapla   PetscValidPointer(interpolated, 2);
19379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
1938a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1939a7748839SVaclav Hapla     DMPlexInterpolatedFlag min, max;
1940a7748839SVaclav Hapla     MPI_Comm               comm;
1941a7748839SVaclav Hapla 
19429566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19439566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
1944712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
1945712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
1946a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1947a7748839SVaclav Hapla     if (debug) {
1948a7748839SVaclav Hapla       PetscMPIInt rank;
1949a7748839SVaclav Hapla 
19509566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
19519566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
19529566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
1953a7748839SVaclav Hapla     }
1954a7748839SVaclav Hapla   }
1955a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
19563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1957a7748839SVaclav Hapla }
1958