xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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 
7e8f14785SLisandro Dalcin /* HashIJKL */
8e8f14785SLisandro Dalcin 
9e8f14785SLisandro Dalcin #include <petsc/private/hashmap.h>
10e8f14785SLisandro Dalcin 
11e8f14785SLisandro Dalcin typedef struct _PetscHashIJKLKey { PetscInt i, j, k, l; } PetscHashIJKLKey;
12e8f14785SLisandro Dalcin 
13e8f14785SLisandro Dalcin #define PetscHashIJKLKeyHash(key) \
14e8f14785SLisandro Dalcin   PetscHashCombine(PetscHashCombine(PetscHashInt((key).i),PetscHashInt((key).j)), \
15e8f14785SLisandro Dalcin                    PetscHashCombine(PetscHashInt((key).k),PetscHashInt((key).l)))
16e8f14785SLisandro Dalcin 
17e8f14785SLisandro Dalcin #define PetscHashIJKLKeyEqual(k1,k2) \
18e8f14785SLisandro Dalcin   (((k1).i==(k2).i) ? ((k1).j==(k2).j) ? ((k1).k==(k2).k) ? ((k1).l==(k2).l) : 0 : 0 : 0)
19e8f14785SLisandro Dalcin 
20999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKL, PetscHashIJKLKey, PetscInt, PetscHashIJKLKeyHash, PetscHashIJKLKeyEqual, -1))
21e8f14785SLisandro Dalcin 
223be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1};
233be36e83SMatthew G. Knepley 
243be36e83SMatthew G. Knepley typedef struct _PetscHashIJKLRemoteKey { PetscSFNode i, j, k, l; } PetscHashIJKLRemoteKey;
253be36e83SMatthew G. Knepley 
263be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \
273be36e83SMatthew G. Knepley   PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index),PetscHashInt((key).j.rank + (key).j.index)), \
283be36e83SMatthew G. Knepley                    PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index),PetscHashInt((key).l.rank + (key).l.index)))
293be36e83SMatthew G. Knepley 
303be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyEqual(k1,k2) \
313be36e83SMatthew 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)
323be36e83SMatthew G. Knepley 
33999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode))
343be36e83SMatthew G. Knepley 
353be36e83SMatthew G. Knepley static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[])
363be36e83SMatthew G. Knepley {
373be36e83SMatthew G. Knepley   PetscInt i;
383be36e83SMatthew G. Knepley 
393be36e83SMatthew G. Knepley   PetscFunctionBegin;
403be36e83SMatthew G. Knepley   for (i = 1; i < n; ++i) {
413be36e83SMatthew G. Knepley     PetscSFNode x = A[i];
423be36e83SMatthew G. Knepley     PetscInt    j;
433be36e83SMatthew G. Knepley 
443be36e83SMatthew G. Knepley     for (j = i-1; j >= 0; --j) {
453be36e83SMatthew G. Knepley       if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break;
463be36e83SMatthew G. Knepley       A[j+1] = A[j];
473be36e83SMatthew G. Knepley     }
483be36e83SMatthew G. Knepley     A[j+1] = x;
493be36e83SMatthew G. Knepley   }
503be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
513be36e83SMatthew G. Knepley }
529f074e33SMatthew G Knepley 
539f074e33SMatthew G Knepley /*
54439ece16SMatthew G. Knepley   DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone
55439ece16SMatthew G. Knepley */
56412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
57439ece16SMatthew G. Knepley {
58412e9a14SMatthew G. Knepley   DMPolytopeType *typesTmp;
59412e9a14SMatthew G. Knepley   PetscInt       *sizesTmp, *facesTmp;
60439ece16SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize;
61439ece16SMatthew G. Knepley 
62439ece16SMatthew G. Knepley   PetscFunctionBegin;
63439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(cone, 3);
655f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
665f80ce2aSJacob Faibussowitsch   if (faceTypes) CHKERRQ(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize),           MPIU_INT, &typesTmp));
675f80ce2aSJacob Faibussowitsch   if (faceSizes) CHKERRQ(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize),           MPIU_INT, &sizesTmp));
685f80ce2aSJacob Faibussowitsch   if (faces)     CHKERRQ(DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp));
69ba2698f1SMatthew G. Knepley   switch (ct) {
70ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_POINT:
71ba2698f1SMatthew G. Knepley       if (numFaces) *numFaces = 0;
72ba2698f1SMatthew G. Knepley       break;
73ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
74412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 2;
75412e9a14SMatthew G. Knepley       if (faceTypes) {
76412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT;
77412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
78412e9a14SMatthew G. Knepley       }
79412e9a14SMatthew G. Knepley       if (faceSizes) {
80412e9a14SMatthew G. Knepley         sizesTmp[0] = 1; sizesTmp[1] = 1;
81412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
82412e9a14SMatthew G. Knepley       }
83c49d9212SMatthew G. Knepley       if (faces) {
84c49d9212SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
85c49d9212SMatthew G. Knepley         *faces = facesTmp;
86c49d9212SMatthew G. Knepley       }
87412e9a14SMatthew G. Knepley       break;
88412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
89c49d9212SMatthew G. Knepley       if (numFaces) *numFaces = 2;
90412e9a14SMatthew G. Knepley       if (faceTypes) {
91412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT;
92412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
93412e9a14SMatthew G. Knepley       }
94412e9a14SMatthew G. Knepley       if (faceSizes) {
95412e9a14SMatthew G. Knepley         sizesTmp[0] = 1; sizesTmp[1] = 1;
96412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
97412e9a14SMatthew G. Knepley       }
98412e9a14SMatthew G. Knepley       if (faces) {
99412e9a14SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
100412e9a14SMatthew G. Knepley         *faces = facesTmp;
101412e9a14SMatthew G. Knepley       }
102c49d9212SMatthew G. Knepley       break;
103ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
104412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 3;
105412e9a14SMatthew G. Knepley       if (faceTypes) {
106412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT;
107412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
108412e9a14SMatthew G. Knepley       }
109412e9a14SMatthew G. Knepley       if (faceSizes) {
110412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2;
111412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
112412e9a14SMatthew G. Knepley       }
1139a5b13a2SMatthew G Knepley       if (faces) {
1149a5b13a2SMatthew G Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
1159a5b13a2SMatthew G Knepley         facesTmp[2] = cone[1]; facesTmp[3] = cone[2];
1169a5b13a2SMatthew G Knepley         facesTmp[4] = cone[2]; facesTmp[5] = cone[0];
1179a5b13a2SMatthew G Knepley         *faces = facesTmp;
1189a5b13a2SMatthew G Knepley       }
1199f074e33SMatthew G Knepley       break;
120ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1219a5b13a2SMatthew G Knepley       /* Vertices follow right hand rule */
122412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 4;
123412e9a14SMatthew G. Knepley       if (faceTypes) {
124412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT; typesTmp[3] = DM_POLYTOPE_SEGMENT;
125412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
126412e9a14SMatthew G. Knepley       }
127412e9a14SMatthew G. Knepley       if (faceSizes) {
128412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2;
129412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
130412e9a14SMatthew G. Knepley       }
1319a5b13a2SMatthew G Knepley       if (faces) {
1329a5b13a2SMatthew G Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
1339a5b13a2SMatthew G Knepley         facesTmp[2] = cone[1]; facesTmp[3] = cone[2];
1349a5b13a2SMatthew G Knepley         facesTmp[4] = cone[2]; facesTmp[5] = cone[3];
1359a5b13a2SMatthew G Knepley         facesTmp[6] = cone[3]; facesTmp[7] = cone[0];
1369a5b13a2SMatthew G Knepley         *faces = facesTmp;
1379a5b13a2SMatthew G Knepley       }
138412e9a14SMatthew G. Knepley       break;
139412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1409a5b13a2SMatthew G Knepley       if (numFaces) *numFaces = 4;
141412e9a14SMatthew G. Knepley       if (faceTypes) {
142412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR; typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
143412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
144412e9a14SMatthew G. Knepley       }
145412e9a14SMatthew G. Knepley       if (faceSizes) {
146412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2;
147412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
148412e9a14SMatthew G. Knepley       }
149412e9a14SMatthew G. Knepley       if (faces) {
150412e9a14SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
151412e9a14SMatthew G. Knepley         facesTmp[2] = cone[2]; facesTmp[3] = cone[3];
152412e9a14SMatthew G. Knepley         facesTmp[4] = cone[0]; facesTmp[5] = cone[2];
153412e9a14SMatthew G. Knepley         facesTmp[6] = cone[1]; facesTmp[7] = cone[3];
154412e9a14SMatthew G. Knepley         *faces = facesTmp;
155412e9a14SMatthew G. Knepley       }
1569f074e33SMatthew G Knepley       break;
157ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
1582e1b13c2SMatthew G. Knepley       /* Vertices of first face follow right hand rule and normal points away from last vertex */
159412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 4;
160412e9a14SMatthew G. Knepley       if (faceTypes) {
161412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE;
162412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
163412e9a14SMatthew G. Knepley       }
164412e9a14SMatthew G. Knepley       if (faceSizes) {
165412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3;
166412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
167412e9a14SMatthew G. Knepley       }
1689a5b13a2SMatthew G Knepley       if (faces) {
1692e1b13c2SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];
1702e1b13c2SMatthew G. Knepley         facesTmp[3] = cone[0]; facesTmp[4]  = cone[3]; facesTmp[5]  = cone[1];
1712e1b13c2SMatthew G. Knepley         facesTmp[6] = cone[0]; facesTmp[7]  = cone[2]; facesTmp[8]  = cone[3];
1722e1b13c2SMatthew G. Knepley         facesTmp[9] = cone[2]; facesTmp[10] = cone[1]; facesTmp[11] = cone[3];
1739a5b13a2SMatthew G Knepley         *faces = facesTmp;
1749a5b13a2SMatthew G Knepley       }
1759a5b13a2SMatthew G Knepley       break;
176ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
177e368ef20SMatthew G. Knepley       /*  7--------6
178e368ef20SMatthew G. Knepley          /|       /|
179e368ef20SMatthew G. Knepley         / |      / |
180e368ef20SMatthew G. Knepley        4--------5  |
181e368ef20SMatthew G. Knepley        |  |     |  |
182e368ef20SMatthew G. Knepley        |  |     |  |
183e368ef20SMatthew G. Knepley        |  1--------2
184e368ef20SMatthew G. Knepley        | /      | /
185e368ef20SMatthew G. Knepley        |/       |/
186e368ef20SMatthew G. Knepley        0--------3
187e368ef20SMatthew G. Knepley        */
188412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 6;
189412e9a14SMatthew G. Knepley       if (faceTypes) {
190412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
191412e9a14SMatthew G. Knepley         typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
192412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
193412e9a14SMatthew G. Knepley       }
194412e9a14SMatthew G. Knepley       if (faceSizes) {
195412e9a14SMatthew G. Knepley         sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4;
196412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
197412e9a14SMatthew G. Knepley       }
1989a5b13a2SMatthew G Knepley       if (faces) {
19951cfd6a4SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
20051cfd6a4SMatthew G. Knepley         facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5]; facesTmp[6]  = cone[6]; facesTmp[7]  = cone[7]; /* Top */
20151cfd6a4SMatthew G. Knepley         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[3]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; /* Front */
20251cfd6a4SMatthew G. Knepley         facesTmp[12] = cone[2]; facesTmp[13] = cone[1]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; /* Back */
20351cfd6a4SMatthew G. Knepley         facesTmp[16] = cone[3]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; /* Right */
20451cfd6a4SMatthew G. Knepley         facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[1]; /* Left */
2059a5b13a2SMatthew G Knepley         *faces = facesTmp;
2069a5b13a2SMatthew G Knepley       }
20799836e0eSStefano Zampini       break;
208ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
209412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 5;
210412e9a14SMatthew G. Knepley       if (faceTypes) {
211412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE;
212412e9a14SMatthew G. Knepley         typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
213412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
214412e9a14SMatthew G. Knepley       }
215412e9a14SMatthew G. Knepley       if (faceSizes) {
216412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3;
217412e9a14SMatthew G. Knepley         sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4;
218412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
219412e9a14SMatthew G. Knepley       }
220ba2698f1SMatthew G. Knepley       if (faces) {
221412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];                         /* Bottom */
222412e9a14SMatthew G. Knepley         facesTmp[3]  = cone[3]; facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5];                         /* Top */
223412e9a14SMatthew G. Knepley         facesTmp[6]  = cone[0]; facesTmp[7]  = cone[2]; facesTmp[8]  = cone[4]; facesTmp[9]  = cone[3]; /* Back left */
224412e9a14SMatthew G. Knepley         facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[5]; facesTmp[13] = cone[4]; /* Front */
225412e9a14SMatthew G. Knepley         facesTmp[14] = cone[1]; facesTmp[15] = cone[0]; facesTmp[16] = cone[3]; facesTmp[17] = cone[5]; /* Back right */
226ba2698f1SMatthew G. Knepley         *faces = facesTmp;
22799836e0eSStefano Zampini       }
22899836e0eSStefano Zampini       break;
229ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
230412e9a14SMatthew G. Knepley       if (numFaces)     *numFaces = 5;
231412e9a14SMatthew G. Knepley       if (faceTypes) {
232412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE;
233412e9a14SMatthew G. Knepley         typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
234412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
235412e9a14SMatthew G. Knepley       }
236412e9a14SMatthew G. Knepley       if (faceSizes) {
237412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3;
238412e9a14SMatthew G. Knepley         sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4;
239412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
240412e9a14SMatthew G. Knepley       }
24199836e0eSStefano Zampini       if (faces) {
242412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];                         /* Bottom */
243412e9a14SMatthew G. Knepley         facesTmp[3]  = cone[3]; facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5];                         /* Top */
244412e9a14SMatthew G. Knepley         facesTmp[6]  = cone[0]; facesTmp[7]  = cone[1]; facesTmp[8]  = cone[3]; facesTmp[9]  = cone[4]; /* Back left */
245412e9a14SMatthew G. Knepley         facesTmp[10] = cone[1]; facesTmp[11] = cone[2]; facesTmp[12] = cone[4]; facesTmp[13] = cone[5]; /* Back right */
246412e9a14SMatthew G. Knepley         facesTmp[14] = cone[2]; facesTmp[15] = cone[0]; facesTmp[16] = cone[5]; facesTmp[17] = cone[3]; /* Front */
24799836e0eSStefano Zampini         *faces = facesTmp;
24899836e0eSStefano Zampini       }
249412e9a14SMatthew G. Knepley       break;
250412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
251412e9a14SMatthew G. Knepley       /*  7--------6
252412e9a14SMatthew G. Knepley          /|       /|
253412e9a14SMatthew G. Knepley         / |      / |
254412e9a14SMatthew G. Knepley        4--------5  |
255412e9a14SMatthew G. Knepley        |  |     |  |
256412e9a14SMatthew G. Knepley        |  |     |  |
257412e9a14SMatthew G. Knepley        |  3--------2
258412e9a14SMatthew G. Knepley        | /      | /
259412e9a14SMatthew G. Knepley        |/       |/
260412e9a14SMatthew G. Knepley        0--------1
261412e9a14SMatthew G. Knepley        */
262412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 6;
263412e9a14SMatthew G. Knepley       if (faceTypes) {
264412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;    typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;    typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
265412e9a14SMatthew G. Knepley         typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
266412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
267412e9a14SMatthew G. Knepley       }
268412e9a14SMatthew G. Knepley       if (faceSizes) {
269412e9a14SMatthew G. Knepley         sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4;
270412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
271412e9a14SMatthew G. Knepley       }
272412e9a14SMatthew G. Knepley       if (faces) {
273412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
274412e9a14SMatthew G. Knepley         facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5]; facesTmp[6]  = cone[6]; facesTmp[7]  = cone[7]; /* Top */
275412e9a14SMatthew G. Knepley         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[1]; facesTmp[10] = cone[4]; facesTmp[11] = cone[5]; /* Front */
276412e9a14SMatthew G. Knepley         facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[5]; facesTmp[15] = cone[6]; /* Right */
277412e9a14SMatthew G. Knepley         facesTmp[16] = cone[2]; facesTmp[17] = cone[3]; facesTmp[18] = cone[6]; facesTmp[19] = cone[7]; /* Back */
278412e9a14SMatthew G. Knepley         facesTmp[20] = cone[3]; facesTmp[21] = cone[0]; facesTmp[22] = cone[7]; facesTmp[23] = cone[4]; /* Left */
279412e9a14SMatthew G. Knepley         *faces = facesTmp;
280412e9a14SMatthew G. Knepley       }
28199836e0eSStefano Zampini       break;
282da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
283da9060c4SMatthew G. Knepley       /*
284da9060c4SMatthew G. Knepley        4----
285da9060c4SMatthew G. Knepley        |\-\ \-----
286da9060c4SMatthew G. Knepley        | \ -\     \
287da9060c4SMatthew G. Knepley        |  1--\-----2
288da9060c4SMatthew G. Knepley        | /    \   /
289da9060c4SMatthew G. Knepley        |/      \ /
290da9060c4SMatthew G. Knepley        0--------3
291da9060c4SMatthew G. Knepley        */
292da9060c4SMatthew G. Knepley       if (numFaces) *numFaces = 5;
293da9060c4SMatthew G. Knepley       if (faceTypes) {
294da9060c4SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
295da9060c4SMatthew G. Knepley         typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; typesTmp[4] = DM_POLYTOPE_TRIANGLE;
296da9060c4SMatthew G. Knepley         *faceTypes = typesTmp;
297da9060c4SMatthew G. Knepley       }
298da9060c4SMatthew G. Knepley       if (faceSizes) {
299da9060c4SMatthew G. Knepley         sizesTmp[0] = 4;
300da9060c4SMatthew G. Knepley         sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; sizesTmp[4] = 3;
301da9060c4SMatthew G. Knepley         *faceSizes = sizesTmp;
302da9060c4SMatthew G. Knepley       }
303da9060c4SMatthew G. Knepley       if (faces) {
304da9060c4SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
305da9060c4SMatthew G. Knepley         facesTmp[4]  = cone[0]; facesTmp[5]  = cone[3]; facesTmp[6]  = cone[4];                         /* Front */
306da9060c4SMatthew G. Knepley         facesTmp[7]  = cone[3]; facesTmp[8]  = cone[2]; facesTmp[9]  = cone[4];                         /* Right */
307da9060c4SMatthew G. Knepley         facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[4];                         /* Back */
308da9060c4SMatthew G. Knepley         facesTmp[13] = cone[1]; facesTmp[14] = cone[0]; facesTmp[15] = cone[4];                         /* Left */
309da9060c4SMatthew G. Knepley         *faces = facesTmp;
310da9060c4SMatthew G. Knepley       }
311da9060c4SMatthew G. Knepley       break;
31298921bdaSJacob Faibussowitsch     default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
31399836e0eSStefano Zampini   }
31499836e0eSStefano Zampini   PetscFunctionReturn(0);
31599836e0eSStefano Zampini }
31699836e0eSStefano Zampini 
317412e9a14SMatthew G. Knepley PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
31899836e0eSStefano Zampini {
31999836e0eSStefano Zampini   PetscFunctionBegin;
3205f80ce2aSJacob Faibussowitsch   if (faceTypes) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceTypes));
3215f80ce2aSJacob Faibussowitsch   if (faceSizes) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceSizes));
3225f80ce2aSJacob Faibussowitsch   if (faces)     CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces));
32399836e0eSStefano Zampini   PetscFunctionReturn(0);
32499836e0eSStefano Zampini }
32599836e0eSStefano Zampini 
3269a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
3279a5b13a2SMatthew G Knepley static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
3289f074e33SMatthew G Knepley {
329412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
3309a5b13a2SMatthew G Knepley   PetscHashIJKL  faceTable;
331412e9a14SMatthew G. Knepley   PetscInt       faceTypeNum[DM_NUM_POLYTOPES];
3329318fe57SMatthew G. Knepley   PetscInt       depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd;
3339f074e33SMatthew G Knepley 
3349f074e33SMatthew G Knepley   PetscFunctionBegin;
3355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
3365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHashIJKLCreate(&faceTable));
3375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
3385f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
339412e9a14SMatthew G. Knepley   /* Number new faces and save face vertices in hash table */
3405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
341412e9a14SMatthew G. Knepley   fEnd = fStart;
342412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
343412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
344412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
345ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
346412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
34799836e0eSStefano Zampini 
3485f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellType(dm, c, &ct));
3495f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, c, &cone));
3505f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
351412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
352412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
353412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
354412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
3559a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
356e8f14785SLisandro Dalcin       PetscHashIter        iter;
357e8f14785SLisandro Dalcin       PetscBool            missing;
3589f074e33SMatthew G Knepley 
3595f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
360412e9a14SMatthew G. Knepley       key.i = face[0];
361412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
362412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
363412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
3645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSortInt(faceSize, (PetscInt *) &key));
3655f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHashIJKLPut(faceTable, key, &iter, &missing));
366e9fa77a1SMatthew G. Knepley       if (missing) {
3675f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscHashIJKLIterSet(faceTable, iter, fEnd++));
368412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
369e9fa77a1SMatthew G. Knepley       }
3709a5b13a2SMatthew G Knepley     }
3715f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
37299836e0eSStefano Zampini   }
373412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
374412e9a14SMatthew G. Knepley   {
375412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
37699836e0eSStefano Zampini 
377412e9a14SMatthew G. Knepley     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {if (faceTypeNum[ct]) ++numFT; faceTypeStart[ct] = 0;}
378412e9a14SMatthew G. Knepley     if (numFT > 1) {
3795f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHashIJKLClear(faceTable));
380412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
381412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct-1] + faceTypeNum[ct-1];
382412e9a14SMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
383412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
384412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
385ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
386412e9a14SMatthew G. Knepley         PetscInt              numFaces, cf, foff = 0;
38799836e0eSStefano Zampini 
3885f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCellType(dm, c, &ct));
3895f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCone(dm, c, &cone));
3905f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
391412e9a14SMatthew G. Knepley         for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
392412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
393412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
394412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
39599836e0eSStefano Zampini           PetscHashIJKLKey     key;
39699836e0eSStefano Zampini           PetscHashIter        iter;
39799836e0eSStefano Zampini           PetscBool            missing;
39899836e0eSStefano Zampini 
3995f80ce2aSJacob Faibussowitsch           PetscCheck(faceSize <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
400412e9a14SMatthew G. Knepley           key.i = face[0];
401412e9a14SMatthew G. Knepley           key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
402412e9a14SMatthew G. Knepley           key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
403412e9a14SMatthew G. Knepley           key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
4045f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSortInt(faceSize, (PetscInt *) &key));
4055f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscHashIJKLPut(faceTable, key, &iter, &missing));
4065f80ce2aSJacob Faibussowitsch           if (missing) CHKERRQ(PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
40799836e0eSStefano Zampini         }
4085f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
40999836e0eSStefano Zampini       }
410412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
4112c71b3e2SJacob Faibussowitsch         PetscCheckFalse(faceTypeStart[ct] != faceTypeStart[ct-1] + faceTypeNum[ct],PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent numbering for cell type %s, %D != %D + %D", DMPolytopeTypes[ct], faceTypeStart[ct], faceTypeStart[ct-1], faceTypeNum[ct]);
4129a5b13a2SMatthew G Knepley       }
4139a5b13a2SMatthew G Knepley     }
414412e9a14SMatthew G. Knepley   }
415412e9a14SMatthew G. Knepley   /* Add new points, always at the end of the numbering */
4165f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &Np));
4175f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
4189a5b13a2SMatthew G Knepley   /* Set cone sizes */
419412e9a14SMatthew G. Knepley   /*   Must create the celltype label here so that we do not automatically try to compute the types */
4205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(idm, "celltype"));
4215f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellTypeLabel(idm, &ctLabel));
4229a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
423412e9a14SMatthew G. Knepley     DMPolytopeType ct;
424412e9a14SMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, p;
4259f074e33SMatthew G Knepley 
426412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
4275f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
428412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
4295f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
4305f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetConeSize(idm, p, coneSize));
4315f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCellType(dm, p, &ct));
4325f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetCellType(idm, p, ct));
4339f074e33SMatthew G Knepley     }
4349f074e33SMatthew G Knepley   }
435412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
436412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
437412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
438412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
439412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
440412e9a14SMatthew G. Knepley 
4415f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellType(dm, c, &ct));
4425f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, c, &cone));
4435f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
4445f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetCellType(idm, c, ct));
4455f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetConeSize(idm, c, numFaces));
446412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
447412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
448412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
449412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
450412e9a14SMatthew G. Knepley       PetscHashIJKLKey     key;
451412e9a14SMatthew G. Knepley       PetscHashIter        iter;
452412e9a14SMatthew G. Knepley       PetscBool            missing;
453412e9a14SMatthew G. Knepley       PetscInt             f;
454412e9a14SMatthew G. Knepley 
4552c71b3e2SJacob Faibussowitsch       PetscCheckFalse(faceSize > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize);
456412e9a14SMatthew G. Knepley       key.i = face[0];
457412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
458412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
459412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
4605f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSortInt(faceSize, (PetscInt *) &key));
4615f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHashIJKLPut(faceTable, key, &iter, &missing));
462*28b400f6SJacob Faibussowitsch       PetscCheck(!missing,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %D, lf %D)", c, cf);
4635f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHashIJKLIterGet(faceTable, iter, &f));
4645f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetConeSize(idm, f, faceSize));
4655f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetCellType(idm, f, faceType));
466412e9a14SMatthew G. Knepley     }
4675f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
4689f074e33SMatthew G Knepley   }
4695f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(idm));
470412e9a14SMatthew G. Knepley   /* Initialize cones so we do not need the bash table to tell us that a cone has been set */
471412e9a14SMatthew G. Knepley   {
472412e9a14SMatthew G. Knepley     PetscSection cs;
473412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
4749a5b13a2SMatthew G Knepley 
4755f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSection(idm, &cs));
4765f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCones(idm, &cones));
4775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(cs, &csize));
478412e9a14SMatthew G. Knepley     for (c = 0; c < csize; ++c) cones[c] = -1;
479412e9a14SMatthew G. Knepley   }
480412e9a14SMatthew G. Knepley   /* Set cones */
481412e9a14SMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
482412e9a14SMatthew G. Knepley     const PetscInt *cone;
483412e9a14SMatthew G. Knepley     PetscInt        pStart, pEnd, p;
484412e9a14SMatthew G. Knepley 
485412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
4865f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
487412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
4885f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(dm, p, &cone));
4895f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetCone(idm, p, cone));
4905f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeOrientation(dm, p, &cone));
4915f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetConeOrientation(idm, p, cone));
4929f074e33SMatthew G Knepley     }
4939a5b13a2SMatthew G Knepley   }
494412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
495412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
496412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
497ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
498412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
49999836e0eSStefano Zampini 
5005f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellType(dm, c, &ct));
5015f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, c, &cone));
5025f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
503412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
504412e9a14SMatthew G. Knepley       DMPolytopeType   faceType = faceTypes[cf];
505412e9a14SMatthew G. Knepley       const PetscInt   faceSize = faceSizes[cf];
506412e9a14SMatthew G. Knepley       const PetscInt  *face     = &faces[foff];
507412e9a14SMatthew G. Knepley       const PetscInt  *fcone;
5089a5b13a2SMatthew G Knepley       PetscHashIJKLKey key;
509e8f14785SLisandro Dalcin       PetscHashIter    iter;
510e8f14785SLisandro Dalcin       PetscBool        missing;
511412e9a14SMatthew G. Knepley       PetscInt         f;
5129f074e33SMatthew G Knepley 
5132c71b3e2SJacob Faibussowitsch       PetscCheckFalse(faceSize > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize);
514412e9a14SMatthew G. Knepley       key.i = face[0];
515412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
516412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
517412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
5185f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSortInt(faceSize, (PetscInt *) &key));
5195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHashIJKLPut(faceTable, key, &iter, &missing));
5205f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHashIJKLIterGet(faceTable, iter, &f));
5215f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexInsertCone(idm, c, cf, f));
5225f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(idm, f, &fcone));
5235f80ce2aSJacob Faibussowitsch       if (fcone[0] < 0) CHKERRQ(DMPlexSetCone(idm, f, face));
524412e9a14SMatthew G. Knepley       {
525412e9a14SMatthew G. Knepley         const PetscInt *cone;
526412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
527a74221b0SStefano Zampini 
5285f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetConeSize(idm, f, &coneSize));
5295f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCone(idm, f, &cone));
5302c71b3e2SJacob Faibussowitsch         PetscCheckFalse(coneSize != faceSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %D for face %D should be %D", coneSize, f, faceSize);
531d89e6e46SMatthew G. Knepley         /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
5325f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt));
5335f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexInsertConeOrientation(idm, c, cf, ornt));
53499836e0eSStefano Zampini       }
53599836e0eSStefano Zampini     }
5365f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
53799836e0eSStefano Zampini   }
5385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHashIJKLDestroy(&faceTable));
5395f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(idm));
5405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(idm));
5419f074e33SMatthew G Knepley   PetscFunctionReturn(0);
5429f074e33SMatthew G Knepley }
5439f074e33SMatthew G Knepley 
544f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
545f80536cbSVaclav Hapla {
546f80536cbSVaclav Hapla   PetscInt            nleaves;
547f80536cbSVaclav Hapla   PetscInt            nranks;
548a0d42dbcSVaclav Hapla   const PetscMPIInt  *ranks=NULL;
549a0d42dbcSVaclav Hapla   const PetscInt     *roffset=NULL, *rmine=NULL, *rremote=NULL;
550f80536cbSVaclav Hapla   PetscInt            n, o, r;
551f80536cbSVaclav Hapla 
552f80536cbSVaclav Hapla   PetscFunctionBegin;
5535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
554f80536cbSVaclav Hapla   nleaves = roffset[nranks];
5555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
556f80536cbSVaclav Hapla   for (r=0; r<nranks; r++) {
557f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
558f80536cbSVaclav Hapla        - to unify order with the other side */
559f80536cbSVaclav Hapla     o = roffset[r];
560f80536cbSVaclav Hapla     n = roffset[r+1] - o;
5615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
5625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
5635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
564f80536cbSVaclav Hapla   }
565f80536cbSVaclav Hapla   PetscFunctionReturn(0);
566f80536cbSVaclav Hapla }
567f80536cbSVaclav Hapla 
56827d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
5692e745bdaSMatthew G. Knepley {
570d89e6e46SMatthew G. Knepley   PetscSF            sf;
571d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
572d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
573d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
574d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
575d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
576d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
577d89e6e46SMatthew G. Knepley   PetscInt         (*roots)[4],      (*leaves)[4], mainCone[4];
578d89e6e46SMatthew G. Knepley   PetscMPIInt      (*rootsRanks)[4], (*leavesRanks)[4];
5792e745bdaSMatthew G. Knepley   MPI_Comm           comm;
58027d0e99aSVaclav Hapla   PetscMPIInt        rank, size;
5812e745bdaSMatthew G. Knepley   PetscInt           debug = 0;
5822e745bdaSMatthew G. Knepley 
5832e745bdaSMatthew G. Knepley   PetscFunctionBegin;
5845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
5855f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
5865f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
5875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &sf));
5885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
5895f80ce2aSJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) CHKERRQ(DMPlexCheckPointSF(dm));
5905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
591d89e6e46SMatthew G. Knepley   if (nroots < 0) PetscFunctionReturn(0);
5925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetUp(sf));
5935f80ce2aSJacob Faibussowitsch   CHKERRQ(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
594d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
595d89e6e46SMatthew G. Knepley     PetscInt coneSize;
5965f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dm, locals[p], &coneSize));
597d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
598d89e6e46SMatthew G. Knepley   }
5992c71b3e2SJacob Faibussowitsch   PetscCheckFalse(maxConeSize > 4,comm, PETSC_ERR_SUP, "This method does not support cones of size %D", maxConeSize);
6005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
6019e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
602d89e6e46SMatthew G. Knepley     const PetscInt *cone;
603d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
604d89e6e46SMatthew G. Knepley 
6055f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
6065f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, p, &cone));
607d89e6e46SMatthew G. Knepley     /* Ignore vertices */
60827d0e99aSVaclav Hapla     if (coneSize < 2) {
609d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
61027d0e99aSVaclav Hapla         roots[p][c]      = -1;
61127d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
61227d0e99aSVaclav Hapla       }
61327d0e99aSVaclav Hapla       continue;
61427d0e99aSVaclav Hapla     }
6152e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
616d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
6175f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFindInt(cone[c], nleaves, locals, &ind0));
6188a650c75SVaclav Hapla       if (ind0 < 0) {
6198a650c75SVaclav Hapla         roots[p][c]      = cone[c];
6208a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
621c8148b97SVaclav Hapla       } else {
6228a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
6238a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
6248a650c75SVaclav Hapla       }
6252e745bdaSMatthew G. Knepley     }
626d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
627d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
628d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
629d89e6e46SMatthew G. Knepley     }
6302e745bdaSMatthew G. Knepley   }
6319e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
632d89e6e46SMatthew G. Knepley     PetscInt c;
633d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
6348ccb905dSVaclav Hapla       leaves[p][c]      = -2;
6358ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
6368ccb905dSVaclav Hapla     }
637c8148b97SVaclav Hapla   }
6385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
6395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
6405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
6415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
642d89e6e46SMatthew G. Knepley   if (debug) {
6435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSynchronizedFlush(comm, NULL));
6445f80ce2aSJacob Faibussowitsch     if (!rank) CHKERRQ(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
645d89e6e46SMatthew G. Knepley   }
6465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
6479e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
648d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
649d89e6e46SMatthew G. Knepley     const PetscInt *cone;
650d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
651d89e6e46SMatthew G. Knepley 
652d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
6535f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellType(dm, p, &ct));
6545f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
6555f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, p, &cone));
656d89e6e46SMatthew G. Knepley     if (debug) {
6575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]  %4D: cone=[%4D %4D %4D %4D] roots=[(%d,%4D) (%d,%4D) (%d,%4D) (%d,%4D)] leaves=[(%d,%4D) (%d,%4D) (%d,%4D) (%d,%4D)]",
658d89e6e46SMatthew G. Knepley                                       rank, p, cone[0], cone[1], cone[2], cone[3],
659d89e6e46SMatthew G. Knepley                                       rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], rootsRanks[p][2], roots[p][2], rootsRanks[p][3], roots[p][3],
6605f80ce2aSJacob Faibussowitsch                                       leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1], leavesRanks[p][2], leaves[p][2], leavesRanks[p][3], leaves[p][3]));
661d89e6e46SMatthew G. Knepley     }
662d89e6e46SMatthew G. Knepley     if (leavesRanks[p][0] != rootsRanks[p][0] || leaves[p][0] != roots[p][0] ||
663d89e6e46SMatthew G. Knepley         leavesRanks[p][1] != rootsRanks[p][1] || leaves[p][1] != roots[p][1] ||
664d89e6e46SMatthew G. Knepley         leavesRanks[p][2] != rootsRanks[p][2] || leaves[p][2] != roots[p][2] ||
665d89e6e46SMatthew G. Knepley         leavesRanks[p][3] != rootsRanks[p][3] || leaves[p][3] != roots[p][3]) {
666d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
667d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
668d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
669d89e6e46SMatthew G. Knepley 
67027d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
671d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
6729dddd249SSatish Balay           mainCone[c] = leaves[p][c];
67327d0e99aSVaclav Hapla           continue;
67427d0e99aSVaclav Hapla         }
675f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
676f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
6775f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFindMPIInt((PetscMPIInt) leavesRanks[p][c], nranks, ranks, &r));
6782c71b3e2SJacob Faibussowitsch         PetscCheckFalse(r < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leaf (%d,%D): leaf rank not found among remote ranks", p, c, cone[c], rootsRanks[p][c], roots[p][c], leavesRanks[p][c], leaves[p][c]);
6792c71b3e2SJacob Faibussowitsch         PetscCheckFalse(ranks[r] < 0 || ranks[r] >= size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%D c=%D commsize=%d: ranks[%D] = %d makes no sense", p, c, size, r, ranks[r]);
680f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
681d89e6e46SMatthew G. Knepley         rS = roffset[r];
682d89e6e46SMatthew G. Knepley         rN = roffset[r+1] - rS;
6835f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
6842c71b3e2SJacob Faibussowitsch         PetscCheckFalse(ind0 < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leave (%d,%D): 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]);
685f80536cbSVaclav Hapla         /* Get the corresponding local point */
6865f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
687f80536cbSVaclav Hapla       }
6885f80ce2aSJacob Faibussowitsch       if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, " mainCone=[%4D %4D %4D %4D]\n", mainCone[0], mainCone[1], mainCone[2], mainCone[3]));
68927d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
6905f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
6915f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexOrientPoint(dm, p, o));
6925f80ce2aSJacob Faibussowitsch     } else if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, " ==\n"));
69323aaf07bSVaclav Hapla   }
69427d0e99aSVaclav Hapla   if (debug) {
6955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSynchronizedFlush(comm, NULL));
6965f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Barrier(comm));
6972e745bdaSMatthew G. Knepley   }
6985f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
6995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
7005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(rmine1, rremote1));
7012e745bdaSMatthew G. Knepley   PetscFunctionReturn(0);
7022e745bdaSMatthew G. Knepley }
7032e745bdaSMatthew G. Knepley 
7042e72742cSMatthew G. Knepley static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
7057bffde78SMichael Lange {
7062e72742cSMatthew G. Knepley   PetscInt       idx;
7072e72742cSMatthew G. Knepley   PetscMPIInt    rank;
7082e72742cSMatthew G. Knepley   PetscBool      flg;
7097bffde78SMichael Lange 
7107bffde78SMichael Lange   PetscFunctionBegin;
7115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(NULL, NULL, opt, &flg));
7122e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
7135f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
7145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
7155f80ce2aSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]%s %D %s %D\n", rank, idxname, idx, valname, a[idx]));
7165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSynchronizedFlush(comm, NULL));
7172e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7182e72742cSMatthew G. Knepley }
7192e72742cSMatthew G. Knepley 
7202e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
7212e72742cSMatthew G. Knepley {
7222e72742cSMatthew G. Knepley   PetscInt       idx;
7232e72742cSMatthew G. Knepley   PetscMPIInt    rank;
7242e72742cSMatthew G. Knepley   PetscBool      flg;
7252e72742cSMatthew G. Knepley 
7262e72742cSMatthew G. Knepley   PetscFunctionBegin;
7275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(NULL, NULL, opt, &flg));
7282e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
7295f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
7305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
7312e72742cSMatthew G. Knepley   if (idxname) {
7325f80ce2aSJacob Faibussowitsch     for (idx = 0; idx < n; ++idx) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]%s %D rank %D index %D\n", rank, idxname, idx, a[idx].rank, a[idx].index));
7332e72742cSMatthew G. Knepley   } else {
7345f80ce2aSJacob Faibussowitsch     for (idx = 0; idx < n; ++idx) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]rank %D index %D\n", rank, a[idx].rank, a[idx].index));
7352e72742cSMatthew G. Knepley   }
7365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSynchronizedFlush(comm, NULL));
7372e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7382e72742cSMatthew G. Knepley }
7392e72742cSMatthew G. Knepley 
7405f80ce2aSJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
7412e72742cSMatthew G. Knepley {
7423be36e83SMatthew G. Knepley   PetscSF         sf;
7433be36e83SMatthew G. Knepley   const PetscInt *locals;
7443be36e83SMatthew G. Knepley   PetscMPIInt     rank;
7452e72742cSMatthew G. Knepley 
7462e72742cSMatthew G. Knepley   PetscFunctionBegin;
7475f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
7485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &sf));
7495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
7505f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
7512e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
7522e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
7532e72742cSMatthew G. Knepley   } else {
7542e72742cSMatthew G. Knepley     PetscHashIJKey key;
7553be36e83SMatthew G. Knepley     PetscInt       l;
7562e72742cSMatthew G. Knepley 
7572e72742cSMatthew G. Knepley     key.i = remotePoint.index;
7582e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
7595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIJGet(remotehash, key, &l));
7603be36e83SMatthew G. Knepley     if (l >= 0) {
7613be36e83SMatthew G. Knepley       *localPoint = locals[l];
7625f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
7632e72742cSMatthew G. Knepley   }
7642e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7652e72742cSMatthew G. Knepley }
7662e72742cSMatthew G. Knepley 
7675f80ce2aSJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
7683be36e83SMatthew G. Knepley {
7693be36e83SMatthew G. Knepley   PetscSF            sf;
7703be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
7713be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
7723be36e83SMatthew G. Knepley   PetscInt           Nl, l;
7733be36e83SMatthew G. Knepley   PetscMPIInt        rank;
7743be36e83SMatthew G. Knepley 
7753be36e83SMatthew G. Knepley   PetscFunctionBegin;
7765f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
7775f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
7785f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &sf));
7795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
7803be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
7815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeBegin(sf, &rootdegree));
7825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeEnd(sf, &rootdegree));
7833be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
7845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFindInt(localPoint, Nl, locals, &l));
7855f80ce2aSJacob Faibussowitsch   if (l < 0) {if (mapFailed) *mapFailed = PETSC_TRUE;}
7865f80ce2aSJacob Faibussowitsch   else *remotePoint = remotes[l];
7873be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
7883be36e83SMatthew G. Knepley   owned:
7893be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
7903be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
7913be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
7923be36e83SMatthew G. Knepley }
7933be36e83SMatthew G. Knepley 
7943be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
7953be36e83SMatthew G. Knepley {
7963be36e83SMatthew G. Knepley   PetscSF         sf;
7973be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
7983be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
7993be36e83SMatthew G. Knepley 
8003be36e83SMatthew G. Knepley   PetscFunctionBegin;
8013be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
8025f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &sf));
8035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
8043be36e83SMatthew G. Knepley   if (Nl < 0) PetscFunctionReturn(0);
8055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFindInt(p, Nl, locals, &idx));
8063be36e83SMatthew G. Knepley   if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);}
8075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeBegin(sf, &rootdegree));
8085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeEnd(sf, &rootdegree));
8093be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
8103be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8113be36e83SMatthew G. Knepley }
8123be36e83SMatthew G. Knepley 
8133be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
8143be36e83SMatthew G. Knepley {
8153be36e83SMatthew G. Knepley   const PetscInt *cone;
8163be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
8173be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
8183be36e83SMatthew G. Knepley 
8193be36e83SMatthew G. Knepley   PetscFunctionBegin;
8205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
8215f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCone(dm, p, &cone));
8223be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
8233be36e83SMatthew G. Knepley     PetscBool pointShared;
8243be36e83SMatthew G. Knepley 
8255f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPointIsShared(dm, cone[c], &pointShared));
8263be36e83SMatthew G. Knepley     cShared = (PetscBool) (cShared && pointShared);
8273be36e83SMatthew G. Knepley   }
8283be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
8293be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8303be36e83SMatthew G. Knepley }
8313be36e83SMatthew G. Knepley 
8323be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
8333be36e83SMatthew G. Knepley {
8343be36e83SMatthew G. Knepley   const PetscInt *cone;
8353be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
8363be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
8373be36e83SMatthew G. Knepley 
8383be36e83SMatthew G. Knepley   PetscFunctionBegin;
8395f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
8405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCone(dm, p, &cone));
8413be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
8423be36e83SMatthew G. Knepley     PetscSFNode rcp;
8435f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
8443be36e83SMatthew G. Knepley 
8455f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
8465f80ce2aSJacob Faibussowitsch     if (mapFailed) {
8473be36e83SMatthew G. Knepley       cmin = missing;
8483be36e83SMatthew G. Knepley     } else {
8493be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
8503be36e83SMatthew G. Knepley     }
8513be36e83SMatthew G. Knepley   }
8523be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
8533be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8543be36e83SMatthew G. Knepley }
8553be36e83SMatthew G. Knepley 
8563be36e83SMatthew G. Knepley /*
8573be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
8583be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
8593be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
8603be36e83SMatthew G. Knepley */
8613be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
8623be36e83SMatthew G. Knepley {
8633be36e83SMatthew G. Knepley   MPI_Comm        comm;
8643be36e83SMatthew G. Knepley   const PetscInt *support;
865cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
8663be36e83SMatthew G. Knepley   PetscMPIInt     rank;
8673be36e83SMatthew G. Knepley 
8683be36e83SMatthew G. Knepley   PetscFunctionBegin;
8695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
8705f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
8715f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetOverlap(dm, &overlap));
8725f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight));
8735f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetPointHeight(dm, p, &height));
874cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight+1) {
875cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
8765f80ce2aSJacob Faibussowitsch     if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    Skipping face %D to avoid adding cell to hashmap since this is nonoverlapping mesh\n", rank, p));
877cf4dc471SVaclav Hapla     PetscFunctionReturn(0);
878cf4dc471SVaclav Hapla   }
8795f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize));
8805f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetSupport(dm, p, &support));
8815f80ce2aSJacob Faibussowitsch   if (candidates) CHKERRQ(PetscSectionGetOffset(candidateSection, p, &off));
8823be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
8833be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
8843be36e83SMatthew G. Knepley     const PetscInt *cone;
8853be36e83SMatthew G. Knepley     PetscSFNode     cpmin={-1,-1}, rp={-1,-1};
8863be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
8873be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
8883be36e83SMatthew G. Knepley     PetscHashIJKey  key;
8893be36e83SMatthew G. Knepley 
8903be36e83SMatthew G. Knepley     /* Only add point once */
8915f80ce2aSJacob Faibussowitsch     if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    Support face %D\n", rank, face));
8923be36e83SMatthew G. Knepley     key.i = p;
8933be36e83SMatthew G. Knepley     key.j = face;
8945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIJGet(faceHash, key, &f));
8953be36e83SMatthew G. Knepley     if (f >= 0) continue;
8965f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexConeIsShared(dm, face, &isShared));
8975f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeMinimum(dm, face, &cpmin));
8985f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
8993be36e83SMatthew G. Knepley     if (debug) {
9005f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]      Face point %D is shared: %d\n", rank, face, (int) isShared));
9015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]      Global point (%D, %D) Min Cone Point (%D, %D)\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index));
9023be36e83SMatthew G. Knepley     }
9033be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
9045f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHMapIJSet(faceHash, key, p));
9053be36e83SMatthew G. Knepley       if (candidates) {
9065f80ce2aSJacob Faibussowitsch         if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %D at idx %D\n[%d]     ", rank, face, idx, rank));
9075f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetConeSize(dm, face, &coneSize));
9085f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCone(dm, face, &cone));
9093be36e83SMatthew G. Knepley         candidates[off+idx].rank    = -1;
9103be36e83SMatthew G. Knepley         candidates[off+idx++].index = coneSize-1;
9113be36e83SMatthew G. Knepley         candidates[off+idx].rank    = rank;
9123be36e83SMatthew G. Knepley         candidates[off+idx++].index = face;
9133be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
9143be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
9153be36e83SMatthew G. Knepley 
9163be36e83SMatthew G. Knepley           if (cp == p) continue;
9175f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx], NULL));
9185f80ce2aSJacob Faibussowitsch           if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index));
9193be36e83SMatthew G. Knepley           ++idx;
9203be36e83SMatthew G. Knepley         }
9215f80ce2aSJacob Faibussowitsch         if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "\n"));
9223be36e83SMatthew G. Knepley       } else {
9233be36e83SMatthew G. Knepley         /* Add cone size to section */
9245f80ce2aSJacob Faibussowitsch         if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %D\n", rank, face));
9255f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetConeSize(dm, face, &coneSize));
9265f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscHMapIJSet(faceHash, key, p));
9275f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionAddDof(candidateSection, p, coneSize+1));
9283be36e83SMatthew G. Knepley       }
9293be36e83SMatthew G. Knepley     }
9303be36e83SMatthew G. Knepley   }
9313be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9323be36e83SMatthew G. Knepley }
9333be36e83SMatthew G. Knepley 
9342e72742cSMatthew G. Knepley /*@
9352e72742cSMatthew G. Knepley   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation
9362e72742cSMatthew G. Knepley 
937d083f849SBarry Smith   Collective on dm
9382e72742cSMatthew G. Knepley 
9392e72742cSMatthew G. Knepley   Input Parameters:
9402e72742cSMatthew G. Knepley + dm      - The interpolated DM
9412e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points
9422e72742cSMatthew G. Knepley 
9432e72742cSMatthew G. Knepley   Output Parameter:
9442e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points
9452e72742cSMatthew G. Knepley 
946f0cfc026SVaclav Hapla   Level: developer
9472e72742cSMatthew G. Knepley 
9482e72742cSMatthew G. Knepley    Note: All 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
9492e72742cSMatthew G. Knepley 
9502e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate()
9512e72742cSMatthew G. Knepley @*/
952e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
9532e72742cSMatthew G. Knepley {
9543be36e83SMatthew G. Knepley   MPI_Comm           comm;
9553be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
9563be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
9573be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
9583be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
9592e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
9602e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
9613be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
9623be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
9633be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
964f0cfc026SVaclav Hapla   PetscMPIInt        rank;
9652e72742cSMatthew G. Knepley 
9662e72742cSMatthew G. Knepley   PetscFunctionBegin;
967f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
968064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
9695f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexIsDistributed(dm, &flg));
970f0cfc026SVaclav Hapla   if (!flg) PetscFunctionReturn(0);
9713be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
9725f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPointSF(dm, pointSF));
9735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
9745f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
9755f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetOverlap(dm, &ov));
976*28b400f6SJacob Faibussowitsch   PetscCheck(!ov,comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
9775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug));
9785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view"));
9795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view"));
9805f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0));
9813be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
9825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
9832c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nr < 0,comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
9845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapIJCreate(&remoteHash));
9853be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
9863be36e83SMatthew G. Knepley     PetscHashIJKey key;
9872e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
9882e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
9895f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIJSet(remoteHash, key, l));
9907bffde78SMichael Lange   }
99166aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
9925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
9935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9945f80ce2aSJacob Faibussowitsch   CHKERRQ(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
9953be36e83SMatthew G. Knepley   /*
9963be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
9973be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
9983be36e83SMatthew G. Knepley   \begin{itemize}
9993be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
10003be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
10013be36e83SMatthew G. Knepley   \end{itemize}
10023be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
10033be36e83SMatthew 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
10043be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
10053be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
10063be36e83SMatthew G. Knepley   */
10073be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
10083be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
10093be36e83SMatthew G. Knepley        The array holds candidate shared faces, each face is refered to by the leaf point */
10105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(comm, &candidateSection));
10115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(candidateSection, 0, Nr));
10127bffde78SMichael Lange   {
10133be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
10142e72742cSMatthew G. Knepley 
10155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIJCreate(&faceHash));
10163be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
10173be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
10182e72742cSMatthew G. Knepley 
10195f80ce2aSJacob Faibussowitsch       if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %D\n", rank, p));
10205f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
10212e72742cSMatthew G. Knepley     }
10225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIJClear(faceHash));
10235f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetUp(candidateSection));
10245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
10255f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(candidatesSize, &candidates));
10263be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
10273be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
10282e72742cSMatthew G. Knepley 
10295f80ce2aSJacob Faibussowitsch       if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %D\n", rank, p));
10305f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
10312e72742cSMatthew G. Knepley     }
10325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIJDestroy(&faceHash));
10335f80ce2aSJacob Faibussowitsch     if (debug) CHKERRQ(PetscSynchronizedFlush(comm, NULL));
10347bffde78SMichael Lange   }
10355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) candidateSection, "Candidate Section"));
10365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view"));
10375f80ce2aSJacob Faibussowitsch   CHKERRQ(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
10383be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
10392e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
10407bffde78SMichael Lange   {
10417bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
10427bffde78SMichael Lange     PetscInt *remoteOffsets;
10432e72742cSMatthew G. Knepley 
10445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetMultiSF(pointSF, &sfMulti));
10455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateInverseSF(sfMulti, &sfInverse));
10465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreate(comm, &candidateRemoteSection));
10475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
10485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
10495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
10505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
10515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE));
10525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE));
10535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfInverse));
10545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfCandidates));
10555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(remoteOffsets));
10562e72742cSMatthew G. Knepley 
10575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section"));
10585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
10595f80ce2aSJacob Faibussowitsch     CHKERRQ(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
10607bffde78SMichael Lange   }
10613be36e83SMatthew 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 */
10627bffde78SMichael Lange   {
10633be36e83SMatthew G. Knepley     PetscHashIJKLRemote faceTable;
10643be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
10653be36e83SMatthew G. Knepley 
10665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHashIJKLRemoteCreate(&faceTable));
10672e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
10683be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
10692e72742cSMatthew G. Knepley       PetscInt deg;
10703be36e83SMatthew G. Knepley 
10712e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
10722e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
10732e72742cSMatthew G. Knepley 
10745f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
10755f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
10763be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
10772e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
10783be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
10793be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
10803be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx+1];
10813be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
10823be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
10833be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
10842e72742cSMatthew G. Knepley           const PetscInt        *join  = NULL;
10853be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
10863be36e83SMatthew G. Knepley           PetscHashIter          iter;
10875f80ce2aSJacob Faibussowitsch           PetscBool              missing,mapToLocalPointFailed = PETSC_FALSE;
10882e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
10892e72742cSMatthew G. Knepley 
10905f80ce2aSJacob Faibussowitsch           if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Checking face (%D, %D) at (%D, %D, %D) with cone size %D\n", rank, rface.rank, rface.index, r, idx, d, Np));
10912c71b3e2SJacob Faibussowitsch           PetscCheckFalse(Np > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle face (%D, %D) at (%D, %D, %D) with %D cone points", rface.rank, rface.index, r, idx, d, Np);
10923be36e83SMatthew G. Knepley           fcp0.rank  = rank;
10933be36e83SMatthew G. Knepley           fcp0.index = r;
10943be36e83SMatthew G. Knepley           d += Np;
10953be36e83SMatthew G. Knepley           /* Put remote face in hash table */
10963be36e83SMatthew G. Knepley           key.i = fcp0;
10973be36e83SMatthew G. Knepley           key.j = fcone[0];
10983be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
10993be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
11005f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSortSFNode(Np, (PetscSFNode *) &key));
11015f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing));
11023be36e83SMatthew G. Knepley           if (missing) {
11035f80ce2aSJacob Faibussowitsch             if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Setting remote face (%D, %D)\n", rank, rface.index, rface.rank));
11045f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscHashIJKLRemoteIterSet(faceTable, iter, rface));
11053be36e83SMatthew G. Knepley           } else {
11063be36e83SMatthew G. Knepley             PetscSFNode oface;
11073be36e83SMatthew G. Knepley 
11085f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface));
11093be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
11105f80ce2aSJacob Faibussowitsch               if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank));
11115f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscHashIJKLRemoteIterSet(faceTable, iter, rface));
11123be36e83SMatthew G. Knepley             }
11133be36e83SMatthew G. Knepley           }
11143be36e83SMatthew G. Knepley           /* Check for local face */
11152e72742cSMatthew G. Knepley           points[0] = r;
11163be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
11175f80ce2aSJacob Faibussowitsch             CHKERRQ(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p], &mapToLocalPointFailed));
11185f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
11195f80ce2aSJacob Faibussowitsch             if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Checking local candidate %D\n", rank, points[p]));
11207bffde78SMichael Lange           }
11215f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
11225f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
11237bffde78SMichael Lange           if (joinSize == 1) {
11243be36e83SMatthew G. Knepley             PetscSFNode lface;
11253be36e83SMatthew G. Knepley             PetscSFNode oface;
11263be36e83SMatthew G. Knepley 
11273be36e83SMatthew G. Knepley             /* Always replace with local face */
11283be36e83SMatthew G. Knepley             lface.rank  = rank;
11293be36e83SMatthew G. Knepley             lface.index = join[0];
11305f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface));
11315f80ce2aSJacob Faibussowitsch             if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing (%D, %D) with local face (%D, %D)\n", rank, oface.index, oface.rank, lface.index, lface.rank));
11325f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscHashIJKLRemoteIterSet(faceTable, iter, lface));
11337bffde78SMichael Lange           }
11345f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
11353be36e83SMatthew G. Knepley         }
11363be36e83SMatthew G. Knepley       }
11373be36e83SMatthew G. Knepley       /* Put back faces for this root */
11383be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
11393be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
11403be36e83SMatthew G. Knepley 
11415f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
11425f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
11433be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
11443be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11453be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
11463be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
11473be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
11483be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
11493be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
11503be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
11513be36e83SMatthew G. Knepley           PetscHashIter          iter;
11523be36e83SMatthew G. Knepley           PetscBool              missing;
11533be36e83SMatthew G. Knepley 
11545f80ce2aSJacob Faibussowitsch           if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Entering face at (%D, %D)\n", rank, r, idx));
11552c71b3e2SJacob Faibussowitsch           PetscCheckFalse(Np > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np);
11563be36e83SMatthew G. Knepley           fcp0.rank  = rank;
11573be36e83SMatthew G. Knepley           fcp0.index = r;
11583be36e83SMatthew G. Knepley           d += Np;
11593be36e83SMatthew G. Knepley           /* Find remote face in hash table */
11603be36e83SMatthew G. Knepley           key.i = fcp0;
11613be36e83SMatthew G. Knepley           key.j = fcone[0];
11623be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
11633be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
11645f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSortSFNode(Np, (PetscSFNode *) &key));
11655f80ce2aSJacob Faibussowitsch           if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]    key (%D, %D) (%D, %D) (%D, %D) (%D, %D)\n", rank, key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index));
11665f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing));
1167*28b400f6SJacob Faibussowitsch           PetscCheck(!missing,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an associated face", r, idx2);
11685f80ce2aSJacob Faibussowitsch           else        CHKERRQ(PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
11697bffde78SMichael Lange         }
11707bffde78SMichael Lange       }
11717bffde78SMichael Lange     }
11725f80ce2aSJacob Faibussowitsch     if (debug) CHKERRQ(PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL));
11735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHashIJKLRemoteDestroy(&faceTable));
11747bffde78SMichael Lange   }
11753be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
11767bffde78SMichael Lange   {
11777bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
11787bffde78SMichael Lange     PetscSFNode *remotePointsNew;
11792e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
11803be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
11812e72742cSMatthew G. Knepley 
11823be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
11835f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetMultiSF(pointSF, &sfMulti));
11845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreate(comm, &claimSection));
11855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
11865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
11875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(claimSection, &claimsSize));
11885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(claimsSize, &claims));
11893be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
11905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE));
11915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE));
11925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfClaims));
11935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(remoteOffsets));
11945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) claimSection, "Claim Section"));
11955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view"));
11965f80ce2aSJacob Faibussowitsch     CHKERRQ(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
11973be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
11983be36e83SMatthew 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 */
11995f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapICreate(&claimshash));
12003be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
12013be36e83SMatthew G. Knepley       PetscInt dof, off, d;
12022e72742cSMatthew G. Knepley 
12035f80ce2aSJacob Faibussowitsch       if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %D\n", rank, r));
12045f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(candidateSection, r, &dof));
12055f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(candidateSection, r, &off));
12062e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
12073be36e83SMatthew G. Knepley         if (claims[off+d].rank >= 0) {
12083be36e83SMatthew G. Knepley           const PetscInt  faceInd = off+d;
12093be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off+d].index;
12102e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
12112e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
12122e72742cSMatthew G. Knepley 
12135f80ce2aSJacob Faibussowitsch           if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%D, %D)\n", rank, claims[faceInd].rank, claims[faceInd].index));
12143be36e83SMatthew G. Knepley           points[0] = r;
12155f80ce2aSJacob Faibussowitsch           if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]      point %D\n", rank, points[0]));
12163be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
12175f80ce2aSJacob Faibussowitsch             CHKERRQ(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1], NULL));
12185f80ce2aSJacob Faibussowitsch             if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]      point %D\n", rank, points[c+1]));
12192e72742cSMatthew G. Knepley           }
12205f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetJoin(dm, Np+1, points, &joinSize, &join));
12212e72742cSMatthew G. Knepley           if (joinSize == 1) {
12223be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
12235f80ce2aSJacob Faibussowitsch               if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %D for non-remote partner\n", rank, join[0]));
12243be36e83SMatthew G. Knepley             } else {
12255f80ce2aSJacob Faibussowitsch               if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    Found local face %D\n", rank, join[0]));
12265f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscHMapISet(claimshash, join[0], faceInd));
12272e72742cSMatthew G. Knepley             }
12283be36e83SMatthew G. Knepley           } else {
12295f80ce2aSJacob Faibussowitsch             if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
12303be36e83SMatthew G. Knepley           }
12315f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join));
12323be36e83SMatthew G. Knepley         } else {
12335f80ce2aSJacob Faibussowitsch           if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %D\n", rank, r));
12343be36e83SMatthew G. Knepley           d += claims[off+d].index+1;
12357bffde78SMichael Lange         }
12367bffde78SMichael Lange       }
12373be36e83SMatthew G. Knepley     }
12385f80ce2aSJacob Faibussowitsch     if (debug) CHKERRQ(PetscSynchronizedFlush(comm, NULL));
12393be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
12405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIGetSize(claimshash, &NlNew));
12415f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
12425f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(Nl + NlNew, &localPointsNew));
12435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(Nl + NlNew, &remotePointsNew));
12443be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12453be36e83SMatthew G. Knepley       localPointsNew[l] = localPoints[l];
12463be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
12473be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
12487bffde78SMichael Lange     }
12493be36e83SMatthew G. Knepley     p = Nl;
12505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
12513be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
12525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortInt(NlNew, &localPointsNew[Nl]));
12533be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
12543be36e83SMatthew G. Knepley       PetscInt off;
12555f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHMapIGet(claimshash, localPointsNew[p], &off));
12562c71b3e2SJacob Faibussowitsch       PetscCheckFalse(claims[off].rank < 0 || claims[off].index < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %D, (%D, %D)", localPointsNew[p], claims[off].rank, claims[off].index);
12573be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
12587bffde78SMichael Lange     }
12595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreate(comm, &sfPointNew));
12605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
12615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetUp(sfPointNew));
12625f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetPointSF(dm, sfPointNew));
12635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view"));
12645f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfPointNew));
12655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIDestroy(&claimshash));
12667bffde78SMichael Lange   }
12675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapIJDestroy(&remoteHash));
12685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&candidateSection));
12695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&candidateRemoteSection));
12705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&claimSection));
12715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(candidates));
12725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(candidatesRemote));
12735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(claims));
12745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0));
12757bffde78SMichael Lange   PetscFunctionReturn(0);
12767bffde78SMichael Lange }
12777bffde78SMichael Lange 
1278248eb259SVaclav Hapla /*@
127980330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
128080330477SMatthew G. Knepley 
1281d083f849SBarry Smith   Collective on dm
128280330477SMatthew G. Knepley 
1283e56d480eSMatthew G. Knepley   Input Parameters:
1284e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices
128510a67516SMatthew G. Knepley - dmInt - The interpolated DM
128680330477SMatthew G. Knepley 
128780330477SMatthew G. Knepley   Output Parameter:
12884e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object
128980330477SMatthew G. Knepley 
129080330477SMatthew G. Knepley   Level: intermediate
129180330477SMatthew G. Knepley 
129295452b02SPatrick Sanan   Notes:
129395452b02SPatrick Sanan     It does not copy over the coordinates.
129443eeeb2dSStefano Zampini 
12959ade3219SVaclav Hapla   Developer Notes:
12969ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL.
12979ade3219SVaclav Hapla 
1298a4a685f2SJacob Faibussowitsch .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates()
129980330477SMatthew G. Knepley @*/
13009f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
13019f074e33SMatthew G Knepley {
1302a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
13039a5b13a2SMatthew G Knepley   DM             idm, odm = dm;
13047bffde78SMichael Lange   PetscSF        sfPoint;
13052e1b13c2SMatthew G. Knepley   PetscInt       depth, dim, d;
130610a67516SMatthew G. Knepley   const char    *name;
1307b325530aSVaclav Hapla   PetscBool      flg=PETSC_TRUE;
13089f074e33SMatthew G Knepley 
13099f074e33SMatthew G Knepley   PetscFunctionBegin;
131010a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
131110a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
13125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0));
13135f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
13145f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
13155f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexIsInterpolated(dm, &interpolated));
13162c71b3e2SJacob Faibussowitsch   PetscCheckFalse(interpolated == DMPLEX_INTERPOLATED_PARTIAL,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1317827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
13185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject) dm));
131976b791aaSMatthew G. Knepley     idm  = dm;
1320b21b8912SMatthew G. Knepley   } else {
13219a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
13229a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
13235f80ce2aSJacob Faibussowitsch       CHKERRQ(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
13245f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetType(idm, DMPLEX));
13255f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(idm, dim));
13267bffde78SMichael Lange       if (depth > 0) {
13275f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexInterpolateFaces_Internal(odm, 1, idm));
13285f80ce2aSJacob Faibussowitsch         CHKERRQ(DMGetPointSF(odm, &sfPoint));
132994488200SVaclav Hapla         {
13303be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
133194488200SVaclav Hapla           PetscInt nroots;
13325f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
13335f80ce2aSJacob Faibussowitsch           if (nroots >= 0) CHKERRQ(DMPlexInterpolatePointSF(idm, sfPoint));
133494488200SVaclav Hapla         }
13357bffde78SMichael Lange       }
13365f80ce2aSJacob Faibussowitsch       if (odm != dm) CHKERRQ(DMDestroy(&odm));
13379a5b13a2SMatthew G Knepley       odm = idm;
13389f074e33SMatthew G Knepley     }
13395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) dm,  &name));
13405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) idm,  name));
13415f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCopyCoordinates(dm, idm));
13425f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
13435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
13445f80ce2aSJacob Faibussowitsch     if (flg) CHKERRQ(DMPlexOrientInterface_Internal(idm));
134584699f70SSatish Balay   }
1346827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1347827c4036SVaclav Hapla   {
1348d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) idm->data;
1349827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1350827c4036SVaclav Hapla   }
13515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, idm));
13529a5b13a2SMatthew G Knepley   *dmInt = idm;
13535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0));
13549f074e33SMatthew G Knepley   PetscFunctionReturn(0);
13559f074e33SMatthew G Knepley }
135607b0a1fcSMatthew G Knepley 
135780330477SMatthew G. Knepley /*@
135880330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
135980330477SMatthew G. Knepley 
1360d083f849SBarry Smith   Collective on dmA
136180330477SMatthew G. Knepley 
136280330477SMatthew G. Knepley   Input Parameter:
136380330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates
136480330477SMatthew G. Knepley 
136580330477SMatthew G. Knepley   Output Parameter:
136680330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates
136780330477SMatthew G. Knepley 
136880330477SMatthew G. Knepley   Level: intermediate
136980330477SMatthew G. Knepley 
137080330477SMatthew G. Knepley   Note: This is typically used when adding pieces other than vertices to a mesh
137180330477SMatthew G. Knepley 
137265f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
137380330477SMatthew G. Knepley @*/
137407b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
137507b0a1fcSMatthew G Knepley {
137607b0a1fcSMatthew G Knepley   Vec            coordinatesA, coordinatesB;
137743eeeb2dSStefano Zampini   VecType        vtype;
137807b0a1fcSMatthew G Knepley   PetscSection   coordSectionA, coordSectionB;
137907b0a1fcSMatthew G Knepley   PetscScalar   *coordsA, *coordsB;
13800bedd6beSMatthew G. Knepley   PetscInt       spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
138190a8aa44SJed Brown   PetscInt       cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
138243eeeb2dSStefano Zampini   PetscBool      lc = PETSC_FALSE;
138307b0a1fcSMatthew G Knepley 
138407b0a1fcSMatthew G Knepley   PetscFunctionBegin;
138543eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
138643eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
138776b791aaSMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
13885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dmA, &cdim));
13895f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dmB, cdim));
13905f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
13915f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
13922c71b3e2SJacob Faibussowitsch   PetscCheckFalse((vEndA-vStartA) != (vEndB-vStartB),PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %d != %d in the second DM", vEndA-vStartA, vEndB-vStartB);
139361a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
139461a622f3SMatthew G. Knepley   {
139561a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
139661a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
139761a622f3SMatthew G. Knepley     PetscObject        objA, objB;
139861a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
139961a622f3SMatthew G. Knepley     const PetscScalar *constants;
140061a622f3SMatthew G. Knepley     PetscInt            cdim, Nc;
140161a622f3SMatthew G. Knepley 
14025f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(dmA, &cdmA));
14035f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(dmB, &cdmB));
14045f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetField(cdmA, 0, NULL, &objA));
14055f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetField(cdmB, 0, NULL, &objB));
14065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetClassId(objA, &idA));
14075f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetClassId(objB, &idB));
140861a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
14095f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetField(cdmB, 0, NULL, objA));
14105f80ce2aSJacob Faibussowitsch       CHKERRQ(DMCreateDS(cdmB));
14115f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetDS(cdmA, &dsA));
14125f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetDS(cdmB, &dsB));
14135f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDSGetCoordinateDimension(dsA, &cdim));
14145f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDSSetCoordinateDimension(dsB, cdim));
14155f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDSGetConstants(dsA, &Nc, &constants));
14165f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDSSetConstants(dsB, Nc, (PetscScalar *) constants));
141761a622f3SMatthew G. Knepley     }
141861a622f3SMatthew G. Knepley   }
14195f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
14205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
14215f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dmA, &coordSectionA));
14225f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dmB, &coordSectionB));
1423972bc18aSToby Isaac   if (coordSectionA == coordSectionB) PetscFunctionReturn(0);
14245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(coordSectionA, &Nf));
14250bedd6beSMatthew G. Knepley   if (!Nf) PetscFunctionReturn(0);
14262c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nf > 1,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf);
1427df26b574SMatthew G. Knepley   if (!coordSectionB) {
1428df26b574SMatthew G. Knepley     PetscInt dim;
1429df26b574SMatthew G. Knepley 
14305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB));
14315f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDim(dmA, &dim));
14325f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetCoordinateSection(dmB, dim, coordSectionB));
14335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectDereference((PetscObject) coordSectionB));
1434df26b574SMatthew G. Knepley   }
14355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSectionB, 1));
14365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
14375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
14385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(coordSectionA, &cS, &cE));
143943eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
14402c71b3e2SJacob Faibussowitsch     PetscCheckFalse((cEndA-cStartA) != (cEndB-cStartB),PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %D != %D in the second DM", cEndA-cStartA, cEndB-cStartB);
144143eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
144243eeeb2dSStefano Zampini     cE = vEndB;
144343eeeb2dSStefano Zampini     lc = PETSC_TRUE;
144443eeeb2dSStefano Zampini   } else {
144543eeeb2dSStefano Zampini     cS = vStartB;
144643eeeb2dSStefano Zampini     cE = vEndB;
144743eeeb2dSStefano Zampini   }
14485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSectionB, cS, cE));
144907b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
14505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSectionB, v, spaceDim));
14515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
145207b0a1fcSMatthew G Knepley   }
145343eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
145443eeeb2dSStefano Zampini     PetscInt c;
145543eeeb2dSStefano Zampini 
145643eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
145743eeeb2dSStefano Zampini       PetscInt dof;
145843eeeb2dSStefano Zampini 
14595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
14605f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetDof(coordSectionB, c + cStartB, dof));
14615f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof));
146243eeeb2dSStefano Zampini     }
146343eeeb2dSStefano Zampini   }
14645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSectionB));
14655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
14665f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dmA, &coordinatesA));
14675f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinatesB));
14685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinatesB, "coordinates"));
14695f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
14705f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetBlockSize(coordinatesA, &d));
14715f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinatesB, d));
14725f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetType(coordinatesA, &vtype));
14735f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinatesB, vtype));
14745f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinatesA, &coordsA));
14755f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinatesB, &coordsB));
147607b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB-vStartB; ++v) {
147743eeeb2dSStefano Zampini     PetscInt offA, offB;
147843eeeb2dSStefano Zampini 
14795f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
14805f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
148107b0a1fcSMatthew G Knepley     for (d = 0; d < spaceDim; ++d) {
148243eeeb2dSStefano Zampini       coordsB[offB+d] = coordsA[offA+d];
148343eeeb2dSStefano Zampini     }
148443eeeb2dSStefano Zampini   }
148543eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
148643eeeb2dSStefano Zampini     PetscInt c;
148743eeeb2dSStefano Zampini 
148843eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
148943eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
149043eeeb2dSStefano Zampini 
14915f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA));
14925f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB));
14935f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
14945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(coordsB + offB,coordsA + offA,dof));
149507b0a1fcSMatthew G Knepley     }
149607b0a1fcSMatthew G Knepley   }
14975f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinatesA, &coordsA));
14985f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinatesB, &coordsB));
14995f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dmB, coordinatesB));
15005f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinatesB));
150107b0a1fcSMatthew G Knepley   PetscFunctionReturn(0);
150207b0a1fcSMatthew G Knepley }
15035c386225SMatthew G. Knepley 
15044e3744c5SMatthew G. Knepley /*@
15054e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
15064e3744c5SMatthew G. Knepley 
1507d083f849SBarry Smith   Collective on dm
15084e3744c5SMatthew G. Knepley 
15094e3744c5SMatthew G. Knepley   Input Parameter:
15104e3744c5SMatthew G. Knepley . dm - The complete DMPlex object
15114e3744c5SMatthew G. Knepley 
15124e3744c5SMatthew G. Knepley   Output Parameter:
15134e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices
15144e3744c5SMatthew G. Knepley 
15154e3744c5SMatthew G. Knepley   Level: intermediate
15164e3744c5SMatthew G. Knepley 
151795452b02SPatrick Sanan   Notes:
151895452b02SPatrick Sanan     It does not copy over the coordinates.
151943eeeb2dSStefano Zampini 
15209ade3219SVaclav Hapla   Developer Notes:
15219ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
15229ade3219SVaclav Hapla 
1523a4a685f2SJacob Faibussowitsch .seealso: DMPlexInterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates()
15244e3744c5SMatthew G. Knepley @*/
15254e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
15264e3744c5SMatthew G. Knepley {
1527827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
15284e3744c5SMatthew G. Knepley   DM             udm;
1529412e9a14SMatthew G. Knepley   PetscInt       dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
15304e3744c5SMatthew G. Knepley 
15314e3744c5SMatthew G. Knepley   PetscFunctionBegin;
153243eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
153343eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
15345f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
15355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexIsInterpolated(dm, &interpolated));
15362c71b3e2SJacob Faibussowitsch   PetscCheckFalse(interpolated == DMPLEX_INTERPOLATED_PARTIAL,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1537827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1538827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
15395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject) dm));
1540595d4abbSMatthew G. Knepley     *dmUnint = dm;
1541595d4abbSMatthew G. Knepley     PetscFunctionReturn(0);
15424e3744c5SMatthew G. Knepley   }
15435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
15445f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
15455f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &udm));
15465f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(udm, DMPLEX));
15475f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(udm, dim));
15485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetChart(udm, cStart, vEnd));
15494e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1550595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
15514e3744c5SMatthew G. Knepley 
15525f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
15534e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
15544e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
15554e3744c5SMatthew G. Knepley 
15564e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
15574e3744c5SMatthew G. Knepley     }
15585f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
15595f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetConeSize(udm, c, coneSize));
1560595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
15614e3744c5SMatthew G. Knepley   }
15625f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(udm));
15635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(maxConeSize, &cone));
15644e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1565595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
15664e3744c5SMatthew G. Knepley 
15675f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
15684e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
15694e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
15704e3744c5SMatthew G. Knepley 
15714e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
15724e3744c5SMatthew G. Knepley     }
15735f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
15745f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetCone(udm, c, cone));
15754e3744c5SMatthew G. Knepley   }
15765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(cone));
15775f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(udm));
15785f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(udm));
15795c7de58aSMatthew G. Knepley   /* Reduce SF */
15805c7de58aSMatthew G. Knepley   {
15815c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
15825c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
15835c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
15845c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
15855c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
15865c7de58aSMatthew G. Knepley     PetscInt           vEnd, numRoots, numLeaves, l;
15875c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
15885c7de58aSMatthew G. Knepley 
15895c7de58aSMatthew G. Knepley     /* Get original SF information */
15905f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetPointSF(dm, &sfPoint));
15915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetPointSF(udm, &sfPointUn));
15925f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, 0, NULL, &vEnd));
15935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
15945c7de58aSMatthew G. Knepley     /* Allocate space for cells and vertices */
15955c7de58aSMatthew G. Knepley     for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++;
15965c7de58aSMatthew G. Knepley     /* Fill in leaves */
15975c7de58aSMatthew G. Knepley     if (vEnd >= 0) {
15985f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(numLeavesUn, &remotePointsUn));
15995f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(numLeavesUn, &localPointsUn));
16005c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
16015c7de58aSMatthew G. Knepley         if (localPoints[l] < vEnd) {
16025c7de58aSMatthew G. Knepley           localPointsUn[n]        = localPoints[l];
16035c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
16045c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
16055c7de58aSMatthew G. Knepley           ++n;
16065c7de58aSMatthew G. Knepley         }
16075c7de58aSMatthew G. Knepley       }
16082c71b3e2SJacob Faibussowitsch       PetscCheckFalse(n != numLeavesUn,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn);
16095f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
16105c7de58aSMatthew G. Knepley     }
16115c7de58aSMatthew G. Knepley   }
1612827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1613827c4036SVaclav Hapla   {
1614d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) udm->data;
1615827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1616827c4036SVaclav Hapla   }
16175f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, udm));
16184e3744c5SMatthew G. Knepley   *dmUnint = udm;
16194e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
16204e3744c5SMatthew G. Knepley }
1621a7748839SVaclav Hapla 
1622a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1623a7748839SVaclav Hapla {
1624a7748839SVaclav Hapla   PetscInt       coneSize, depth, dim, h, p, pStart, pEnd;
1625a7748839SVaclav Hapla   MPI_Comm       comm;
1626a7748839SVaclav Hapla 
1627a7748839SVaclav Hapla   PetscFunctionBegin;
16285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
16295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
16305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
1631a7748839SVaclav Hapla 
1632a7748839SVaclav Hapla   if (depth == dim) {
1633a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1634a7748839SVaclav Hapla     if (!dim) goto finish;
1635a7748839SVaclav Hapla 
1636a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
16375f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1638a7748839SVaclav Hapla     for (p=pStart; p<pEnd; p++) {
16395f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
1640a7748839SVaclav Hapla       if (coneSize) {
1641a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1642a7748839SVaclav Hapla         goto finish;
1643a7748839SVaclav Hapla       }
1644a7748839SVaclav Hapla     }
1645a7748839SVaclav Hapla 
1646a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1647a7748839SVaclav Hapla     for (h=0; h<dim; h++) {
16485f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1649a7748839SVaclav Hapla       for (p=pStart; p<pEnd; p++) {
16505f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
1651a7748839SVaclav Hapla         if (!coneSize) {
1652a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1653a7748839SVaclav Hapla           goto finish;
1654a7748839SVaclav Hapla         }
1655a7748839SVaclav Hapla       }
1656a7748839SVaclav Hapla     }
1657a7748839SVaclav Hapla   } else if (depth == 1) {
1658a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1659a7748839SVaclav Hapla   } else {
1660a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1661a7748839SVaclav Hapla   }
1662a7748839SVaclav Hapla finish:
1663a7748839SVaclav Hapla   PetscFunctionReturn(0);
1664a7748839SVaclav Hapla }
1665a7748839SVaclav Hapla 
1666a7748839SVaclav Hapla /*@
16679ade3219SVaclav Hapla   DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated.
1668a7748839SVaclav Hapla 
1669a7748839SVaclav Hapla   Not Collective
1670a7748839SVaclav Hapla 
1671a7748839SVaclav Hapla   Input Parameter:
1672a7748839SVaclav Hapla . dm      - The DM object
1673a7748839SVaclav Hapla 
1674a7748839SVaclav Hapla   Output Parameter:
1675a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1676a7748839SVaclav Hapla 
1677a7748839SVaclav Hapla   Level: intermediate
1678a7748839SVaclav Hapla 
1679a7748839SVaclav Hapla   Notes:
16809ade3219SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this is NOT collective
16819ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
1682a7748839SVaclav Hapla   However, DMPlexInterpolate() guarantees the result is the same on all.
16839ade3219SVaclav Hapla 
1684a7748839SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED.
1685a7748839SVaclav Hapla 
16869ade3219SVaclav Hapla   Developer Notes:
16879ade3219SVaclav Hapla   Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID.
16889ade3219SVaclav Hapla 
16899ade3219SVaclav Hapla   If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called.
16909ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
16919ade3219SVaclav Hapla   DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL.
16929ade3219SVaclav Hapla 
16939ade3219SVaclav Hapla   If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated.
16949ade3219SVaclav Hapla 
16959ade3219SVaclav Hapla   DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL,
16969ade3219SVaclav Hapla   and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
16979ade3219SVaclav Hapla 
1698a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective()
1699a7748839SVaclav Hapla @*/
1700a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1701a7748839SVaclav Hapla {
1702a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1703a7748839SVaclav Hapla 
1704a7748839SVaclav Hapla   PetscFunctionBegin;
1705a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1706a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
1707a7748839SVaclav Hapla   if (plex->interpolated < 0) {
17085f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
170976bd3646SJed Brown   } else if (PetscDefined (USE_DEBUG)) {
1710a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1711a7748839SVaclav Hapla 
17125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexIsInterpolated_Internal(dm, &flg));
17132c71b3e2SJacob Faibussowitsch     PetscCheckFalse(flg != plex->interpolated,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1714a7748839SVaclav Hapla   }
1715a7748839SVaclav Hapla   *interpolated = plex->interpolated;
1716a7748839SVaclav Hapla   PetscFunctionReturn(0);
1717a7748839SVaclav Hapla }
1718a7748839SVaclav Hapla 
1719a7748839SVaclav Hapla /*@
17209ade3219SVaclav Hapla   DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner).
1721a7748839SVaclav Hapla 
17222666ff3cSVaclav Hapla   Collective
1723a7748839SVaclav Hapla 
1724a7748839SVaclav Hapla   Input Parameter:
1725a7748839SVaclav Hapla . dm      - The DM object
1726a7748839SVaclav Hapla 
1727a7748839SVaclav Hapla   Output Parameter:
1728a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1729a7748839SVaclav Hapla 
1730a7748839SVaclav Hapla   Level: intermediate
1731a7748839SVaclav Hapla 
1732a7748839SVaclav Hapla   Notes:
17339ade3219SVaclav Hapla   Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks.
17349ade3219SVaclav Hapla 
17359ade3219SVaclav Hapla   This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks.
17369ade3219SVaclav Hapla 
17379ade3219SVaclav Hapla   Developer Notes:
17389ade3219SVaclav Hapla   Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID.
17399ade3219SVaclav Hapla 
17409ade3219SVaclav Hapla   If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated.
17419ade3219SVaclav Hapla   MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
17429ade3219SVaclav Hapla   if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED,
17439ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
17449ade3219SVaclav Hapla 
17459ade3219SVaclav Hapla   If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective.
1746a7748839SVaclav Hapla 
1747a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated()
1748a7748839SVaclav Hapla @*/
1749a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1750a7748839SVaclav Hapla {
1751a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1752a7748839SVaclav Hapla   PetscBool       debug=PETSC_FALSE;
1753a7748839SVaclav Hapla 
1754a7748839SVaclav Hapla   PetscFunctionBegin;
1755a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1756a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
17575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
1758a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1759a7748839SVaclav Hapla     DMPlexInterpolatedFlag  min, max;
1760a7748839SVaclav Hapla     MPI_Comm                comm;
1761a7748839SVaclav Hapla 
17625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
17635f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
17645f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
17655f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
1766a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1767a7748839SVaclav Hapla     if (debug) {
1768a7748839SVaclav Hapla       PetscMPIInt rank;
1769a7748839SVaclav Hapla 
17705f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Comm_rank(comm, &rank));
17715f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
17725f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedFlush(comm, PETSC_STDOUT));
1773a7748839SVaclav Hapla     }
1774a7748839SVaclav Hapla   }
1775a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
1776a7748839SVaclav Hapla   PetscFunctionReturn(0);
1777a7748839SVaclav Hapla }
1778