xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 5d3bc7bebe3f6ef0b4c2756f1a15e9cfa34561eb)
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 
PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP (HMapIJKLRemote,PetscHMapIJKLRemoteKey,PetscSFNode,PetscHMapIJKLRemoteKeyHash,PetscHMapIJKLRemoteKeyEqual,_PetscInvalidSFNode))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 */
DMPlexGetRawFaces_Internal(DM dm,DMPolytopeType ct,const PetscInt cone[],PetscInt * numFaces,const DMPolytopeType * faceTypes[],const PetscInt * faceSizes[],const PetscInt * faces[])46d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
47d71ae5a4SJacob Faibussowitsch {
48442f3b32SStefano Zampini   DMPolytopeType *typesTmp = NULL;
49442f3b32SStefano Zampini   PetscInt       *sizesTmp = NULL, *facesTmp = NULL;
50442f3b32SStefano Zampini   PetscInt       *tmp;
51442f3b32SStefano Zampini   PetscInt        maxConeSize, maxSupportSize, maxSize;
52442f3b32SStefano Zampini   PetscInt        getSize = 0;
53439ece16SMatthew G. Knepley 
54439ece16SMatthew G. Knepley   PetscFunctionBegin;
55439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
564f572ea9SToby Isaac   if (cone) PetscAssertPointer(cone, 3);
579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
58442f3b32SStefano Zampini   maxSize = PetscMax(maxConeSize, maxSupportSize);
59442f3b32SStefano Zampini   if (faceTypes) getSize += maxSize;
60442f3b32SStefano Zampini   if (faceSizes) getSize += maxSize;
61442f3b32SStefano Zampini   if (faces) getSize += PetscSqr(maxSize);
62442f3b32SStefano Zampini   PetscCall(DMGetWorkArray(dm, getSize, MPIU_INT, &tmp));
63442f3b32SStefano Zampini   if (faceTypes) {
64442f3b32SStefano Zampini     typesTmp = (DMPolytopeType *)tmp;
65442f3b32SStefano Zampini     tmp += maxSize;
66442f3b32SStefano Zampini   }
67442f3b32SStefano Zampini   if (faceSizes) {
68442f3b32SStefano Zampini     sizesTmp = tmp;
69442f3b32SStefano Zampini     tmp += maxSize;
70442f3b32SStefano Zampini   }
71442f3b32SStefano Zampini   if (faces) facesTmp = tmp;
72ba2698f1SMatthew G. Knepley   switch (ct) {
73ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_POINT:
74ba2698f1SMatthew G. Knepley     if (numFaces) *numFaces = 0;
756f5c9017SMatthew G. Knepley     if (faceTypes) *faceTypes = typesTmp;
766f5c9017SMatthew G. Knepley     if (faceSizes) *faceSizes = sizesTmp;
776f5c9017SMatthew G. Knepley     if (faces) *faces = facesTmp;
78ba2698f1SMatthew G. Knepley     break;
79ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
80412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 2;
81412e9a14SMatthew G. Knepley     if (faceTypes) {
829371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
839371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
84412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
85412e9a14SMatthew G. Knepley     }
86412e9a14SMatthew G. Knepley     if (faceSizes) {
879371c9d4SSatish Balay       sizesTmp[0] = 1;
889371c9d4SSatish Balay       sizesTmp[1] = 1;
89412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
90412e9a14SMatthew G. Knepley     }
91c49d9212SMatthew G. Knepley     if (faces) {
929371c9d4SSatish Balay       facesTmp[0] = cone[0];
939371c9d4SSatish Balay       facesTmp[1] = cone[1];
94c49d9212SMatthew G. Knepley       *faces      = facesTmp;
95c49d9212SMatthew G. Knepley     }
96412e9a14SMatthew G. Knepley     break;
97412e9a14SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
98c49d9212SMatthew G. Knepley     if (numFaces) *numFaces = 2;
99412e9a14SMatthew G. Knepley     if (faceTypes) {
1009371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
1019371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
102412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
103412e9a14SMatthew G. Knepley     }
104412e9a14SMatthew G. Knepley     if (faceSizes) {
1059371c9d4SSatish Balay       sizesTmp[0] = 1;
1069371c9d4SSatish Balay       sizesTmp[1] = 1;
107412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
108412e9a14SMatthew G. Knepley     }
109412e9a14SMatthew G. Knepley     if (faces) {
1109371c9d4SSatish Balay       facesTmp[0] = cone[0];
1119371c9d4SSatish Balay       facesTmp[1] = cone[1];
112412e9a14SMatthew G. Knepley       *faces      = facesTmp;
113412e9a14SMatthew G. Knepley     }
114c49d9212SMatthew G. Knepley     break;
115ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
116412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 3;
117412e9a14SMatthew G. Knepley     if (faceTypes) {
1189371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1199371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1209371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
121412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
122412e9a14SMatthew G. Knepley     }
123412e9a14SMatthew G. Knepley     if (faceSizes) {
1249371c9d4SSatish Balay       sizesTmp[0] = 2;
1259371c9d4SSatish Balay       sizesTmp[1] = 2;
1269371c9d4SSatish Balay       sizesTmp[2] = 2;
127412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
128412e9a14SMatthew G. Knepley     }
1299a5b13a2SMatthew G Knepley     if (faces) {
1309371c9d4SSatish Balay       facesTmp[0] = cone[0];
1319371c9d4SSatish Balay       facesTmp[1] = cone[1];
1329371c9d4SSatish Balay       facesTmp[2] = cone[1];
1339371c9d4SSatish Balay       facesTmp[3] = cone[2];
1349371c9d4SSatish Balay       facesTmp[4] = cone[2];
1359371c9d4SSatish Balay       facesTmp[5] = cone[0];
1369a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1379a5b13a2SMatthew G Knepley     }
1389f074e33SMatthew G Knepley     break;
139ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
1409a5b13a2SMatthew G Knepley     /* Vertices follow right hand rule */
141412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
142412e9a14SMatthew G. Knepley     if (faceTypes) {
1439371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1449371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1459371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
1469371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEGMENT;
147412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
148412e9a14SMatthew G. Knepley     }
149412e9a14SMatthew G. Knepley     if (faceSizes) {
1509371c9d4SSatish Balay       sizesTmp[0] = 2;
1519371c9d4SSatish Balay       sizesTmp[1] = 2;
1529371c9d4SSatish Balay       sizesTmp[2] = 2;
1539371c9d4SSatish Balay       sizesTmp[3] = 2;
154412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
155412e9a14SMatthew G. Knepley     }
1569a5b13a2SMatthew G Knepley     if (faces) {
1579371c9d4SSatish Balay       facesTmp[0] = cone[0];
1589371c9d4SSatish Balay       facesTmp[1] = cone[1];
1599371c9d4SSatish Balay       facesTmp[2] = cone[1];
1609371c9d4SSatish Balay       facesTmp[3] = cone[2];
1619371c9d4SSatish Balay       facesTmp[4] = cone[2];
1629371c9d4SSatish Balay       facesTmp[5] = cone[3];
1639371c9d4SSatish Balay       facesTmp[6] = cone[3];
1649371c9d4SSatish Balay       facesTmp[7] = cone[0];
1659a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1669a5b13a2SMatthew G Knepley     }
167412e9a14SMatthew G. Knepley     break;
168412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
1699a5b13a2SMatthew G Knepley     if (numFaces) *numFaces = 4;
170412e9a14SMatthew G. Knepley     if (faceTypes) {
1719371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1729371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1739371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1749371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
175412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
176412e9a14SMatthew G. Knepley     }
177412e9a14SMatthew G. Knepley     if (faceSizes) {
1789371c9d4SSatish Balay       sizesTmp[0] = 2;
1799371c9d4SSatish Balay       sizesTmp[1] = 2;
1809371c9d4SSatish Balay       sizesTmp[2] = 2;
1819371c9d4SSatish Balay       sizesTmp[3] = 2;
182412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
183412e9a14SMatthew G. Knepley     }
184412e9a14SMatthew G. Knepley     if (faces) {
1859371c9d4SSatish Balay       facesTmp[0] = cone[0];
1869371c9d4SSatish Balay       facesTmp[1] = cone[1];
1879371c9d4SSatish Balay       facesTmp[2] = cone[2];
1889371c9d4SSatish Balay       facesTmp[3] = cone[3];
1899371c9d4SSatish Balay       facesTmp[4] = cone[0];
1909371c9d4SSatish Balay       facesTmp[5] = cone[2];
1919371c9d4SSatish Balay       facesTmp[6] = cone[1];
1929371c9d4SSatish Balay       facesTmp[7] = cone[3];
193412e9a14SMatthew G. Knepley       *faces      = facesTmp;
194412e9a14SMatthew G. Knepley     }
1959f074e33SMatthew G Knepley     break;
196ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
1972e1b13c2SMatthew G. Knepley     /* Vertices of first face follow right hand rule and normal points away from last vertex */
198412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
199412e9a14SMatthew G. Knepley     if (faceTypes) {
2009371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2019371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2029371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
2039371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
204412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
205412e9a14SMatthew G. Knepley     }
206412e9a14SMatthew G. Knepley     if (faceSizes) {
2079371c9d4SSatish Balay       sizesTmp[0] = 3;
2089371c9d4SSatish Balay       sizesTmp[1] = 3;
2099371c9d4SSatish Balay       sizesTmp[2] = 3;
2109371c9d4SSatish Balay       sizesTmp[3] = 3;
211412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
212412e9a14SMatthew G. Knepley     }
2139a5b13a2SMatthew G Knepley     if (faces) {
2149371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2159371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2169371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2179371c9d4SSatish Balay       facesTmp[3]  = cone[0];
2189371c9d4SSatish Balay       facesTmp[4]  = cone[3];
2199371c9d4SSatish Balay       facesTmp[5]  = cone[1];
2209371c9d4SSatish Balay       facesTmp[6]  = cone[0];
2219371c9d4SSatish Balay       facesTmp[7]  = cone[2];
2229371c9d4SSatish Balay       facesTmp[8]  = cone[3];
2239371c9d4SSatish Balay       facesTmp[9]  = cone[2];
2249371c9d4SSatish Balay       facesTmp[10] = cone[1];
2259371c9d4SSatish Balay       facesTmp[11] = cone[3];
2269a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2279a5b13a2SMatthew G Knepley     }
2289a5b13a2SMatthew G Knepley     break;
229ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
230e368ef20SMatthew G. Knepley     /*  7--------6
231e368ef20SMatthew G. Knepley          /|       /|
232e368ef20SMatthew G. Knepley         / |      / |
233e368ef20SMatthew G. Knepley        4--------5  |
234e368ef20SMatthew G. Knepley        |  |     |  |
235e368ef20SMatthew G. Knepley        |  |     |  |
236e368ef20SMatthew G. Knepley        |  1--------2
237e368ef20SMatthew G. Knepley        | /      | /
238e368ef20SMatthew G. Knepley        |/       |/
239e368ef20SMatthew G. Knepley        0--------3
240e368ef20SMatthew G. Knepley        */
241412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
242412e9a14SMatthew G. Knepley     if (faceTypes) {
2439371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
2449371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
2459371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2469371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2479371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
2489371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
249412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
250412e9a14SMatthew G. Knepley     }
251412e9a14SMatthew G. Knepley     if (faceSizes) {
2529371c9d4SSatish Balay       sizesTmp[0] = 4;
2539371c9d4SSatish Balay       sizesTmp[1] = 4;
2549371c9d4SSatish Balay       sizesTmp[2] = 4;
2559371c9d4SSatish Balay       sizesTmp[3] = 4;
2569371c9d4SSatish Balay       sizesTmp[4] = 4;
2579371c9d4SSatish Balay       sizesTmp[5] = 4;
258412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
259412e9a14SMatthew G. Knepley     }
2609a5b13a2SMatthew G Knepley     if (faces) {
2619371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2629371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2639371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2649371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
2659371c9d4SSatish Balay       facesTmp[4]  = cone[4];
2669371c9d4SSatish Balay       facesTmp[5]  = cone[5];
2679371c9d4SSatish Balay       facesTmp[6]  = cone[6];
2689371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
2699371c9d4SSatish Balay       facesTmp[8]  = cone[0];
2709371c9d4SSatish Balay       facesTmp[9]  = cone[3];
2719371c9d4SSatish Balay       facesTmp[10] = cone[5];
2729371c9d4SSatish Balay       facesTmp[11] = cone[4]; /* Front */
2739371c9d4SSatish Balay       facesTmp[12] = cone[2];
2749371c9d4SSatish Balay       facesTmp[13] = cone[1];
2759371c9d4SSatish Balay       facesTmp[14] = cone[7];
2769371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Back */
2779371c9d4SSatish Balay       facesTmp[16] = cone[3];
2789371c9d4SSatish Balay       facesTmp[17] = cone[2];
2799371c9d4SSatish Balay       facesTmp[18] = cone[6];
2809371c9d4SSatish Balay       facesTmp[19] = cone[5]; /* Right */
2819371c9d4SSatish Balay       facesTmp[20] = cone[0];
2829371c9d4SSatish Balay       facesTmp[21] = cone[4];
2839371c9d4SSatish Balay       facesTmp[22] = cone[7];
2849371c9d4SSatish Balay       facesTmp[23] = cone[1]; /* Left */
2859a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2869a5b13a2SMatthew G Knepley     }
28799836e0eSStefano Zampini     break;
288ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM:
289412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
290412e9a14SMatthew G. Knepley     if (faceTypes) {
2919371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2929371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2939371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2949371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2959371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
296412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
297412e9a14SMatthew G. Knepley     }
298412e9a14SMatthew G. Knepley     if (faceSizes) {
2999371c9d4SSatish Balay       sizesTmp[0] = 3;
3009371c9d4SSatish Balay       sizesTmp[1] = 3;
3019371c9d4SSatish Balay       sizesTmp[2] = 4;
3029371c9d4SSatish Balay       sizesTmp[3] = 4;
3039371c9d4SSatish Balay       sizesTmp[4] = 4;
304412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
305412e9a14SMatthew G. Knepley     }
306ba2698f1SMatthew G. Knepley     if (faces) {
3079371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3089371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3099371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3109371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3119371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3129371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3139371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3149371c9d4SSatish Balay       facesTmp[7]  = cone[2];
3159371c9d4SSatish Balay       facesTmp[8]  = cone[4];
3169371c9d4SSatish Balay       facesTmp[9]  = cone[3]; /* Back left */
3179371c9d4SSatish Balay       facesTmp[10] = cone[2];
3189371c9d4SSatish Balay       facesTmp[11] = cone[1];
3199371c9d4SSatish Balay       facesTmp[12] = cone[5];
3209371c9d4SSatish Balay       facesTmp[13] = cone[4]; /* Front */
3219371c9d4SSatish Balay       facesTmp[14] = cone[1];
3229371c9d4SSatish Balay       facesTmp[15] = cone[0];
3239371c9d4SSatish Balay       facesTmp[16] = cone[3];
3249371c9d4SSatish Balay       facesTmp[17] = cone[5]; /* Back right */
325ba2698f1SMatthew G. Knepley       *faces       = facesTmp;
32699836e0eSStefano Zampini     }
32799836e0eSStefano Zampini     break;
328ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
329412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
330412e9a14SMatthew G. Knepley     if (faceTypes) {
3319371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
3329371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
3339371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3349371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3359371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
336412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
337412e9a14SMatthew G. Knepley     }
338412e9a14SMatthew G. Knepley     if (faceSizes) {
3399371c9d4SSatish Balay       sizesTmp[0] = 3;
3409371c9d4SSatish Balay       sizesTmp[1] = 3;
3419371c9d4SSatish Balay       sizesTmp[2] = 4;
3429371c9d4SSatish Balay       sizesTmp[3] = 4;
3439371c9d4SSatish Balay       sizesTmp[4] = 4;
344412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
345412e9a14SMatthew G. Knepley     }
34699836e0eSStefano Zampini     if (faces) {
3479371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3489371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3499371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3509371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3519371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3529371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3539371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3549371c9d4SSatish Balay       facesTmp[7]  = cone[1];
3559371c9d4SSatish Balay       facesTmp[8]  = cone[3];
3569371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Back left */
3579371c9d4SSatish Balay       facesTmp[10] = cone[1];
3589371c9d4SSatish Balay       facesTmp[11] = cone[2];
3599371c9d4SSatish Balay       facesTmp[12] = cone[4];
3609371c9d4SSatish Balay       facesTmp[13] = cone[5]; /* Back right */
3619371c9d4SSatish Balay       facesTmp[14] = cone[2];
3629371c9d4SSatish Balay       facesTmp[15] = cone[0];
3639371c9d4SSatish Balay       facesTmp[16] = cone[5];
3649371c9d4SSatish Balay       facesTmp[17] = cone[3]; /* Front */
36599836e0eSStefano Zampini       *faces       = facesTmp;
36699836e0eSStefano Zampini     }
367412e9a14SMatthew G. Knepley     break;
368412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
369412e9a14SMatthew G. Knepley     /*  7--------6
370412e9a14SMatthew G. Knepley          /|       /|
371412e9a14SMatthew G. Knepley         / |      / |
372412e9a14SMatthew G. Knepley        4--------5  |
373412e9a14SMatthew G. Knepley        |  |     |  |
374412e9a14SMatthew G. Knepley        |  |     |  |
375412e9a14SMatthew G. Knepley        |  3--------2
376412e9a14SMatthew G. Knepley        | /      | /
377412e9a14SMatthew G. Knepley        |/       |/
378412e9a14SMatthew G. Knepley        0--------1
379412e9a14SMatthew G. Knepley        */
380412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
381412e9a14SMatthew G. Knepley     if (faceTypes) {
3829371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
3839371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
3849371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3859371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3869371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3879371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
388412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
389412e9a14SMatthew G. Knepley     }
390412e9a14SMatthew G. Knepley     if (faceSizes) {
3919371c9d4SSatish Balay       sizesTmp[0] = 4;
3929371c9d4SSatish Balay       sizesTmp[1] = 4;
3939371c9d4SSatish Balay       sizesTmp[2] = 4;
3949371c9d4SSatish Balay       sizesTmp[3] = 4;
3959371c9d4SSatish Balay       sizesTmp[4] = 4;
3969371c9d4SSatish Balay       sizesTmp[5] = 4;
397412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
398412e9a14SMatthew G. Knepley     }
399412e9a14SMatthew G. Knepley     if (faces) {
4009371c9d4SSatish Balay       facesTmp[0]  = cone[0];
4019371c9d4SSatish Balay       facesTmp[1]  = cone[1];
4029371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4039371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4049371c9d4SSatish Balay       facesTmp[4]  = cone[4];
4059371c9d4SSatish Balay       facesTmp[5]  = cone[5];
4069371c9d4SSatish Balay       facesTmp[6]  = cone[6];
4079371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
4089371c9d4SSatish Balay       facesTmp[8]  = cone[0];
4099371c9d4SSatish Balay       facesTmp[9]  = cone[1];
4109371c9d4SSatish Balay       facesTmp[10] = cone[4];
4119371c9d4SSatish Balay       facesTmp[11] = cone[5]; /* Front */
4129371c9d4SSatish Balay       facesTmp[12] = cone[1];
4139371c9d4SSatish Balay       facesTmp[13] = cone[2];
4149371c9d4SSatish Balay       facesTmp[14] = cone[5];
4159371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Right */
4169371c9d4SSatish Balay       facesTmp[16] = cone[2];
4179371c9d4SSatish Balay       facesTmp[17] = cone[3];
4189371c9d4SSatish Balay       facesTmp[18] = cone[6];
4199371c9d4SSatish Balay       facesTmp[19] = cone[7]; /* Back */
4209371c9d4SSatish Balay       facesTmp[20] = cone[3];
4219371c9d4SSatish Balay       facesTmp[21] = cone[0];
4229371c9d4SSatish Balay       facesTmp[22] = cone[7];
4239371c9d4SSatish Balay       facesTmp[23] = cone[4]; /* Left */
424412e9a14SMatthew G. Knepley       *faces       = facesTmp;
425412e9a14SMatthew G. Knepley     }
42699836e0eSStefano Zampini     break;
427da9060c4SMatthew G. Knepley   case DM_POLYTOPE_PYRAMID:
428da9060c4SMatthew G. Knepley     /*
429da9060c4SMatthew G. Knepley        4----
430da9060c4SMatthew G. Knepley        |\-\ \-----
431da9060c4SMatthew G. Knepley        | \ -\     \
432da9060c4SMatthew G. Knepley        |  1--\-----2
433da9060c4SMatthew G. Knepley        | /    \   /
434da9060c4SMatthew G. Knepley        |/      \ /
435da9060c4SMatthew G. Knepley        0--------3
436da9060c4SMatthew G. Knepley        */
437da9060c4SMatthew G. Knepley     if (numFaces) *numFaces = 5;
438da9060c4SMatthew G. Knepley     if (faceTypes) {
439da9060c4SMatthew G. Knepley       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
4409371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
4419371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
4429371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
4439371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_TRIANGLE;
444da9060c4SMatthew G. Knepley       *faceTypes  = typesTmp;
445da9060c4SMatthew G. Knepley     }
446da9060c4SMatthew G. Knepley     if (faceSizes) {
447da9060c4SMatthew G. Knepley       sizesTmp[0] = 4;
4489371c9d4SSatish Balay       sizesTmp[1] = 3;
4499371c9d4SSatish Balay       sizesTmp[2] = 3;
4509371c9d4SSatish Balay       sizesTmp[3] = 3;
4519371c9d4SSatish Balay       sizesTmp[4] = 3;
452da9060c4SMatthew G. Knepley       *faceSizes  = sizesTmp;
453da9060c4SMatthew G. Knepley     }
454da9060c4SMatthew G. Knepley     if (faces) {
4559371c9d4SSatish Balay       facesTmp[0]  = cone[0];
4569371c9d4SSatish Balay       facesTmp[1]  = cone[1];
4579371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4589371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4599371c9d4SSatish Balay       facesTmp[4]  = cone[0];
4609371c9d4SSatish Balay       facesTmp[5]  = cone[3];
4619371c9d4SSatish Balay       facesTmp[6]  = cone[4]; /* Front */
4629371c9d4SSatish Balay       facesTmp[7]  = cone[3];
4639371c9d4SSatish Balay       facesTmp[8]  = cone[2];
4649371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Right */
4659371c9d4SSatish Balay       facesTmp[10] = cone[2];
4669371c9d4SSatish Balay       facesTmp[11] = cone[1];
4679371c9d4SSatish Balay       facesTmp[12] = cone[4]; /* Back */
4689371c9d4SSatish Balay       facesTmp[13] = cone[1];
4699371c9d4SSatish Balay       facesTmp[14] = cone[0];
4709371c9d4SSatish Balay       facesTmp[15] = cone[4]; /* Left */
471da9060c4SMatthew G. Knepley       *faces       = facesTmp;
472da9060c4SMatthew G. Knepley     }
473da9060c4SMatthew G. Knepley     break;
474d71ae5a4SJacob Faibussowitsch   default:
475d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
47699836e0eSStefano Zampini   }
4773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47899836e0eSStefano Zampini }
47999836e0eSStefano Zampini 
DMPlexRestoreRawFaces_Internal(DM dm,DMPolytopeType ct,const PetscInt cone[],PetscInt * numFaces,const DMPolytopeType * faceTypes[],const PetscInt * faceSizes[],const PetscInt * faces[])480d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
481d71ae5a4SJacob Faibussowitsch {
48299836e0eSStefano Zampini   PetscFunctionBegin;
4839566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes));
484442f3b32SStefano Zampini   else if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes));
485442f3b32SStefano Zampini   else if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces));
486442f3b32SStefano Zampini   if (faceTypes) *faceTypes = NULL;
487442f3b32SStefano Zampini   if (faceSizes) *faceSizes = NULL;
488442f3b32SStefano Zampini   if (faces) *faces = NULL;
4893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49099836e0eSStefano Zampini }
49199836e0eSStefano Zampini 
4929a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
DMPlexInterpolateFaces_Internal(DM dm,PetscInt cellDepth,DM idm)4939fbdc704SMatthew G. Knepley PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
494d71ae5a4SJacob Faibussowitsch {
495412e9a14SMatthew G. Knepley   DMLabel       ctLabel;
496a03d55ffSStefano Zampini   PetscHMapIJKL faceTable;
497412e9a14SMatthew G. Knepley   PetscInt      faceTypeNum[DM_NUM_POLYTOPES];
4981afe9b7dSMatthew G. Knepley   PetscInt      depth, pStart, Np, cStart, cEnd, fStart, fEnd, vStart, vEnd;
499a03d55ffSStefano Zampini   PetscInt      cntFaces, *facesId, minCone;
5009f074e33SMatthew G Knepley 
5019f074e33SMatthew G Knepley   PetscFunctionBegin;
5029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
503a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLCreate(&faceTable));
5049566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
5051afe9b7dSMatthew G. Knepley   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
5069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
5071afe9b7dSMatthew G. Knepley   // If the range incorporates the vertices, it means we have a non-manifold topology, so choose just cells
5081afe9b7dSMatthew G. Knepley   if (cStart <= vStart && cEnd >= vEnd) cEnd = vStart;
5095c2c0cecSMatthew G. Knepley   // Number new faces and save face vertices in hash table
5101afe9b7dSMatthew G. Knepley   //   If depth > cellDepth, meaning we are interpolating faces, put the new (d-1)-faces after them
5111afe9b7dSMatthew G. Knepley   //   otherwise, we are interpolating cells, so put the faces after the vertices
5129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
513412e9a14SMatthew G. Knepley   fEnd = fStart;
514591a860aSStefano Zampini 
5151690c2aeSBarry Smith   minCone  = PETSC_INT_MAX;
5165c2c0cecSMatthew G. Knepley   cntFaces = 0;
5175c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
518591a860aSStefano Zampini     const PetscInt *cone;
519591a860aSStefano Zampini     DMPolytopeType  ct;
520ed896b67SJose E. Roman     PetscInt        numFaces = 0, coneSize;
521591a860aSStefano Zampini 
522591a860aSStefano Zampini     PetscCall(DMPlexGetCellType(dm, c, &ct));
523591a860aSStefano Zampini     PetscCall(DMPlexGetCone(dm, c, &cone));
524a03d55ffSStefano Zampini     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
525a03d55ffSStefano Zampini     for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone);
5266f5c9017SMatthew G. Knepley     // Ignore faces since they are interpolated
5276f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL));
528591a860aSStefano Zampini     cntFaces += numFaces;
529591a860aSStefano Zampini   }
5301690c2aeSBarry Smith   // Encode so that we can use 0 as an excluded value, instead of PETSC_INT_MAX
531a03d55ffSStefano Zampini   minCone = -(minCone - 1);
532591a860aSStefano Zampini 
533591a860aSStefano Zampini   PetscCall(PetscMalloc1(cntFaces, &facesId));
534591a860aSStefano Zampini 
5355c2c0cecSMatthew G. Knepley   cntFaces = 0;
5365c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
537412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
538412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
539ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
5405c2c0cecSMatthew G. Knepley     PetscInt              numFaces, foff = 0;
54199836e0eSStefano Zampini 
5429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5446f5c9017SMatthew G. Knepley     // Ignore faces since they are interpolated
5456f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5476f5c9017SMatthew G. Knepley     } else {
5486f5c9017SMatthew G. Knepley       numFaces = 0;
5496f5c9017SMatthew G. Knepley     }
5505c2c0cecSMatthew G. Knepley     for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
551412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
552412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
553412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
5549a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
555e8f14785SLisandro Dalcin       PetscHashIter        iter;
556e8f14785SLisandro Dalcin       PetscBool            missing;
5579f074e33SMatthew G Knepley 
5585f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
559a03d55ffSStefano Zampini       key.i = face[0] + minCone;
560a03d55ffSStefano Zampini       key.j = faceSize > 1 ? face[1] + minCone : 0;
561a03d55ffSStefano Zampini       key.k = faceSize > 2 ? face[2] + minCone : 0;
562a03d55ffSStefano Zampini       key.l = faceSize > 3 ? face[3] + minCone : 0;
5639566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
564a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
565e9fa77a1SMatthew G. Knepley       if (missing) {
566591a860aSStefano Zampini         facesId[cntFaces] = fEnd;
567a03d55ffSStefano Zampini         PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++));
568412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
569a03d55ffSStefano Zampini       } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
570591a860aSStefano Zampini       cntFaces++;
5719a5b13a2SMatthew G Knepley     }
5726f5c9017SMatthew G. Knepley     if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
57399836e0eSStefano Zampini   }
574412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
575412e9a14SMatthew G. Knepley   {
576412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
57799836e0eSStefano Zampini 
5789371c9d4SSatish Balay     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5799371c9d4SSatish Balay       if (faceTypeNum[ct]) ++numFT;
5809371c9d4SSatish Balay       faceTypeStart[ct] = 0;
5819371c9d4SSatish Balay     }
582412e9a14SMatthew G. Knepley     if (numFT > 1) {
583a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLClear(faceTable));
584412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
585412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
5865c2c0cecSMatthew G. Knepley       cntFaces = 0;
5875c2c0cecSMatthew G. Knepley       for (PetscInt c = cStart; c < cEnd; ++c) {
588412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
589412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
590ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
5915c2c0cecSMatthew G. Knepley         PetscInt              numFaces, foff = 0;
59299836e0eSStefano Zampini 
5939566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
5949566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
5956f5c9017SMatthew G. Knepley         if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5969566063dSJacob Faibussowitsch           PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5976f5c9017SMatthew G. Knepley         } else {
5986f5c9017SMatthew G. Knepley           numFaces = 0;
5996f5c9017SMatthew G. Knepley         }
6005c2c0cecSMatthew G. Knepley         for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
601412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
602412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
603412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
60499836e0eSStefano Zampini           PetscHashIJKLKey     key;
60599836e0eSStefano Zampini           PetscHashIter        iter;
60699836e0eSStefano Zampini           PetscBool            missing;
60799836e0eSStefano Zampini 
608a03d55ffSStefano Zampini           key.i = face[0] + minCone;
609a03d55ffSStefano Zampini           key.j = faceSize > 1 ? face[1] + minCone : 0;
610a03d55ffSStefano Zampini           key.k = faceSize > 2 ? face[2] + minCone : 0;
611a03d55ffSStefano Zampini           key.l = faceSize > 3 ? face[3] + minCone : 0;
6129566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
613a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
614591a860aSStefano Zampini           if (missing) {
615591a860aSStefano Zampini             facesId[cntFaces] = faceTypeStart[faceType];
616a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
617a03d55ffSStefano Zampini           } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
618591a860aSStefano Zampini           cntFaces++;
61999836e0eSStefano Zampini         }
6206f5c9017SMatthew G. Knepley         if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
62199836e0eSStefano Zampini       }
622412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
6231dca8a05SBarry Smith         PetscCheck(faceTypeStart[ct] == faceTypeStart[ct - 1] + faceTypeNum[ct], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent numbering for cell type %s, %" PetscInt_FMT " != %" PetscInt_FMT " + %" PetscInt_FMT, DMPolytopeTypes[ct], faceTypeStart[ct], faceTypeStart[ct - 1], faceTypeNum[ct]);
6249a5b13a2SMatthew G Knepley       }
6259a5b13a2SMatthew G Knepley     }
626412e9a14SMatthew G. Knepley   }
627a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLDestroy(&faceTable));
628591a860aSStefano Zampini 
6295c2c0cecSMatthew G. Knepley   // Add new points, perhaps inserting into the numbering
6309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
6319566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
6325c2c0cecSMatthew G. Knepley   // Set cone sizes
6335c2c0cecSMatthew G. Knepley   //   Must create the celltype label here so that we do not automatically try to compute the types
6349566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
6359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
6365c2c0cecSMatthew G. Knepley   for (PetscInt d = 0; d <= depth; ++d) {
637412e9a14SMatthew G. Knepley     DMPolytopeType ct;
6385c2c0cecSMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, poff = 0;
6399f074e33SMatthew G Knepley 
6409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
6411afe9b7dSMatthew G. Knepley     // Check for non-manifold condition
6421afe9b7dSMatthew G. Knepley     if (d == cellDepth) {
6431afe9b7dSMatthew G. Knepley       if (pEnd == cEnd) continue;
6441afe9b7dSMatthew G. Knepley       else pStart = vEnd;
6451afe9b7dSMatthew G. Knepley     }
6465c2c0cecSMatthew G. Knepley     // Account for insertion
6475c2c0cecSMatthew G. Knepley     if (pStart >= fStart) poff = fEnd - fStart;
6485c2c0cecSMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
6499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
6505c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetConeSize(idm, p + poff, coneSize));
6519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
6525c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetCellType(idm, p + poff, ct));
6539f074e33SMatthew G Knepley     }
6549f074e33SMatthew G Knepley   }
6555c2c0cecSMatthew G. Knepley   cntFaces = 0;
6565c2c0cecSMatthew G. Knepley   for (PetscInt c = cStart; c < cEnd; ++c) {
657591a860aSStefano Zampini     const PetscInt       *cone, *faceSizes;
658412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
659412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
6605c2c0cecSMatthew G. Knepley     PetscInt              numFaces, poff = 0;
661412e9a14SMatthew G. Knepley 
6629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
6645c2c0cecSMatthew G. Knepley     if (c >= fStart) poff = fEnd - fStart;
6656f5c9017SMatthew G. Knepley     if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
6665c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetCellType(idm, c + poff, ct));
6675c2c0cecSMatthew G. Knepley       PetscCall(DMPlexSetConeSize(idm, c + poff, 2));
6686f5c9017SMatthew G. Knepley       continue;
6696f5c9017SMatthew G. Knepley     }
670591a860aSStefano Zampini     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6715c2c0cecSMatthew G. Knepley     PetscCall(DMPlexSetCellType(idm, c + poff, ct));
6725c2c0cecSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(idm, c + poff, numFaces));
6735c2c0cecSMatthew G. Knepley     for (PetscInt cf = 0; cf < numFaces; ++cf) {
674591a860aSStefano Zampini       const PetscInt f        = facesId[cntFaces];
675591a860aSStefano Zampini       DMPolytopeType faceType = faceTypes[cf];
676412e9a14SMatthew G. Knepley       const PetscInt faceSize = faceSizes[cf];
6779566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, f, faceSize));
6789566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, f, faceType));
679591a860aSStefano Zampini       cntFaces++;
680412e9a14SMatthew G. Knepley     }
681591a860aSStefano Zampini     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6829f074e33SMatthew G Knepley   }
6839566063dSJacob Faibussowitsch   PetscCall(DMSetUp(idm));
6845c2c0cecSMatthew G. Knepley   // Initialize cones so we do not need the bash table to tell us that a cone has been set
685412e9a14SMatthew G. Knepley   {
686412e9a14SMatthew G. Knepley     PetscSection cs;
687412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
6889a5b13a2SMatthew G Knepley 
6899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSection(idm, &cs));
6909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCones(idm, &cones));
6919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(cs, &csize));
6925c2c0cecSMatthew G. Knepley     for (PetscInt c = 0; c < csize; ++c) cones[c] = -1;
693412e9a14SMatthew G. Knepley   }
6945c2c0cecSMatthew G. Knepley   // Set cones
6955c2c0cecSMatthew G. Knepley   {
6965c2c0cecSMatthew G. Knepley     PetscInt *icone;
6975c2c0cecSMatthew G. Knepley     PetscInt  maxConeSize;
6985c2c0cecSMatthew G. Knepley 
6995c2c0cecSMatthew G. Knepley     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL));
7005c2c0cecSMatthew G. Knepley     PetscCall(PetscMalloc1(maxConeSize, &icone));
7015c2c0cecSMatthew G. Knepley     for (PetscInt d = 0; d <= depth; ++d) {
702412e9a14SMatthew G. Knepley       const PetscInt *cone;
7035c2c0cecSMatthew G. Knepley       PetscInt        pStart, pEnd, poff = 0, coneSize;
704412e9a14SMatthew G. Knepley 
7059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
7061afe9b7dSMatthew G. Knepley       // Check for non-manifold condition
7071afe9b7dSMatthew G. Knepley       if (d == cellDepth) {
7081afe9b7dSMatthew G. Knepley         if (pEnd == cEnd) continue;
7091afe9b7dSMatthew G. Knepley         else pStart = vEnd;
7101afe9b7dSMatthew G. Knepley       }
7115c2c0cecSMatthew G. Knepley       // Account for insertion
7125c2c0cecSMatthew G. Knepley       if (pStart >= fStart) poff = fEnd - fStart;
7135c2c0cecSMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
7149566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
7155c2c0cecSMatthew G. Knepley         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
7165c2c0cecSMatthew G. Knepley         for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0);
7175c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetCone(idm, p + poff, icone));
7189566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
7195c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetConeOrientation(idm, p + poff, cone));
7209f074e33SMatthew G Knepley       }
7219a5b13a2SMatthew G Knepley     }
7225c2c0cecSMatthew G. Knepley     cntFaces = 0;
7235c2c0cecSMatthew G. Knepley     for (PetscInt c = cStart; c < cEnd; ++c) {
724412e9a14SMatthew G. Knepley       const PetscInt       *cone, *faceSizes, *faces;
725412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
726ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
7275c2c0cecSMatthew G. Knepley       PetscInt              coneSize, numFaces, foff = 0, poff = 0;
72899836e0eSStefano Zampini 
7299566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
7309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
7315c2c0cecSMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
7325c2c0cecSMatthew G. Knepley       if (c >= fStart) poff = fEnd - fStart;
7336f5c9017SMatthew G. Knepley       if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
7345c2c0cecSMatthew G. Knepley         for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0);
7355c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetCone(idm, c + poff, icone));
7366f5c9017SMatthew G. Knepley         PetscCall(DMPlexGetConeOrientation(dm, c, &cone));
7375c2c0cecSMatthew G. Knepley         PetscCall(DMPlexSetConeOrientation(idm, c + poff, cone));
7386f5c9017SMatthew G. Knepley         continue;
7396f5c9017SMatthew G. Knepley       }
7409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
7415c2c0cecSMatthew G. Knepley       for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
742412e9a14SMatthew G. Knepley         DMPolytopeType  faceType = faceTypes[cf];
743412e9a14SMatthew G. Knepley         const PetscInt  faceSize = faceSizes[cf];
744591a860aSStefano Zampini         const PetscInt  f        = facesId[cntFaces];
745412e9a14SMatthew G. Knepley         const PetscInt *face     = &faces[foff];
746412e9a14SMatthew G. Knepley         const PetscInt *fcone;
7479f074e33SMatthew G Knepley 
7489566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertCone(idm, c, cf, f));
7499566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &fcone));
7509566063dSJacob Faibussowitsch         if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
751412e9a14SMatthew G. Knepley         {
7521afe9b7dSMatthew G. Knepley           const PetscInt *fcone2;
7535c2c0cecSMatthew G. Knepley           PetscInt        ornt;
754a74221b0SStefano Zampini 
7559566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
7561afe9b7dSMatthew G. Knepley           PetscCall(DMPlexGetCone(idm, f, &fcone2));
75763a3b9bcSJacob Faibussowitsch           PetscCheck(coneSize == faceSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %" PetscInt_FMT " for face %" PetscInt_FMT " should be %" PetscInt_FMT, coneSize, f, faceSize);
758d89e6e46SMatthew G. Knepley           /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
7591afe9b7dSMatthew G. Knepley           PetscCall(DMPolytopeGetVertexOrientation(faceType, fcone2, face, &ornt));
7605c2c0cecSMatthew G. Knepley           PetscCall(DMPlexInsertConeOrientation(idm, c + poff, cf, ornt));
76199836e0eSStefano Zampini         }
762591a860aSStefano Zampini         cntFaces++;
76399836e0eSStefano Zampini       }
7649566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
76599836e0eSStefano Zampini     }
7665c2c0cecSMatthew G. Knepley     PetscCall(PetscFree(icone));
7675c2c0cecSMatthew G. Knepley   }
768591a860aSStefano Zampini   PetscCall(PetscFree(facesId));
7699566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
7709566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
7713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7729f074e33SMatthew G Knepley }
7739f074e33SMatthew G Knepley 
SortRmineRremoteByRemote_Private(PetscSF sf,PetscInt * rmine1[],PetscInt * rremote1[])774d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
775d71ae5a4SJacob Faibussowitsch {
776f80536cbSVaclav Hapla   PetscInt           nleaves;
7776497c311SBarry Smith   PetscMPIInt        nranks;
778a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks   = NULL;
779a0d42dbcSVaclav Hapla   const PetscInt    *roffset = NULL, *rmine = NULL, *rremote = NULL;
7806497c311SBarry Smith   PetscInt           n, o;
781f80536cbSVaclav Hapla 
782f80536cbSVaclav Hapla   PetscFunctionBegin;
7839566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
784f80536cbSVaclav Hapla   nleaves = roffset[nranks];
7859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
7866497c311SBarry Smith   for (PetscMPIInt r = 0; r < nranks; r++) {
787f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
788f80536cbSVaclav Hapla        - to unify order with the other side */
789f80536cbSVaclav Hapla     o = roffset[r];
790f80536cbSVaclav Hapla     n = roffset[r + 1] - o;
7919566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7929566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7939566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
794f80536cbSVaclav Hapla   }
7953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
796f80536cbSVaclav Hapla }
797f80536cbSVaclav Hapla 
DMPlexOrientInterface_Internal(DM dm)798d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
799d71ae5a4SJacob Faibussowitsch {
800d89e6e46SMatthew G. Knepley   PetscSF            sf;
801d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
802d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
803d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
804d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
805d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
8066497c311SBarry Smith   PetscInt           nroots, p, nleaves, maxConeSize = 0;
8076497c311SBarry Smith   PetscMPIInt        nranks, r;
808d89e6e46SMatthew G. Knepley   PetscInt (*roots)[4], (*leaves)[4], mainCone[4];
809d89e6e46SMatthew G. Knepley   PetscMPIInt (*rootsRanks)[4], (*leavesRanks)[4];
8102e745bdaSMatthew G. Knepley   MPI_Comm    comm;
81127d0e99aSVaclav Hapla   PetscMPIInt rank, size;
8122e745bdaSMatthew G. Knepley   PetscInt    debug = 0;
8132e745bdaSMatthew G. Knepley 
8142e745bdaSMatthew G. Knepley   PetscFunctionBegin;
8159566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8179566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
8189566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
8199566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
820d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
8219566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
8223ba16761SJacob Faibussowitsch   if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS);
8239566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
8249566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
825d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
826d89e6e46SMatthew G. Knepley     PetscInt coneSize;
8279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
828d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
829d89e6e46SMatthew G. Knepley   }
83063a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
8319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
8329e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
833d89e6e46SMatthew G. Knepley     const PetscInt *cone;
834d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
835d89e6e46SMatthew G. Knepley 
8369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
838d89e6e46SMatthew G. Knepley     /* Ignore vertices */
83927d0e99aSVaclav Hapla     if (coneSize < 2) {
840d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
84127d0e99aSVaclav Hapla         roots[p][c]      = -1;
84227d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
84327d0e99aSVaclav Hapla       }
84427d0e99aSVaclav Hapla       continue;
84527d0e99aSVaclav Hapla     }
8462e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
847d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
8489566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
8498a650c75SVaclav Hapla       if (ind0 < 0) {
8508a650c75SVaclav Hapla         roots[p][c]      = cone[c];
8518a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
852c8148b97SVaclav Hapla       } else {
8538a650c75SVaclav Hapla         roots[p][c] = remotes[ind0].index;
854835f2295SStefano Zampini         PetscCall(PetscMPIIntCast(remotes[ind0].rank, &rootsRanks[p][c]));
8558a650c75SVaclav Hapla       }
8562e745bdaSMatthew G. Knepley     }
857d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
858d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
859d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
860d89e6e46SMatthew G. Knepley     }
8612e745bdaSMatthew G. Knepley   }
8629e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
863d89e6e46SMatthew G. Knepley     PetscInt c;
864d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
8658ccb905dSVaclav Hapla       leaves[p][c]      = -2;
8668ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
8678ccb905dSVaclav Hapla     }
868c8148b97SVaclav Hapla   }
8699566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8709566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
8719566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8729566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
873d89e6e46SMatthew G. Knepley   if (debug) {
8749566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
875c5853193SPierre Jolivet     if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
876d89e6e46SMatthew G. Knepley   }
8779566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8789e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
879d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
880d89e6e46SMatthew G. Knepley     const PetscInt *cone;
8816497c311SBarry Smith     PetscInt        coneSize, c, ind0, o, ir;
882d89e6e46SMatthew G. Knepley 
883d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
8849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
8859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
887d89e6e46SMatthew G. Knepley     if (debug) {
8889371c9d4SSatish 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]));
889d89e6e46SMatthew G. Knepley     }
8909371c9d4SSatish 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]) {
891d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
892d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
893d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
894d89e6e46SMatthew G. Knepley 
89527d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
896d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
8979dddd249SSatish Balay           mainCone[c] = leaves[p][c];
89827d0e99aSVaclav Hapla           continue;
89927d0e99aSVaclav Hapla         }
900f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
901f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
902835f2295SStefano Zampini         PetscCall(PetscFindMPIInt(leavesRanks[p][c], nranks, ranks, &ir));
9036497c311SBarry Smith         PetscCall(PetscMPIIntCast(ir, &r));
90463a3b9bcSJacob 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]);
9056497c311SBarry Smith         PetscCheck(ranks[r] >= 0 && ranks[r] < size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%" PetscInt_FMT " c=%" PetscInt_FMT " commsize=%d: ranks[%d] = %d makes no sense", p, c, size, r, ranks[r]);
906f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
907d89e6e46SMatthew G. Knepley         rS = roffset[r];
908d89e6e46SMatthew G. Knepley         rN = roffset[r + 1] - rS;
9099566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
91063a3b9bcSJacob 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]);
911f80536cbSVaclav Hapla         /* Get the corresponding local point */
9125f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
913f80536cbSVaclav Hapla       }
91463a3b9bcSJacob 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]));
91527d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
9169566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
9179566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
9189566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
91923aaf07bSVaclav Hapla   }
92027d0e99aSVaclav Hapla   if (debug) {
9219566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
9229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
9232e745bdaSMatthew G. Knepley   }
9249566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
9259566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
9269566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
9273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9282e745bdaSMatthew G. Knepley }
9292e745bdaSMatthew G. Knepley 
IntArrayViewFromOptions(MPI_Comm comm,const char opt[],const char name[],const char idxname[],const char valname[],PetscInt n,const PetscInt a[])930d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
931d71ae5a4SJacob Faibussowitsch {
9322e72742cSMatthew G. Knepley   PetscInt    idx;
9332e72742cSMatthew G. Knepley   PetscMPIInt rank;
9342e72742cSMatthew G. Knepley   PetscBool   flg;
9357bffde78SMichael Lange 
9367bffde78SMichael Lange   PetscFunctionBegin;
9379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9383ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9409566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
94163a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
9429566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9442e72742cSMatthew G. Knepley }
9452e72742cSMatthew G. Knepley 
SFNodeArrayViewFromOptions(MPI_Comm comm,const char opt[],const char name[],const char idxname[],PetscInt n,const PetscSFNode a[])946d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
947d71ae5a4SJacob Faibussowitsch {
9482e72742cSMatthew G. Knepley   PetscInt    idx;
9492e72742cSMatthew G. Knepley   PetscMPIInt rank;
9502e72742cSMatthew G. Knepley   PetscBool   flg;
9512e72742cSMatthew G. Knepley 
9522e72742cSMatthew G. Knepley   PetscFunctionBegin;
9539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9543ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9559566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9569566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
9572e72742cSMatthew G. Knepley   if (idxname) {
958835f2295SStefano Zampini     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));
9592e72742cSMatthew G. Knepley   } else {
960835f2295SStefano Zampini     for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]rank %" PetscInt_FMT " index %" PetscInt_FMT "\n", rank, a[idx].rank, a[idx].index));
9612e72742cSMatthew G. Knepley   }
9629566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
9633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9642e72742cSMatthew G. Knepley }
9652e72742cSMatthew G. Knepley 
DMPlexMapToLocalPoint(DM dm,PetscHMapIJ remotehash,PetscSFNode remotePoint,PetscInt * localPoint,PetscBool * mapFailed)966d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
967d71ae5a4SJacob Faibussowitsch {
9683be36e83SMatthew G. Knepley   PetscSF         sf;
9693be36e83SMatthew G. Knepley   const PetscInt *locals;
9703be36e83SMatthew G. Knepley   PetscMPIInt     rank;
9712e72742cSMatthew G. Knepley 
9722e72742cSMatthew G. Knepley   PetscFunctionBegin;
9739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9749566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9759566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
9765f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9772e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
9782e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
9792e72742cSMatthew G. Knepley   } else {
9802e72742cSMatthew G. Knepley     PetscHashIJKey key;
9813be36e83SMatthew G. Knepley     PetscInt       l;
9822e72742cSMatthew G. Knepley 
9832e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9842e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9859566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
9863be36e83SMatthew G. Knepley     if (l >= 0) {
9873be36e83SMatthew G. Knepley       *localPoint = locals[l];
9885f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
9892e72742cSMatthew G. Knepley   }
9903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9912e72742cSMatthew G. Knepley }
9922e72742cSMatthew G. Knepley 
DMPlexMapToGlobalPoint(DM dm,PetscInt localPoint,PetscSFNode * remotePoint,PetscBool * mapFailed)993d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
994d71ae5a4SJacob Faibussowitsch {
9953be36e83SMatthew G. Knepley   PetscSF            sf;
9963be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9973be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9983be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9993be36e83SMatthew G. Knepley   PetscMPIInt        rank;
10003be36e83SMatthew G. Knepley 
10013be36e83SMatthew G. Knepley   PetscFunctionBegin;
10025f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
10039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10049566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
10059566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
10063be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
10079566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
10089566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
10093be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
10109566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
10119371c9d4SSatish Balay   if (l < 0) {
10129371c9d4SSatish Balay     if (mapFailed) *mapFailed = PETSC_TRUE;
10139371c9d4SSatish Balay   } else *remotePoint = remotes[l];
10143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10153be36e83SMatthew G. Knepley owned:
10163be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
10173be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
10183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10193be36e83SMatthew G. Knepley }
10203be36e83SMatthew G. Knepley 
DMPlexPointIsShared(DM dm,PetscInt p,PetscBool * isShared)1021d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
1022d71ae5a4SJacob Faibussowitsch {
10233be36e83SMatthew G. Knepley   PetscSF         sf;
10243be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
10253be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
10263be36e83SMatthew G. Knepley 
10273be36e83SMatthew G. Knepley   PetscFunctionBegin;
10283be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
10299566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
10309566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
10313ba16761SJacob Faibussowitsch   if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS);
10329566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
10339371c9d4SSatish Balay   if (idx >= 0) {
10349371c9d4SSatish Balay     *isShared = PETSC_TRUE;
10353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
10369371c9d4SSatish Balay   }
10379566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
10389566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
10393be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
10403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10413be36e83SMatthew G. Knepley }
10423be36e83SMatthew G. Knepley 
DMPlexConeIsShared(DM dm,PetscInt p,PetscBool * isShared)1043d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
1044d71ae5a4SJacob Faibussowitsch {
10453be36e83SMatthew G. Knepley   const PetscInt *cone;
10463be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10473be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
10483be36e83SMatthew G. Knepley 
10493be36e83SMatthew G. Knepley   PetscFunctionBegin;
10509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10523be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10533be36e83SMatthew G. Knepley     PetscBool pointShared;
10543be36e83SMatthew G. Knepley 
10559566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
10563be36e83SMatthew G. Knepley     cShared = (PetscBool)(cShared && pointShared);
10573be36e83SMatthew G. Knepley   }
10583be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
10593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10603be36e83SMatthew G. Knepley }
10613be36e83SMatthew G. Knepley 
DMPlexGetConeMinimum(DM dm,PetscInt p,PetscSFNode * cpmin)1062d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
1063d71ae5a4SJacob Faibussowitsch {
10643be36e83SMatthew G. Knepley   const PetscInt *cone;
10653be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
10666497c311SBarry Smith   PetscSFNode     cmin = {PETSC_INT_MAX, PETSC_MPI_INT_MAX}, missing = {-1, -1};
10673be36e83SMatthew G. Knepley 
10683be36e83SMatthew G. Knepley   PetscFunctionBegin;
10699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
10713be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
10723be36e83SMatthew G. Knepley     PetscSFNode rcp;
10735f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
10743be36e83SMatthew G. Knepley 
10759566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
10765f80ce2aSJacob Faibussowitsch     if (mapFailed) {
10773be36e83SMatthew G. Knepley       cmin = missing;
10783be36e83SMatthew G. Knepley     } else {
10793be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10803be36e83SMatthew G. Knepley     }
10813be36e83SMatthew G. Knepley   }
10823be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
10833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10843be36e83SMatthew G. Knepley }
10853be36e83SMatthew G. Knepley 
10863be36e83SMatthew G. Knepley /*
10873be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10883be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10893be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10903be36e83SMatthew G. Knepley */
DMPlexAddSharedFace_Private(DM dm,PetscSection candidateSection,PetscSFNode candidates[],PetscHMapIJ faceHash,PetscInt p,PetscBool debug)1091d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
1092d71ae5a4SJacob Faibussowitsch {
10933be36e83SMatthew G. Knepley   MPI_Comm        comm;
10943be36e83SMatthew G. Knepley   const PetscInt *support;
1095cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10963be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10973be36e83SMatthew G. Knepley 
10983be36e83SMatthew G. Knepley   PetscFunctionBegin;
10999566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
11029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
11039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
1104cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight + 1) {
1105cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
110663a3b9bcSJacob 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));
11073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1108cf4dc471SVaclav Hapla   }
11099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
11109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
11119566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
11123be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
11133be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
11143be36e83SMatthew G. Knepley     const PetscInt *cone;
11153be36e83SMatthew G. Knepley     PetscSFNode     cpmin = {-1, -1}, rp = {-1, -1};
11163be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
11173be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
11183be36e83SMatthew G. Knepley     PetscHashIJKey  key;
11193be36e83SMatthew G. Knepley 
11203be36e83SMatthew G. Knepley     /* Only add point once */
112163a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
11223be36e83SMatthew G. Knepley     key.i = p;
11233be36e83SMatthew G. Knepley     key.j = face;
11249566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
11253be36e83SMatthew G. Knepley     if (f >= 0) continue;
11269566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
11279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
11289566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
11293be36e83SMatthew G. Knepley     if (debug) {
113063a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
1131835f2295SStefano Zampini       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));
11323be36e83SMatthew G. Knepley     }
11333be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
11349566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
11353be36e83SMatthew G. Knepley       if (candidates) {
113663a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
11379566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11389566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
11393be36e83SMatthew G. Knepley         candidates[off + idx].rank    = -1;
11403be36e83SMatthew G. Knepley         candidates[off + idx++].index = coneSize - 1;
11413be36e83SMatthew G. Knepley         candidates[off + idx].rank    = rank;
11423be36e83SMatthew G. Knepley         candidates[off + idx++].index = face;
11433be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
11443be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
11453be36e83SMatthew G. Knepley 
11463be36e83SMatthew G. Knepley           if (cp == p) continue;
11479566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
1148835f2295SStefano Zampini           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT "),%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
11493be36e83SMatthew G. Knepley           ++idx;
11503be36e83SMatthew G. Knepley         }
11519566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
11523be36e83SMatthew G. Knepley       } else {
11533be36e83SMatthew G. Knepley         /* Add cone size to section */
115463a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
11559566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11569566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
11579566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
11583be36e83SMatthew G. Knepley       }
11593be36e83SMatthew G. Knepley     }
11603be36e83SMatthew G. Knepley   }
11613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11623be36e83SMatthew G. Knepley }
11633be36e83SMatthew G. Knepley 
11642e72742cSMatthew G. Knepley /*@
116520f4b53cSBarry Smith   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation
11662e72742cSMatthew G. Knepley 
116720f4b53cSBarry Smith   Collective
11682e72742cSMatthew G. Knepley 
11692e72742cSMatthew G. Knepley   Input Parameters:
117020f4b53cSBarry Smith + dm      - The interpolated `DMPLEX`
117120f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points
11722e72742cSMatthew G. Knepley 
1173f0cfc026SVaclav Hapla   Level: developer
11742e72742cSMatthew G. Knepley 
117520f4b53cSBarry Smith   Note:
117620f4b53cSBarry 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`
11772e72742cSMatthew G. Knepley 
117820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()`
11792e72742cSMatthew G. Knepley @*/
DMPlexInterpolatePointSF(DM dm,PetscSF pointSF)1180d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
1181d71ae5a4SJacob Faibussowitsch {
11823be36e83SMatthew G. Knepley   MPI_Comm           comm;
11833be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
11843be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
11853be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11863be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11872e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11882e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11893be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11903be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11913be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1192f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11932e72742cSMatthew G. Knepley 
11942e72742cSMatthew G. Knepley   PetscFunctionBegin;
1195f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1196064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11979566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
11983ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
11993be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
12009566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
12019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
12029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
12039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
120428b400f6SJacob Faibussowitsch   PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
12059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
12069566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
12079566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
12089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
12093be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
12109566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
121108401ef6SPierre Jolivet   PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
12129566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
12133be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
12143be36e83SMatthew G. Knepley     PetscHashIJKey key;
12156497c311SBarry Smith 
12162e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
12172e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
12189566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
12197bffde78SMichael Lange   }
122066aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
12219566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
12229566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
12239566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
12243be36e83SMatthew G. Knepley   /*
12253be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
12263be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
12273be36e83SMatthew G. Knepley   \begin{itemize}
12283be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
12293be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
12303be36e83SMatthew G. Knepley   \end{itemize}
12313be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
12323be36e83SMatthew 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
12333be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
12343be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
12353be36e83SMatthew G. Knepley   */
12363be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
12373be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
1238da81f932SPierre Jolivet        The array holds candidate shared faces, each face is referred to by the leaf point */
12399566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
12409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
12417bffde78SMichael Lange   {
12423be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
12432e72742cSMatthew G. Knepley 
12449566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
12453be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12463be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
12472e72742cSMatthew G. Knepley 
124863a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
12499566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
12502e72742cSMatthew G. Knepley     }
12519566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
12529566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
12539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
12549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
12553be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12563be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
12572e72742cSMatthew G. Knepley 
125863a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
12599566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
12602e72742cSMatthew G. Knepley     }
12619566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
12629566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
12637bffde78SMichael Lange   }
12649566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
12659566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
12669566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
12673be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
12682e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
12697bffde78SMichael Lange   {
12707bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
12717bffde78SMichael Lange     PetscInt *remoteOffsets;
12722e72742cSMatthew G. Knepley 
12739566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
12749566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
12759566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
12769566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
12779566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
12789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
12799566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
12806497c311SBarry Smith     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_SF_NODE, candidates, candidatesRemote, MPI_REPLACE));
12816497c311SBarry Smith     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_SF_NODE, candidates, candidatesRemote, MPI_REPLACE));
12829566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
12839566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
12849566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
12852e72742cSMatthew G. Knepley 
12869566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12879566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12889566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12897bffde78SMichael Lange   }
12903be36e83SMatthew 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 */
12917bffde78SMichael Lange   {
1292a03d55ffSStefano Zampini     PetscHMapIJKLRemote faceTable;
12933be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12943be36e83SMatthew G. Knepley 
1295a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteCreate(&faceTable));
12962e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12973be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12982e72742cSMatthew G. Knepley       PetscInt deg;
12993be36e83SMatthew G. Knepley 
13002e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
13012e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
13022e72742cSMatthew G. Knepley 
13039566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
13049566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
13053be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
13062e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13073be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
13083be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13093be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx + 1];
13103be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13113be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
1312d9dd0fdcSStefano Zampini           const PetscSFNode      pmax = {-1, -1};
13132e72742cSMatthew G. Knepley           const PetscInt        *join = NULL;
1314a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
13153be36e83SMatthew G. Knepley           PetscHashIter          iter;
13165f80ce2aSJacob Faibussowitsch           PetscBool              missing, mapToLocalPointFailed = PETSC_FALSE;
13172e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
13182e72742cSMatthew G. Knepley 
13199371c9d4SSatish Balay           if (debug)
1320835f2295SStefano Zampini             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,
13219371c9d4SSatish Balay                                               rface.index, r, idx, d, Np));
13226497c311SBarry Smith 
1323835f2295SStefano Zampini           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);
13243be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13253be36e83SMatthew G. Knepley           fcp0.index = r;
13263be36e83SMatthew G. Knepley           d += Np;
13273be36e83SMatthew G. Knepley           /* Put remote face in hash table */
13283be36e83SMatthew G. Knepley           key.i = fcp0;
13293be36e83SMatthew G. Knepley           key.j = fcone[0];
13303be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13313be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13329566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
1333a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
13343be36e83SMatthew G. Knepley           if (missing) {
1335835f2295SStefano Zampini             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT "))\n", rank, rface.index, rface.rank));
1336a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13373be36e83SMatthew G. Knepley           } else {
13383be36e83SMatthew G. Knepley             PetscSFNode oface;
13393be36e83SMatthew G. Knepley 
1340a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13413be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
1342835f2295SStefano Zampini               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1343a03d55ffSStefano Zampini               PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13443be36e83SMatthew G. Knepley             }
13453be36e83SMatthew G. Knepley           }
13463be36e83SMatthew G. Knepley           /* Check for local face */
13472e72742cSMatthew G. Knepley           points[0] = r;
13483be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
13499566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
13505f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
135163a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
13527bffde78SMichael Lange           }
13535f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
13549566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
13557bffde78SMichael Lange           if (joinSize == 1) {
13563be36e83SMatthew G. Knepley             PetscSFNode lface;
13573be36e83SMatthew G. Knepley             PetscSFNode oface;
13583be36e83SMatthew G. Knepley 
13593be36e83SMatthew G. Knepley             /* Always replace with local face */
13603be36e83SMatthew G. Knepley             lface.rank  = rank;
13613be36e83SMatthew G. Knepley             lface.index = join[0];
1362a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13639371c9d4SSatish Balay             if (debug)
1364835f2295SStefano Zampini               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));
1365a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface));
13667bffde78SMichael Lange           }
13679566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
13683be36e83SMatthew G. Knepley         }
13693be36e83SMatthew G. Knepley       }
13703be36e83SMatthew G. Knepley       /* Put back faces for this root */
13713be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
13723be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
13733be36e83SMatthew G. Knepley 
13749566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
13759566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
13763be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
13773be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
13783be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
13793be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13803be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13813be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
1382d9dd0fdcSStefano Zampini           const PetscSFNode      pmax = {-1, -1};
1383a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
13843be36e83SMatthew G. Knepley           PetscHashIter          iter;
13853be36e83SMatthew G. Knepley           PetscBool              missing;
13863be36e83SMatthew G. Knepley 
138763a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
138863a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13893be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13903be36e83SMatthew G. Knepley           fcp0.index = r;
13913be36e83SMatthew G. Knepley           d += Np;
13923be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13933be36e83SMatthew G. Knepley           key.i = fcp0;
13943be36e83SMatthew G. Knepley           key.j = fcone[0];
13953be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13963be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13979566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13989371c9d4SSatish Balay           if (debug)
1399835f2295SStefano Zampini             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,
1400835f2295SStefano Zampini                                               key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index));
1401a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
140263a3b9bcSJacob Faibussowitsch           PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1403a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
14047bffde78SMichael Lange         }
14057bffde78SMichael Lange       }
14067bffde78SMichael Lange     }
14079566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
1408a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable));
14097bffde78SMichael Lange   }
14103be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
14117bffde78SMichael Lange   {
14127bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
14137bffde78SMichael Lange     PetscSFNode *remotePointsNew;
14142e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
14153be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
14162e72742cSMatthew G. Knepley 
14173be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
14189566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
14199566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
14209566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
14219566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
14229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
14239566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
14243be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
14256497c311SBarry Smith     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_SF_NODE, candidatesRemote, claims, MPI_REPLACE));
14266497c311SBarry Smith     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_SF_NODE, candidatesRemote, claims, MPI_REPLACE));
14279566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
14289566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
14299566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
14309566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
14319566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
14323be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
14333be36e83SMatthew 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 */
14349566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
14353be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
14363be36e83SMatthew G. Knepley       PetscInt dof, off, d;
14372e72742cSMatthew G. Knepley 
143863a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
14399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
14409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
14412e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
14423be36e83SMatthew G. Knepley         if (claims[off + d].rank >= 0) {
14433be36e83SMatthew G. Knepley           const PetscInt  faceInd = off + d;
14443be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off + d].index;
14452e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
14462e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
14472e72742cSMatthew G. Knepley 
1448835f2295SStefano Zampini           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
14493be36e83SMatthew G. Knepley           points[0] = r;
145063a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
14513be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
14529566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
145363a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c + 1]));
14542e72742cSMatthew G. Knepley           }
14559566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
14562e72742cSMatthew G. Knepley           if (joinSize == 1) {
14573be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
145863a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
14593be36e83SMatthew G. Knepley             } else {
146063a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
14619566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
14622e72742cSMatthew G. Knepley             }
14633be36e83SMatthew G. Knepley           } else {
14649566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
14653be36e83SMatthew G. Knepley           }
14669566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
14673be36e83SMatthew G. Knepley         } else {
146863a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
14693be36e83SMatthew G. Knepley           d += claims[off + d].index + 1;
14707bffde78SMichael Lange         }
14717bffde78SMichael Lange       }
14723be36e83SMatthew G. Knepley     }
14739566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
14743be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
14759566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
14769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14779566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
14789566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
14793be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
14803be36e83SMatthew G. Knepley       localPointsNew[l]        = localPoints[l];
14813be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
14823be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
14837bffde78SMichael Lange     }
14843be36e83SMatthew G. Knepley     p = Nl;
14859566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
14863be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
14878e3a54c0SPierre Jolivet     PetscCall(PetscSortInt(NlNew, PetscSafePointerPlusOffset(localPointsNew, Nl)));
14883be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14893be36e83SMatthew G. Knepley       PetscInt off;
14909566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
1491835f2295SStefano Zampini       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);
14923be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14937bffde78SMichael Lange     }
14949566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
14959566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14969566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
14979566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
14989566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1499d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
15009566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
15019566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
15027bffde78SMichael Lange   }
15039566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
15049566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
15059566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
15069566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
15079566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
15089566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
15099566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
15109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
15113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15127bffde78SMichael Lange }
15137bffde78SMichael Lange 
1514248eb259SVaclav Hapla /*@
151580330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
151680330477SMatthew G. Knepley 
151720f4b53cSBarry Smith   Collective
151880330477SMatthew G. Knepley 
151920f4b53cSBarry Smith   Input Parameter:
152020f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices
152180330477SMatthew G. Knepley 
152280330477SMatthew G. Knepley   Output Parameter:
152320f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object
152480330477SMatthew G. Knepley 
152580330477SMatthew G. Knepley   Level: intermediate
152680330477SMatthew G. Knepley 
152720f4b53cSBarry Smith   Note:
15287fb59074SVaclav Hapla   Labels and coordinates are copied.
152943eeeb2dSStefano Zampini 
153060225df5SJacob Faibussowitsch   Developer Notes:
153120f4b53cSBarry Smith   It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`.
15329ade3219SVaclav Hapla 
153320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
153480330477SMatthew G. Knepley @*/
DMPlexInterpolate(DM dm,DM * dmInt)1535d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
1536d71ae5a4SJacob Faibussowitsch {
1537a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
15389a5b13a2SMatthew G Knepley   DM                     idm, odm = dm;
15397bffde78SMichael Lange   PetscSF                sfPoint;
15402e1b13c2SMatthew G. Knepley   PetscInt               depth, dim, d;
154110a67516SMatthew G. Knepley   const char            *name;
1542b325530aSVaclav Hapla   PetscBool              flg = PETSC_TRUE;
15439f074e33SMatthew G Knepley 
15449f074e33SMatthew G Knepley   PetscFunctionBegin;
154510a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15464f572ea9SToby Isaac   PetscAssertPointer(dmInt, 2);
15479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
15489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
15499566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
15509566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
155108401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1552827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
15539566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
155476b791aaSMatthew G. Knepley     idm = dm;
1555b21b8912SMatthew G. Knepley   } else {
15565c2c0cecSMatthew G. Knepley     PetscBool nonmanifold = PETSC_FALSE;
15575c2c0cecSMatthew G. Knepley 
15585c2c0cecSMatthew G. Knepley     PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &nonmanifold, NULL));
15595c2c0cecSMatthew G. Knepley     if (nonmanifold) {
15605c2c0cecSMatthew G. Knepley       do {
15615c2c0cecSMatthew G. Knepley         const char *prefix;
15625c2c0cecSMatthew G. Knepley         PetscInt    pStart, pEnd, pdepth;
15635c2c0cecSMatthew G. Knepley         PetscBool   done = PETSC_TRUE;
15645c2c0cecSMatthew G. Knepley 
15655c2c0cecSMatthew G. Knepley         // Find a point which is not correctly interpolated
15665c2c0cecSMatthew G. Knepley         PetscCall(DMPlexGetChart(odm, &pStart, &pEnd));
15675c2c0cecSMatthew G. Knepley         for (PetscInt p = pStart; p < pEnd; ++p) {
15685c2c0cecSMatthew G. Knepley           DMPolytopeType  ct;
15695c2c0cecSMatthew G. Knepley           const PetscInt *cone;
15705c2c0cecSMatthew G. Knepley           PetscInt        coneSize, cdepth;
15715c2c0cecSMatthew G. Knepley 
15725c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetPointDepth(odm, p, &pdepth));
15735c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetCellType(odm, p, &ct));
15745c2c0cecSMatthew G. Knepley           // Check against celltype
15755c2c0cecSMatthew G. Knepley           if (pdepth != DMPolytopeTypeGetDim(ct)) {
15765c2c0cecSMatthew G. Knepley             done = PETSC_FALSE;
15775c2c0cecSMatthew G. Knepley             break;
15785c2c0cecSMatthew G. Knepley           }
15795c2c0cecSMatthew G. Knepley           // Check against boundary
15805c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetCone(odm, p, &cone));
15815c2c0cecSMatthew G. Knepley           PetscCall(DMPlexGetConeSize(odm, p, &coneSize));
15825c2c0cecSMatthew G. Knepley           for (PetscInt c = 0; c < coneSize; ++c) {
15835c2c0cecSMatthew G. Knepley             PetscCall(DMPlexGetPointDepth(odm, cone[c], &cdepth));
15845c2c0cecSMatthew G. Knepley             if (cdepth != pdepth - 1) {
15855c2c0cecSMatthew G. Knepley               done = PETSC_FALSE;
15865c2c0cecSMatthew G. Knepley               p    = pEnd;
15875c2c0cecSMatthew G. Knepley               break;
15885c2c0cecSMatthew G. Knepley             }
15895c2c0cecSMatthew G. Knepley           }
15905c2c0cecSMatthew G. Knepley         }
15915c2c0cecSMatthew G. Knepley         if (done) break;
15925c2c0cecSMatthew G. Knepley         /* Create interpolated mesh */
15935c2c0cecSMatthew G. Knepley         PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
15945c2c0cecSMatthew G. Knepley         PetscCall(DMSetType(idm, DMPLEX));
15955c2c0cecSMatthew G. Knepley         PetscCall(DMSetDimension(idm, dim));
15965c2c0cecSMatthew G. Knepley         PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
15975c2c0cecSMatthew G. Knepley         PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
15985c2c0cecSMatthew G. Knepley         if (depth > 0) {
15995c2c0cecSMatthew G. Knepley           PetscCall(DMPlexInterpolateFaces_Internal(odm, pdepth, idm));
16005c2c0cecSMatthew G. Knepley           PetscCall(DMGetPointSF(odm, &sfPoint));
16015c2c0cecSMatthew G. Knepley           if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
16025c2c0cecSMatthew G. Knepley           {
16035c2c0cecSMatthew G. Knepley             /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
16045c2c0cecSMatthew G. Knepley             PetscInt nroots;
16055c2c0cecSMatthew G. Knepley             PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
16065c2c0cecSMatthew G. Knepley             if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
16075c2c0cecSMatthew G. Knepley           }
16085c2c0cecSMatthew G. Knepley         }
16095c2c0cecSMatthew G. Knepley         if (odm != dm) PetscCall(DMDestroy(&odm));
16105c2c0cecSMatthew G. Knepley         odm = idm;
16115c2c0cecSMatthew G. Knepley       } while (1);
16125c2c0cecSMatthew G. Knepley     } else {
16139a5b13a2SMatthew G Knepley       for (d = 1; d < dim; ++d) {
16146f5c9017SMatthew G. Knepley         const char *prefix;
16156f5c9017SMatthew G. Knepley 
16169a5b13a2SMatthew G Knepley         /* Create interpolated mesh */
16179566063dSJacob Faibussowitsch         PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
16189566063dSJacob Faibussowitsch         PetscCall(DMSetType(idm, DMPLEX));
16199566063dSJacob Faibussowitsch         PetscCall(DMSetDimension(idm, dim));
16206f5c9017SMatthew G. Knepley         PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
16216f5c9017SMatthew G. Knepley         PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
16227bffde78SMichael Lange         if (depth > 0) {
16239566063dSJacob Faibussowitsch           PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
16249566063dSJacob Faibussowitsch           PetscCall(DMGetPointSF(odm, &sfPoint));
1625d7d32a9aSMatthew G. Knepley           if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
162694488200SVaclav Hapla           {
16273be36e83SMatthew G. Knepley             /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
162894488200SVaclav Hapla             PetscInt nroots;
16299566063dSJacob Faibussowitsch             PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
16309566063dSJacob Faibussowitsch             if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
163194488200SVaclav Hapla           }
16327bffde78SMichael Lange         }
16339566063dSJacob Faibussowitsch         if (odm != dm) PetscCall(DMDestroy(&odm));
16349a5b13a2SMatthew G Knepley         odm = idm;
16359f074e33SMatthew G Knepley       }
16365c2c0cecSMatthew G. Knepley     }
16379566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
16389566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)idm, name));
16399566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
16409566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
16419566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
16429566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
164384699f70SSatish Balay   }
1644827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1645827c4036SVaclav Hapla   {
1646d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)idm->data;
1647827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1648827c4036SVaclav Hapla   }
16495de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
16509a5b13a2SMatthew G Knepley   *dmInt = idm;
16519566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
16523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16539f074e33SMatthew G Knepley }
165407b0a1fcSMatthew G Knepley 
165580330477SMatthew G. Knepley /*@
165680330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
165780330477SMatthew G. Knepley 
165820f4b53cSBarry Smith   Collective
165980330477SMatthew G. Knepley 
166080330477SMatthew G. Knepley   Input Parameter:
166120f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates
166280330477SMatthew G. Knepley 
166380330477SMatthew G. Knepley   Output Parameter:
166420f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates
166580330477SMatthew G. Knepley 
166680330477SMatthew G. Knepley   Level: intermediate
166780330477SMatthew G. Knepley 
16686f5c9017SMatthew G. Knepley   Notes:
166920f4b53cSBarry Smith   This is typically used when adding pieces other than vertices to a mesh
167080330477SMatthew G. Knepley 
16716f5c9017SMatthew G. Knepley   This function does not copy localized coordinates.
16726f5c9017SMatthew G. Knepley 
167320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
167480330477SMatthew G. Knepley @*/
DMPlexCopyCoordinates(DM dmA,DM dmB)1675d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
1676d71ae5a4SJacob Faibussowitsch {
167707b0a1fcSMatthew G Knepley   Vec          coordinatesA, coordinatesB;
167843eeeb2dSStefano Zampini   VecType      vtype;
167907b0a1fcSMatthew G Knepley   PetscSection coordSectionA, coordSectionB;
168007b0a1fcSMatthew G Knepley   PetscScalar *coordsA, *coordsB;
16810bedd6beSMatthew G. Knepley   PetscInt     spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
168290a8aa44SJed Brown   PetscInt     cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
168307b0a1fcSMatthew G Knepley 
168407b0a1fcSMatthew G Knepley   PetscFunctionBegin;
168543eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
168643eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
16873ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
16889566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
16899566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
16909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
16919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
169263a3b9bcSJacob 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);
169361a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
169461a622f3SMatthew G. Knepley   {
169561a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
169661a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
169761a622f3SMatthew G. Knepley     PetscObject        objA, objB;
169861a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
169961a622f3SMatthew G. Knepley     const PetscScalar *constants;
170061a622f3SMatthew G. Knepley     PetscInt           cdim, Nc;
170161a622f3SMatthew G. Knepley 
17029566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
17039566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
17049566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
17059566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
17069566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
17079566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
170861a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
17099566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
17109566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
17119566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
17129566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
17139566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
17149566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
17159566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
17169566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
171761a622f3SMatthew G. Knepley     }
171861a622f3SMatthew G. Knepley   }
17199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
17209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
17219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
17229566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
17233ba16761SJacob Faibussowitsch   if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS);
17249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
17253ba16761SJacob Faibussowitsch   if (!Nf) PetscFunctionReturn(PETSC_SUCCESS);
172663a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1727df26b574SMatthew G. Knepley   if (!coordSectionB) {
1728df26b574SMatthew G. Knepley     PetscInt dim;
1729df26b574SMatthew G. Knepley 
17309566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
17319566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
17329566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
17339566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1734df26b574SMatthew G. Knepley   }
17359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
17369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
17379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
17389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
173943eeeb2dSStefano Zampini   cS = vStartB;
174043eeeb2dSStefano Zampini   cE = vEndB;
17419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
174207b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
17439566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
17449566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
174507b0a1fcSMatthew G Knepley   }
17469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
17479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
17489566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
17499566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
17509566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
17519566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
17529566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
17539566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
17549566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
17559566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
17569566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
17579566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
175807b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB - vStartB; ++v) {
175943eeeb2dSStefano Zampini     PetscInt offA, offB;
176043eeeb2dSStefano Zampini 
17619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
17629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1763ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
176443eeeb2dSStefano Zampini   }
17659566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
17669566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
17679566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
17689566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
17693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
177007b0a1fcSMatthew G Knepley }
17715c386225SMatthew G. Knepley 
17724e3744c5SMatthew G. Knepley /*@
17734e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
17744e3744c5SMatthew G. Knepley 
177520f4b53cSBarry Smith   Collective
17764e3744c5SMatthew G. Knepley 
17774e3744c5SMatthew G. Knepley   Input Parameter:
177820f4b53cSBarry Smith . dm - The complete `DMPLEX` object
17794e3744c5SMatthew G. Knepley 
17804e3744c5SMatthew G. Knepley   Output Parameter:
178120f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices
17824e3744c5SMatthew G. Knepley 
17834e3744c5SMatthew G. Knepley   Level: intermediate
17844e3744c5SMatthew G. Knepley 
178520f4b53cSBarry Smith   Note:
178695452b02SPatrick Sanan   It does not copy over the coordinates.
178743eeeb2dSStefano Zampini 
178860225df5SJacob Faibussowitsch   Developer Notes:
178920f4b53cSBarry Smith   Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
17909ade3219SVaclav Hapla 
179120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
17924e3744c5SMatthew G. Knepley @*/
DMPlexUninterpolate(DM dm,DM * dmUnint)1793d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
1794d71ae5a4SJacob Faibussowitsch {
1795827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
17964e3744c5SMatthew G. Knepley   DM                     udm;
1797412e9a14SMatthew G. Knepley   PetscInt               dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
17984e3744c5SMatthew G. Knepley 
17994e3744c5SMatthew G. Knepley   PetscFunctionBegin;
180043eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18014f572ea9SToby Isaac   PetscAssertPointer(dmUnint, 2);
1802172ee266SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0));
18039566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
18049566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
180508401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1806827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1807827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
18089566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1809595d4abbSMatthew G. Knepley     *dmUnint = dm;
18103ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18114e3744c5SMatthew G. Knepley   }
18129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
18139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
18149566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
18159566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
18169566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
18179566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
18184e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1819595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
18204e3744c5SMatthew G. Knepley 
18219566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18224e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
18234e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
18244e3744c5SMatthew G. Knepley 
18254e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
18264e3744c5SMatthew G. Knepley     }
18279566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18289566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1829595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
18304e3744c5SMatthew G. Knepley   }
18319566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
18329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
18334e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1834595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
18354e3744c5SMatthew G. Knepley 
18369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18374e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
18384e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
18394e3744c5SMatthew G. Knepley 
18404e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
18414e3744c5SMatthew G. Knepley     }
18429566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18439566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
18444e3744c5SMatthew G. Knepley   }
18459566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
18469566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
18479566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
18485c7de58aSMatthew G. Knepley   /* Reduce SF */
18495c7de58aSMatthew G. Knepley   {
18505c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
18515c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
18525c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
18535c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
18545c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
185522fd0ad9SVaclav Hapla     PetscInt           numRoots, numLeaves, l;
18565c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
18575c7de58aSMatthew G. Knepley 
18585c7de58aSMatthew G. Knepley     /* Get original SF information */
18599566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
1860d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
18619566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
18629566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
186322fd0ad9SVaclav Hapla     if (numRoots >= 0) {
18645c7de58aSMatthew G. Knepley       /* Allocate space for cells and vertices */
186522fd0ad9SVaclav Hapla       for (l = 0; l < numLeaves; ++l) {
186622fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
186722fd0ad9SVaclav Hapla 
186822fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
186922fd0ad9SVaclav Hapla       }
18705c7de58aSMatthew G. Knepley       /* Fill in leaves */
18719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
18729566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
18735c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
187422fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
187522fd0ad9SVaclav Hapla 
187622fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
187722fd0ad9SVaclav Hapla           localPointsUn[n]        = p;
18785c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
18795c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
18805c7de58aSMatthew G. Knepley           ++n;
18815c7de58aSMatthew G. Knepley         }
18825c7de58aSMatthew G. Knepley       }
188363a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
188422fd0ad9SVaclav Hapla       PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
18855c7de58aSMatthew G. Knepley     }
18865c7de58aSMatthew G. Knepley   }
1887827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1888827c4036SVaclav Hapla   {
1889d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)udm->data;
1890827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1891827c4036SVaclav Hapla   }
18925de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1893d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
18944e3744c5SMatthew G. Knepley   *dmUnint = udm;
1895172ee266SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0));
18963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18974e3744c5SMatthew G. Knepley }
1898a7748839SVaclav Hapla 
DMPlexIsInterpolated_Internal(DM dm,DMPlexInterpolatedFlag * interpolated)1899d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1900d71ae5a4SJacob Faibussowitsch {
1901a7748839SVaclav Hapla   PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1902a7748839SVaclav Hapla   MPI_Comm comm;
1903a7748839SVaclav Hapla 
1904a7748839SVaclav Hapla   PetscFunctionBegin;
19059566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
19079566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1908a7748839SVaclav Hapla 
1909a7748839SVaclav Hapla   if (depth == dim) {
1910a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1911a7748839SVaclav Hapla     if (!dim) goto finish;
1912a7748839SVaclav Hapla 
1913a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
19149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1915a7748839SVaclav Hapla     for (p = pStart; p < pEnd; p++) {
19169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1917a7748839SVaclav Hapla       if (coneSize) {
1918a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1919a7748839SVaclav Hapla         goto finish;
1920a7748839SVaclav Hapla       }
1921a7748839SVaclav Hapla     }
1922a7748839SVaclav Hapla 
1923a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1924a7748839SVaclav Hapla     for (h = 0; h < dim; h++) {
19259566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1926a7748839SVaclav Hapla       for (p = pStart; p < pEnd; p++) {
19279566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1928a7748839SVaclav Hapla         if (!coneSize) {
1929a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1930a7748839SVaclav Hapla           goto finish;
1931a7748839SVaclav Hapla         }
1932a7748839SVaclav Hapla       }
1933a7748839SVaclav Hapla     }
1934a7748839SVaclav Hapla   } else if (depth == 1) {
1935a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1936a7748839SVaclav Hapla   } else {
1937a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1938a7748839SVaclav Hapla   }
1939a7748839SVaclav Hapla finish:
19403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1941a7748839SVaclav Hapla }
1942a7748839SVaclav Hapla 
1943a7748839SVaclav Hapla /*@
194420f4b53cSBarry Smith   DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated.
1945a7748839SVaclav Hapla 
1946a7748839SVaclav Hapla   Not Collective
1947a7748839SVaclav Hapla 
1948a7748839SVaclav Hapla   Input Parameter:
194920f4b53cSBarry Smith . dm - The `DMPLEX` object
1950a7748839SVaclav Hapla 
1951a7748839SVaclav Hapla   Output Parameter:
195220f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1953a7748839SVaclav Hapla 
1954a7748839SVaclav Hapla   Level: intermediate
1955a7748839SVaclav Hapla 
1956a7748839SVaclav Hapla   Notes:
195720f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective
19589ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
195920f4b53cSBarry Smith   However, `DMPlexInterpolate()` guarantees the result is the same on all.
19609ade3219SVaclav Hapla 
196120f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`.
1962a7748839SVaclav Hapla 
19639ade3219SVaclav Hapla   Developer Notes:
196420f4b53cSBarry Smith   Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`.
19659ade3219SVaclav Hapla 
196620f4b53cSBarry Smith   If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called.
19679ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
196820f4b53cSBarry Smith   `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`.
19699ade3219SVaclav Hapla 
197020f4b53cSBarry Smith   If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated.
19719ade3219SVaclav Hapla 
197220f4b53cSBarry Smith   `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`,
197320f4b53cSBarry Smith   and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
19749ade3219SVaclav Hapla 
197520f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1976a7748839SVaclav Hapla @*/
DMPlexIsInterpolated(DM dm,DMPlexInterpolatedFlag * interpolated)1977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1978d71ae5a4SJacob Faibussowitsch {
1979a7748839SVaclav Hapla   DM_Plex *plex = (DM_Plex *)dm->data;
1980a7748839SVaclav Hapla 
1981a7748839SVaclav Hapla   PetscFunctionBegin;
1982a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19834f572ea9SToby Isaac   PetscAssertPointer(interpolated, 2);
1984a7748839SVaclav Hapla   if (plex->interpolated < 0) {
19859566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
198676bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
1987a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1988a7748839SVaclav Hapla 
19899566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
1990c282ed06SStefano 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]);
1991a7748839SVaclav Hapla   }
1992a7748839SVaclav Hapla   *interpolated = plex->interpolated;
19933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1994a7748839SVaclav Hapla }
1995a7748839SVaclav Hapla 
1996a7748839SVaclav Hapla /*@
199720f4b53cSBarry Smith   DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner).
1998a7748839SVaclav Hapla 
19992666ff3cSVaclav Hapla   Collective
2000a7748839SVaclav Hapla 
2001a7748839SVaclav Hapla   Input Parameter:
200220f4b53cSBarry Smith . dm - The `DMPLEX` object
2003a7748839SVaclav Hapla 
2004a7748839SVaclav Hapla   Output Parameter:
200520f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
2006a7748839SVaclav Hapla 
2007a7748839SVaclav Hapla   Level: intermediate
2008a7748839SVaclav Hapla 
2009a7748839SVaclav Hapla   Notes:
201020f4b53cSBarry Smith   Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks.
20119ade3219SVaclav Hapla 
201220f4b53cSBarry Smith   This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks.
20139ade3219SVaclav Hapla 
20149ade3219SVaclav Hapla   Developer Notes:
201520f4b53cSBarry Smith   Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`.
20169ade3219SVaclav Hapla 
201720f4b53cSBarry Smith   If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated.
201820f4b53cSBarry Smith   `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
201920f4b53cSBarry Smith   if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`,
20209ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
20219ade3219SVaclav Hapla 
202220f4b53cSBarry Smith   If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective.
2023a7748839SVaclav Hapla 
202420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
2025a7748839SVaclav Hapla @*/
DMPlexIsInterpolatedCollective(DM dm,DMPlexInterpolatedFlag * interpolated)2026d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
2027d71ae5a4SJacob Faibussowitsch {
2028a7748839SVaclav Hapla   DM_Plex  *plex  = (DM_Plex *)dm->data;
2029a7748839SVaclav Hapla   PetscBool debug = PETSC_FALSE;
2030a7748839SVaclav Hapla 
2031a7748839SVaclav Hapla   PetscFunctionBegin;
2032a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20334f572ea9SToby Isaac   PetscAssertPointer(interpolated, 2);
20349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
2035a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
2036a7748839SVaclav Hapla     DMPlexInterpolatedFlag min, max;
2037a7748839SVaclav Hapla     MPI_Comm               comm;
2038a7748839SVaclav Hapla 
20399566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
20409566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
2041462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
2042462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
2043a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
2044a7748839SVaclav Hapla     if (debug) {
2045a7748839SVaclav Hapla       PetscMPIInt rank;
2046a7748839SVaclav Hapla 
20479566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
20489566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
20499566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
2050a7748839SVaclav Hapla     }
2051a7748839SVaclav Hapla   }
2052a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
20533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2054a7748839SVaclav Hapla }
2055*5e2c5519SMatthew G. Knepley 
2056*5e2c5519SMatthew G. Knepley /*@
2057*5e2c5519SMatthew G. Knepley   DMPlexGetInterpolatePreferTensor - Get the flag to prefer tensor order when interpolating a cell
2058*5e2c5519SMatthew G. Knepley 
2059*5e2c5519SMatthew G. Knepley   Not Collective
2060*5e2c5519SMatthew G. Knepley 
2061*5e2c5519SMatthew G. Knepley   Input Parameter:
2062*5e2c5519SMatthew G. Knepley . dm - The `DMPLEX` object
2063*5e2c5519SMatthew G. Knepley 
2064*5e2c5519SMatthew G. Knepley   Output Parameter:
2065*5e2c5519SMatthew G. Knepley . preferTensor - Flag to prefer tensor order
2066*5e2c5519SMatthew G. Knepley 
2067*5e2c5519SMatthew G. Knepley   Level: intermediate
2068*5e2c5519SMatthew G. Knepley 
2069*5e2c5519SMatthew G. Knepley   Notes:
2070*5e2c5519SMatthew G. Knepley   Currently, this just affects triangular prisms,
2071*5e2c5519SMatthew G. Knepley 
2072*5e2c5519SMatthew G. Knepley .seealso: `DMPlexSetInterpolatePreferTensor()`, `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
2073*5e2c5519SMatthew G. Knepley @*/
DMPlexGetInterpolatePreferTensor(DM dm,PetscBool * preferTensor)2074*5e2c5519SMatthew G. Knepley PetscErrorCode DMPlexGetInterpolatePreferTensor(DM dm, PetscBool *preferTensor)
2075*5e2c5519SMatthew G. Knepley {
2076*5e2c5519SMatthew G. Knepley   DM_Plex *plex = (DM_Plex *)dm->data;
2077*5e2c5519SMatthew G. Knepley 
2078*5e2c5519SMatthew G. Knepley   PetscFunctionBegin;
2079*5e2c5519SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2080*5e2c5519SMatthew G. Knepley   PetscAssertPointer(preferTensor, 2);
2081*5e2c5519SMatthew G. Knepley   *preferTensor = plex->interpolatePreferTensor;
2082*5e2c5519SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2083*5e2c5519SMatthew G. Knepley }
2084*5e2c5519SMatthew G. Knepley 
2085*5e2c5519SMatthew G. Knepley /*@
2086*5e2c5519SMatthew G. Knepley   DMPlexSetInterpolatePreferTensor - Set the flag to prefer tensor order when interpolating a cell
2087*5e2c5519SMatthew G. Knepley 
2088*5e2c5519SMatthew G. Knepley   Logically Collective
2089*5e2c5519SMatthew G. Knepley 
2090*5e2c5519SMatthew G. Knepley   Input Parameters:
2091*5e2c5519SMatthew G. Knepley + dm           - The `DMPLEX` object
2092*5e2c5519SMatthew G. Knepley - preferTensor - Flag to prefer tensor order
2093*5e2c5519SMatthew G. Knepley 
2094*5e2c5519SMatthew G. Knepley   Level: intermediate
2095*5e2c5519SMatthew G. Knepley 
2096*5e2c5519SMatthew G. Knepley   Notes:
2097*5e2c5519SMatthew G. Knepley   Currently, this just affects triangular prisms,
2098*5e2c5519SMatthew G. Knepley 
2099*5e2c5519SMatthew G. Knepley .seealso: `DMPlexGetInterpolatePreferTensor()`, `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
2100*5e2c5519SMatthew G. Knepley @*/
DMPlexSetInterpolatePreferTensor(DM dm,PetscBool preferTensor)2101*5e2c5519SMatthew G. Knepley PetscErrorCode DMPlexSetInterpolatePreferTensor(DM dm, PetscBool preferTensor)
2102*5e2c5519SMatthew G. Knepley {
2103*5e2c5519SMatthew G. Knepley   DM_Plex *plex = (DM_Plex *)dm->data;
2104*5e2c5519SMatthew G. Knepley 
2105*5e2c5519SMatthew G. Knepley   PetscFunctionBegin;
2106*5e2c5519SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2107*5e2c5519SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, preferTensor, 2);
2108*5e2c5519SMatthew G. Knepley   plex->interpolatePreferTensor = preferTensor;
2109*5e2c5519SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2110*5e2c5519SMatthew G. Knepley }
2111