xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
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   PetscErrorCode  ierr;
62439ece16SMatthew G. Knepley 
63439ece16SMatthew G. Knepley   PetscFunctionBegin;
64439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(cone, 3);
66439ece16SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
67412e9a14SMatthew G. Knepley   if (faceTypes) {ierr = DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize),           MPIU_INT, &typesTmp);CHKERRQ(ierr);}
68412e9a14SMatthew G. Knepley   if (faceSizes) {ierr = DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize),           MPIU_INT, &sizesTmp);CHKERRQ(ierr);}
6969291d52SBarry Smith   if (faces)     {ierr = DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp);CHKERRQ(ierr);}
70ba2698f1SMatthew G. Knepley   switch (ct) {
71ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_POINT:
72ba2698f1SMatthew G. Knepley       if (numFaces) *numFaces = 0;
73ba2698f1SMatthew G. Knepley       break;
74ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
75412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 2;
76412e9a14SMatthew G. Knepley       if (faceTypes) {
77412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT;
78412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
79412e9a14SMatthew G. Knepley       }
80412e9a14SMatthew G. Knepley       if (faceSizes) {
81412e9a14SMatthew G. Knepley         sizesTmp[0] = 1; sizesTmp[1] = 1;
82412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
83412e9a14SMatthew G. Knepley       }
84c49d9212SMatthew G. Knepley       if (faces) {
85c49d9212SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
86c49d9212SMatthew G. Knepley         *faces = facesTmp;
87c49d9212SMatthew G. Knepley       }
88412e9a14SMatthew G. Knepley       break;
89412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
90c49d9212SMatthew G. Knepley       if (numFaces) *numFaces = 2;
91412e9a14SMatthew G. Knepley       if (faceTypes) {
92412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT;
93412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
94412e9a14SMatthew G. Knepley       }
95412e9a14SMatthew G. Knepley       if (faceSizes) {
96412e9a14SMatthew G. Knepley         sizesTmp[0] = 1; sizesTmp[1] = 1;
97412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
98412e9a14SMatthew G. Knepley       }
99412e9a14SMatthew G. Knepley       if (faces) {
100412e9a14SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
101412e9a14SMatthew G. Knepley         *faces = facesTmp;
102412e9a14SMatthew G. Knepley       }
103c49d9212SMatthew G. Knepley       break;
104ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
105412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 3;
106412e9a14SMatthew G. Knepley       if (faceTypes) {
107412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT;
108412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
109412e9a14SMatthew G. Knepley       }
110412e9a14SMatthew G. Knepley       if (faceSizes) {
111412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2;
112412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
113412e9a14SMatthew G. Knepley       }
1149a5b13a2SMatthew G Knepley       if (faces) {
1159a5b13a2SMatthew G Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
1169a5b13a2SMatthew G Knepley         facesTmp[2] = cone[1]; facesTmp[3] = cone[2];
1179a5b13a2SMatthew G Knepley         facesTmp[4] = cone[2]; facesTmp[5] = cone[0];
1189a5b13a2SMatthew G Knepley         *faces = facesTmp;
1199a5b13a2SMatthew G Knepley       }
1209f074e33SMatthew G Knepley       break;
121ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1229a5b13a2SMatthew G Knepley       /* Vertices follow right hand rule */
123412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 4;
124412e9a14SMatthew G. Knepley       if (faceTypes) {
125412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT; typesTmp[3] = DM_POLYTOPE_SEGMENT;
126412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
127412e9a14SMatthew G. Knepley       }
128412e9a14SMatthew G. Knepley       if (faceSizes) {
129412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2;
130412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
131412e9a14SMatthew G. Knepley       }
1329a5b13a2SMatthew G Knepley       if (faces) {
1339a5b13a2SMatthew G Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
1349a5b13a2SMatthew G Knepley         facesTmp[2] = cone[1]; facesTmp[3] = cone[2];
1359a5b13a2SMatthew G Knepley         facesTmp[4] = cone[2]; facesTmp[5] = cone[3];
1369a5b13a2SMatthew G Knepley         facesTmp[6] = cone[3]; facesTmp[7] = cone[0];
1379a5b13a2SMatthew G Knepley         *faces = facesTmp;
1389a5b13a2SMatthew G Knepley       }
139412e9a14SMatthew G. Knepley       break;
140412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1419a5b13a2SMatthew G Knepley       if (numFaces) *numFaces = 4;
142412e9a14SMatthew G. Knepley       if (faceTypes) {
143412e9a14SMatthew 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;
144412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
145412e9a14SMatthew G. Knepley       }
146412e9a14SMatthew G. Knepley       if (faceSizes) {
147412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2;
148412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
149412e9a14SMatthew G. Knepley       }
150412e9a14SMatthew G. Knepley       if (faces) {
151412e9a14SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
152412e9a14SMatthew G. Knepley         facesTmp[2] = cone[2]; facesTmp[3] = cone[3];
153412e9a14SMatthew G. Knepley         facesTmp[4] = cone[0]; facesTmp[5] = cone[2];
154412e9a14SMatthew G. Knepley         facesTmp[6] = cone[1]; facesTmp[7] = cone[3];
155412e9a14SMatthew G. Knepley         *faces = facesTmp;
156412e9a14SMatthew G. Knepley       }
1579f074e33SMatthew G Knepley       break;
158ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
1592e1b13c2SMatthew G. Knepley       /* Vertices of first face follow right hand rule and normal points away from last vertex */
160412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 4;
161412e9a14SMatthew G. Knepley       if (faceTypes) {
162412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE;
163412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
164412e9a14SMatthew G. Knepley       }
165412e9a14SMatthew G. Knepley       if (faceSizes) {
166412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3;
167412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
168412e9a14SMatthew G. Knepley       }
1699a5b13a2SMatthew G Knepley       if (faces) {
1702e1b13c2SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];
1712e1b13c2SMatthew G. Knepley         facesTmp[3] = cone[0]; facesTmp[4]  = cone[3]; facesTmp[5]  = cone[1];
1722e1b13c2SMatthew G. Knepley         facesTmp[6] = cone[0]; facesTmp[7]  = cone[2]; facesTmp[8]  = cone[3];
1732e1b13c2SMatthew G. Knepley         facesTmp[9] = cone[2]; facesTmp[10] = cone[1]; facesTmp[11] = cone[3];
1749a5b13a2SMatthew G Knepley         *faces = facesTmp;
1759a5b13a2SMatthew G Knepley       }
1769a5b13a2SMatthew G Knepley       break;
177ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
178e368ef20SMatthew G. Knepley       /*  7--------6
179e368ef20SMatthew G. Knepley          /|       /|
180e368ef20SMatthew G. Knepley         / |      / |
181e368ef20SMatthew G. Knepley        4--------5  |
182e368ef20SMatthew G. Knepley        |  |     |  |
183e368ef20SMatthew G. Knepley        |  |     |  |
184e368ef20SMatthew G. Knepley        |  1--------2
185e368ef20SMatthew G. Knepley        | /      | /
186e368ef20SMatthew G. Knepley        |/       |/
187e368ef20SMatthew G. Knepley        0--------3
188e368ef20SMatthew G. Knepley        */
189412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 6;
190412e9a14SMatthew G. Knepley       if (faceTypes) {
191412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
192412e9a14SMatthew G. Knepley         typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
193412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
194412e9a14SMatthew G. Knepley       }
195412e9a14SMatthew G. Knepley       if (faceSizes) {
196412e9a14SMatthew G. Knepley         sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4;
197412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
198412e9a14SMatthew G. Knepley       }
1999a5b13a2SMatthew G Knepley       if (faces) {
20051cfd6a4SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
20151cfd6a4SMatthew G. Knepley         facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5]; facesTmp[6]  = cone[6]; facesTmp[7]  = cone[7]; /* Top */
20251cfd6a4SMatthew G. Knepley         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[3]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; /* Front */
20351cfd6a4SMatthew G. Knepley         facesTmp[12] = cone[2]; facesTmp[13] = cone[1]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; /* Back */
20451cfd6a4SMatthew G. Knepley         facesTmp[16] = cone[3]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; /* Right */
20551cfd6a4SMatthew G. Knepley         facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[1]; /* Left */
2069a5b13a2SMatthew G Knepley         *faces = facesTmp;
2079a5b13a2SMatthew G Knepley       }
20899836e0eSStefano Zampini       break;
209ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
210412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 5;
211412e9a14SMatthew G. Knepley       if (faceTypes) {
212412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE;
213412e9a14SMatthew G. Knepley         typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
214412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
215412e9a14SMatthew G. Knepley       }
216412e9a14SMatthew G. Knepley       if (faceSizes) {
217412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3;
218412e9a14SMatthew G. Knepley         sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4;
219412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
220412e9a14SMatthew G. Knepley       }
221ba2698f1SMatthew G. Knepley       if (faces) {
222412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];                         /* Bottom */
223412e9a14SMatthew G. Knepley         facesTmp[3]  = cone[3]; facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5];                         /* Top */
224412e9a14SMatthew G. Knepley         facesTmp[6]  = cone[0]; facesTmp[7]  = cone[2]; facesTmp[8]  = cone[4]; facesTmp[9]  = cone[3]; /* Back left */
225412e9a14SMatthew G. Knepley         facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[5]; facesTmp[13] = cone[4]; /* Front */
226412e9a14SMatthew G. Knepley         facesTmp[14] = cone[1]; facesTmp[15] = cone[0]; facesTmp[16] = cone[3]; facesTmp[17] = cone[5]; /* Back right */
227ba2698f1SMatthew G. Knepley         *faces = facesTmp;
22899836e0eSStefano Zampini       }
22999836e0eSStefano Zampini       break;
230ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
231412e9a14SMatthew G. Knepley       if (numFaces)     *numFaces = 5;
232412e9a14SMatthew G. Knepley       if (faceTypes) {
233412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE;
234412e9a14SMatthew G. Knepley         typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
235412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
236412e9a14SMatthew G. Knepley       }
237412e9a14SMatthew G. Knepley       if (faceSizes) {
238412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3;
239412e9a14SMatthew G. Knepley         sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4;
240412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
241412e9a14SMatthew G. Knepley       }
24299836e0eSStefano Zampini       if (faces) {
243412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];                         /* Bottom */
244412e9a14SMatthew G. Knepley         facesTmp[3]  = cone[3]; facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5];                         /* Top */
245412e9a14SMatthew G. Knepley         facesTmp[6]  = cone[0]; facesTmp[7]  = cone[1]; facesTmp[8]  = cone[3]; facesTmp[9]  = cone[4]; /* Back left */
246412e9a14SMatthew G. Knepley         facesTmp[10] = cone[1]; facesTmp[11] = cone[2]; facesTmp[12] = cone[4]; facesTmp[13] = cone[5]; /* Back right */
247412e9a14SMatthew G. Knepley         facesTmp[14] = cone[2]; facesTmp[15] = cone[0]; facesTmp[16] = cone[5]; facesTmp[17] = cone[3]; /* Front */
24899836e0eSStefano Zampini         *faces = facesTmp;
24999836e0eSStefano Zampini       }
250412e9a14SMatthew G. Knepley       break;
251412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
252412e9a14SMatthew G. Knepley       /*  7--------6
253412e9a14SMatthew G. Knepley          /|       /|
254412e9a14SMatthew G. Knepley         / |      / |
255412e9a14SMatthew G. Knepley        4--------5  |
256412e9a14SMatthew G. Knepley        |  |     |  |
257412e9a14SMatthew G. Knepley        |  |     |  |
258412e9a14SMatthew G. Knepley        |  3--------2
259412e9a14SMatthew G. Knepley        | /      | /
260412e9a14SMatthew G. Knepley        |/       |/
261412e9a14SMatthew G. Knepley        0--------1
262412e9a14SMatthew G. Knepley        */
263412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 6;
264412e9a14SMatthew G. Knepley       if (faceTypes) {
265412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;    typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;    typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
266412e9a14SMatthew G. Knepley         typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
267412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
268412e9a14SMatthew G. Knepley       }
269412e9a14SMatthew G. Knepley       if (faceSizes) {
270412e9a14SMatthew G. Knepley         sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4;
271412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
272412e9a14SMatthew G. Knepley       }
273412e9a14SMatthew G. Knepley       if (faces) {
274412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
275412e9a14SMatthew G. Knepley         facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5]; facesTmp[6]  = cone[6]; facesTmp[7]  = cone[7]; /* Top */
276412e9a14SMatthew G. Knepley         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[1]; facesTmp[10] = cone[4]; facesTmp[11] = cone[5]; /* Front */
277412e9a14SMatthew G. Knepley         facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[5]; facesTmp[15] = cone[6]; /* Right */
278412e9a14SMatthew G. Knepley         facesTmp[16] = cone[2]; facesTmp[17] = cone[3]; facesTmp[18] = cone[6]; facesTmp[19] = cone[7]; /* Back */
279412e9a14SMatthew G. Knepley         facesTmp[20] = cone[3]; facesTmp[21] = cone[0]; facesTmp[22] = cone[7]; facesTmp[23] = cone[4]; /* Left */
280412e9a14SMatthew G. Knepley         *faces = facesTmp;
281412e9a14SMatthew G. Knepley       }
28299836e0eSStefano Zampini       break;
283da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
284da9060c4SMatthew G. Knepley       /*
285da9060c4SMatthew G. Knepley        4----
286da9060c4SMatthew G. Knepley        |\-\ \-----
287da9060c4SMatthew G. Knepley        | \ -\     \
288da9060c4SMatthew G. Knepley        |  1--\-----2
289da9060c4SMatthew G. Knepley        | /    \   /
290da9060c4SMatthew G. Knepley        |/      \ /
291da9060c4SMatthew G. Knepley        0--------3
292da9060c4SMatthew G. Knepley        */
293da9060c4SMatthew G. Knepley       if (numFaces) *numFaces = 5;
294da9060c4SMatthew G. Knepley       if (faceTypes) {
295da9060c4SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
296da9060c4SMatthew G. Knepley         typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; typesTmp[4] = DM_POLYTOPE_TRIANGLE;
297da9060c4SMatthew G. Knepley         *faceTypes = typesTmp;
298da9060c4SMatthew G. Knepley       }
299da9060c4SMatthew G. Knepley       if (faceSizes) {
300da9060c4SMatthew G. Knepley         sizesTmp[0] = 4;
301da9060c4SMatthew G. Knepley         sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; sizesTmp[4] = 3;
302da9060c4SMatthew G. Knepley         *faceSizes = sizesTmp;
303da9060c4SMatthew G. Knepley       }
304da9060c4SMatthew G. Knepley       if (faces) {
305da9060c4SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
306da9060c4SMatthew G. Knepley         facesTmp[4]  = cone[0]; facesTmp[5]  = cone[3]; facesTmp[6]  = cone[4];                         /* Front */
307da9060c4SMatthew G. Knepley         facesTmp[7]  = cone[3]; facesTmp[8]  = cone[2]; facesTmp[9]  = cone[4];                         /* Right */
308da9060c4SMatthew G. Knepley         facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[4];                         /* Back */
309da9060c4SMatthew G. Knepley         facesTmp[13] = cone[1]; facesTmp[14] = cone[0]; facesTmp[15] = cone[4];                         /* Left */
310da9060c4SMatthew G. Knepley         *faces = facesTmp;
311da9060c4SMatthew G. Knepley       }
312da9060c4SMatthew G. Knepley       break;
31398921bdaSJacob Faibussowitsch     default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
31499836e0eSStefano Zampini   }
31599836e0eSStefano Zampini   PetscFunctionReturn(0);
31699836e0eSStefano Zampini }
31799836e0eSStefano Zampini 
318412e9a14SMatthew G. Knepley PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
31999836e0eSStefano Zampini {
32099836e0eSStefano Zampini   PetscErrorCode  ierr;
32199836e0eSStefano Zampini 
32299836e0eSStefano Zampini   PetscFunctionBegin;
323412e9a14SMatthew G. Knepley   if (faceTypes) {ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceTypes);CHKERRQ(ierr);}
324412e9a14SMatthew G. Knepley   if (faceSizes) {ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceSizes);CHKERRQ(ierr);}
32599836e0eSStefano Zampini   if (faces)     {ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces);CHKERRQ(ierr);}
32699836e0eSStefano Zampini   PetscFunctionReturn(0);
32799836e0eSStefano Zampini }
32899836e0eSStefano Zampini 
3299a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
3309a5b13a2SMatthew G Knepley static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
3319f074e33SMatthew G Knepley {
332412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
3339a5b13a2SMatthew G Knepley   PetscHashIJKL  faceTable;
334412e9a14SMatthew G. Knepley   PetscInt       faceTypeNum[DM_NUM_POLYTOPES];
3359318fe57SMatthew G. Knepley   PetscInt       depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd;
3369f074e33SMatthew G Knepley   PetscErrorCode ierr;
3379f074e33SMatthew G Knepley 
3389f074e33SMatthew G Knepley   PetscFunctionBegin;
3399a5b13a2SMatthew G Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
34099836e0eSStefano Zampini   ierr = PetscHashIJKLCreate(&faceTable);CHKERRQ(ierr);
341412e9a14SMatthew G. Knepley   ierr = PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES);CHKERRQ(ierr);
342412e9a14SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd);CHKERRQ(ierr);
343412e9a14SMatthew G. Knepley   /* Number new faces and save face vertices in hash table */
344412e9a14SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart);CHKERRQ(ierr);
345412e9a14SMatthew G. Knepley   fEnd = fStart;
346412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
347412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
348412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
349ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
350412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
35199836e0eSStefano Zampini 
352ba2698f1SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
35399836e0eSStefano Zampini     ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
354412e9a14SMatthew G. Knepley     ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
355412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
356412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
357412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
358412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
3599a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
360e8f14785SLisandro Dalcin       PetscHashIter        iter;
361e8f14785SLisandro Dalcin       PetscBool            missing;
3629f074e33SMatthew G Knepley 
363*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(faceSize > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize);
364412e9a14SMatthew G. Knepley       key.i = face[0];
365412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
366412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
367412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
368302440fdSBarry Smith       ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr);
369e8f14785SLisandro Dalcin       ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
370e9fa77a1SMatthew G. Knepley       if (missing) {
371412e9a14SMatthew G. Knepley         ierr = PetscHashIJKLIterSet(faceTable, iter, fEnd++);CHKERRQ(ierr);
372412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
373e9fa77a1SMatthew G. Knepley       }
3749a5b13a2SMatthew G Knepley     }
375412e9a14SMatthew G. Knepley     ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
37699836e0eSStefano Zampini   }
377412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
378412e9a14SMatthew G. Knepley   {
379412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
38099836e0eSStefano Zampini 
381412e9a14SMatthew G. Knepley     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {if (faceTypeNum[ct]) ++numFT; faceTypeStart[ct] = 0;}
382412e9a14SMatthew G. Knepley     if (numFT > 1) {
383412e9a14SMatthew G. Knepley       ierr = PetscHashIJKLClear(faceTable);CHKERRQ(ierr);
384412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
385412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct-1] + faceTypeNum[ct-1];
386412e9a14SMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
387412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
388412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
389ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
390412e9a14SMatthew G. Knepley         PetscInt              numFaces, cf, foff = 0;
39199836e0eSStefano Zampini 
392ba2698f1SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
39399836e0eSStefano Zampini         ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
394412e9a14SMatthew G. Knepley         ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
395412e9a14SMatthew G. Knepley         for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
396412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
397412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
398412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
39999836e0eSStefano Zampini           PetscHashIJKLKey     key;
40099836e0eSStefano Zampini           PetscHashIter        iter;
40199836e0eSStefano Zampini           PetscBool            missing;
40299836e0eSStefano Zampini 
403*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(faceSize > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize);
404412e9a14SMatthew G. Knepley           key.i = face[0];
405412e9a14SMatthew G. Knepley           key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
406412e9a14SMatthew G. Knepley           key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
407412e9a14SMatthew G. Knepley           key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
40899836e0eSStefano Zampini           ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr);
40999836e0eSStefano Zampini           ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
410412e9a14SMatthew G. Knepley           if (missing) {ierr = PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++);CHKERRQ(ierr);}
41199836e0eSStefano Zampini         }
412412e9a14SMatthew G. Knepley         ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
41399836e0eSStefano Zampini       }
414412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
415*2c71b3e2SJacob 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]);
4169a5b13a2SMatthew G Knepley       }
4179a5b13a2SMatthew G Knepley     }
418412e9a14SMatthew G. Knepley   }
419412e9a14SMatthew G. Knepley   /* Add new points, always at the end of the numbering */
4209318fe57SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &Np);CHKERRQ(ierr);
4219318fe57SMatthew G. Knepley   ierr = DMPlexSetChart(idm, pStart, Np + (fEnd - fStart));CHKERRQ(ierr);
4229a5b13a2SMatthew G Knepley   /* Set cone sizes */
423412e9a14SMatthew G. Knepley   /*   Must create the celltype label here so that we do not automatically try to compute the types */
424412e9a14SMatthew G. Knepley   ierr = DMCreateLabel(idm, "celltype");CHKERRQ(ierr);
425412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(idm, &ctLabel);CHKERRQ(ierr);
4269a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
427412e9a14SMatthew G. Knepley     DMPolytopeType ct;
428412e9a14SMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, p;
4299f074e33SMatthew G Knepley 
430412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
431412e9a14SMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
432412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
4339a5b13a2SMatthew G Knepley       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
4349a5b13a2SMatthew G Knepley       ierr = DMPlexSetConeSize(idm, p, coneSize);CHKERRQ(ierr);
435412e9a14SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
436412e9a14SMatthew G. Knepley       ierr = DMPlexSetCellType(idm, p, ct);CHKERRQ(ierr);
4379f074e33SMatthew G Knepley     }
4389f074e33SMatthew G Knepley   }
439412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
440412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
441412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
442412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
443412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
444412e9a14SMatthew G. Knepley 
445412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
446412e9a14SMatthew G. Knepley     ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
447412e9a14SMatthew G. Knepley     ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
448412e9a14SMatthew G. Knepley     ierr = DMPlexSetCellType(idm, c, ct);CHKERRQ(ierr);
449412e9a14SMatthew G. Knepley     ierr = DMPlexSetConeSize(idm, c, numFaces);CHKERRQ(ierr);
450412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
451412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
452412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
453412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
454412e9a14SMatthew G. Knepley       PetscHashIJKLKey     key;
455412e9a14SMatthew G. Knepley       PetscHashIter        iter;
456412e9a14SMatthew G. Knepley       PetscBool            missing;
457412e9a14SMatthew G. Knepley       PetscInt             f;
458412e9a14SMatthew G. Knepley 
459*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(faceSize > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize);
460412e9a14SMatthew G. Knepley       key.i = face[0];
461412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
462412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
463412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
464412e9a14SMatthew G. Knepley       ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr);
465412e9a14SMatthew G. Knepley       ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
466*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(missing,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %D, lf %D)", c, cf);
467412e9a14SMatthew G. Knepley       ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr);
468412e9a14SMatthew G. Knepley       ierr = DMPlexSetConeSize(idm, f, faceSize);CHKERRQ(ierr);
469412e9a14SMatthew G. Knepley       ierr = DMPlexSetCellType(idm, f, faceType);CHKERRQ(ierr);
470412e9a14SMatthew G. Knepley     }
471412e9a14SMatthew G. Knepley     ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
4729f074e33SMatthew G Knepley   }
4739f074e33SMatthew G Knepley   ierr = DMSetUp(idm);CHKERRQ(ierr);
474412e9a14SMatthew G. Knepley   /* Initialize cones so we do not need the bash table to tell us that a cone has been set */
475412e9a14SMatthew G. Knepley   {
476412e9a14SMatthew G. Knepley     PetscSection cs;
477412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
4789a5b13a2SMatthew G Knepley 
479412e9a14SMatthew G. Knepley     ierr = DMPlexGetConeSection(idm, &cs);CHKERRQ(ierr);
480412e9a14SMatthew G. Knepley     ierr = DMPlexGetCones(idm, &cones);CHKERRQ(ierr);
481412e9a14SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(cs, &csize);CHKERRQ(ierr);
482412e9a14SMatthew G. Knepley     for (c = 0; c < csize; ++c) cones[c] = -1;
483412e9a14SMatthew G. Knepley   }
484412e9a14SMatthew G. Knepley   /* Set cones */
485412e9a14SMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
486412e9a14SMatthew G. Knepley     const PetscInt *cone;
487412e9a14SMatthew G. Knepley     PetscInt        pStart, pEnd, p;
488412e9a14SMatthew G. Knepley 
489412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
490412e9a14SMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
491412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
4929a5b13a2SMatthew G Knepley       ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
4939a5b13a2SMatthew G Knepley       ierr = DMPlexSetCone(idm, p, cone);CHKERRQ(ierr);
4949a5b13a2SMatthew G Knepley       ierr = DMPlexGetConeOrientation(dm, p, &cone);CHKERRQ(ierr);
4959a5b13a2SMatthew G Knepley       ierr = DMPlexSetConeOrientation(idm, p, cone);CHKERRQ(ierr);
4969f074e33SMatthew G Knepley     }
4979a5b13a2SMatthew G Knepley   }
498412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
499412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
500412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
501ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
502412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
50399836e0eSStefano Zampini 
504ba2698f1SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
50599836e0eSStefano Zampini     ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
506412e9a14SMatthew G. Knepley     ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
507412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
508412e9a14SMatthew G. Knepley       DMPolytopeType   faceType = faceTypes[cf];
509412e9a14SMatthew G. Knepley       const PetscInt   faceSize = faceSizes[cf];
510412e9a14SMatthew G. Knepley       const PetscInt  *face     = &faces[foff];
511412e9a14SMatthew G. Knepley       const PetscInt  *fcone;
5129a5b13a2SMatthew G Knepley       PetscHashIJKLKey key;
513e8f14785SLisandro Dalcin       PetscHashIter    iter;
514e8f14785SLisandro Dalcin       PetscBool        missing;
515412e9a14SMatthew G. Knepley       PetscInt         f;
5169f074e33SMatthew G Knepley 
517*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(faceSize > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize);
518412e9a14SMatthew G. Knepley       key.i = face[0];
519412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
520412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
521412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
52299836e0eSStefano Zampini       ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr);
52399836e0eSStefano Zampini       ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
52499836e0eSStefano Zampini       ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr);
52599836e0eSStefano Zampini       ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr);
526412e9a14SMatthew G. Knepley       ierr = DMPlexGetCone(idm, f, &fcone);CHKERRQ(ierr);
527412e9a14SMatthew G. Knepley       if (fcone[0] < 0) {ierr = DMPlexSetCone(idm, f, face);CHKERRQ(ierr);}
528412e9a14SMatthew G. Knepley       {
529412e9a14SMatthew G. Knepley         const PetscInt *cone;
530412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
531a74221b0SStefano Zampini 
532412e9a14SMatthew G. Knepley         ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr);
533412e9a14SMatthew G. Knepley         ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr);
534*2c71b3e2SJacob 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);
535d89e6e46SMatthew G. Knepley         /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
536d89e6e46SMatthew G. Knepley         ierr = DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt);CHKERRQ(ierr);
53799836e0eSStefano Zampini         ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr);
53899836e0eSStefano Zampini       }
53999836e0eSStefano Zampini     }
540412e9a14SMatthew G. Knepley     ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
54199836e0eSStefano Zampini   }
5429a5b13a2SMatthew G Knepley   ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr);
5439a5b13a2SMatthew G Knepley   ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr);
5449a5b13a2SMatthew G Knepley   ierr = DMPlexStratify(idm);CHKERRQ(ierr);
5459f074e33SMatthew G Knepley   PetscFunctionReturn(0);
5469f074e33SMatthew G Knepley }
5479f074e33SMatthew G Knepley 
548f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
549f80536cbSVaclav Hapla {
550f80536cbSVaclav Hapla   PetscInt            nleaves;
551f80536cbSVaclav Hapla   PetscInt            nranks;
552a0d42dbcSVaclav Hapla   const PetscMPIInt  *ranks=NULL;
553a0d42dbcSVaclav Hapla   const PetscInt     *roffset=NULL, *rmine=NULL, *rremote=NULL;
554f80536cbSVaclav Hapla   PetscInt            n, o, r;
555f80536cbSVaclav Hapla   PetscErrorCode      ierr;
556f80536cbSVaclav Hapla 
557f80536cbSVaclav Hapla   PetscFunctionBegin;
558dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote);CHKERRQ(ierr);
559f80536cbSVaclav Hapla   nleaves = roffset[nranks];
560f80536cbSVaclav Hapla   ierr = PetscMalloc2(nleaves, rmine1, nleaves, rremote1);CHKERRQ(ierr);
561f80536cbSVaclav Hapla   for (r=0; r<nranks; r++) {
562f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
563f80536cbSVaclav Hapla        - to unify order with the other side */
564f80536cbSVaclav Hapla     o = roffset[r];
565f80536cbSVaclav Hapla     n = roffset[r+1] - o;
566580bdb30SBarry Smith     ierr = PetscArraycpy(&(*rmine1)[o], &rmine[o], n);CHKERRQ(ierr);
567580bdb30SBarry Smith     ierr = PetscArraycpy(&(*rremote1)[o], &rremote[o], n);CHKERRQ(ierr);
568f80536cbSVaclav Hapla     ierr = PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]);CHKERRQ(ierr);
569f80536cbSVaclav Hapla   }
570f80536cbSVaclav Hapla   PetscFunctionReturn(0);
571f80536cbSVaclav Hapla }
572f80536cbSVaclav Hapla 
57327d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
5742e745bdaSMatthew G. Knepley {
575d89e6e46SMatthew G. Knepley   PetscSF            sf;
576d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
577d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
578d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
579d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
580d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
581d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
582d89e6e46SMatthew G. Knepley   PetscInt         (*roots)[4],      (*leaves)[4], mainCone[4];
583d89e6e46SMatthew G. Knepley   PetscMPIInt      (*rootsRanks)[4], (*leavesRanks)[4];
5842e745bdaSMatthew G. Knepley   MPI_Comm           comm;
58527d0e99aSVaclav Hapla   PetscMPIInt        rank, size;
5862e745bdaSMatthew G. Knepley   PetscInt           debug = 0;
5872e745bdaSMatthew G. Knepley   PetscErrorCode     ierr;
5882e745bdaSMatthew G. Knepley 
5892e745bdaSMatthew G. Knepley   PetscFunctionBegin;
5902e745bdaSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
591ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
592ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
593d89e6e46SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
594d89e6e46SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view");CHKERRQ(ierr);
595d89e6e46SMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) {ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr);}
596d89e6e46SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes);CHKERRQ(ierr);
597d89e6e46SMatthew G. Knepley   if (nroots < 0) PetscFunctionReturn(0);
598d89e6e46SMatthew G. Knepley   ierr = PetscSFSetUp(sf);CHKERRQ(ierr);
599d89e6e46SMatthew G. Knepley   ierr = SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1);CHKERRQ(ierr);
600d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
601d89e6e46SMatthew G. Knepley     PetscInt coneSize;
602d89e6e46SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, locals[p], &coneSize);CHKERRQ(ierr);
603d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
604d89e6e46SMatthew G. Knepley   }
605*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(maxConeSize > 4,comm, PETSC_ERR_SUP, "This method does not support cones of size %D", maxConeSize);
606d89e6e46SMatthew G. Knepley   ierr = PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks);CHKERRQ(ierr);
6079e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
608d89e6e46SMatthew G. Knepley     const PetscInt *cone;
609d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
610d89e6e46SMatthew G. Knepley 
6119e24d8a0SVaclav Hapla     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
6129e24d8a0SVaclav Hapla     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
613d89e6e46SMatthew G. Knepley     /* Ignore vertices */
61427d0e99aSVaclav Hapla     if (coneSize < 2) {
615d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
61627d0e99aSVaclav Hapla         roots[p][c]      = -1;
61727d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
61827d0e99aSVaclav Hapla       }
61927d0e99aSVaclav Hapla       continue;
62027d0e99aSVaclav Hapla     }
6212e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
622d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
6238a650c75SVaclav Hapla       ierr = PetscFindInt(cone[c], nleaves, locals, &ind0);CHKERRQ(ierr);
6248a650c75SVaclav Hapla       if (ind0 < 0) {
6258a650c75SVaclav Hapla         roots[p][c]      = cone[c];
6268a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
627c8148b97SVaclav Hapla       } else {
6288a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
6298a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
6308a650c75SVaclav Hapla       }
6312e745bdaSMatthew G. Knepley     }
632d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
633d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
634d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
635d89e6e46SMatthew G. Knepley     }
6362e745bdaSMatthew G. Knepley   }
6379e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
638d89e6e46SMatthew G. Knepley     PetscInt c;
639d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
6408ccb905dSVaclav Hapla       leaves[p][c]      = -2;
6418ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
6428ccb905dSVaclav Hapla     }
643c8148b97SVaclav Hapla   }
644d89e6e46SMatthew G. Knepley   ierr = PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE);CHKERRQ(ierr);
645d89e6e46SMatthew G. Knepley   ierr = PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE);CHKERRQ(ierr);
646d89e6e46SMatthew G. Knepley   ierr = PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE);CHKERRQ(ierr);
647d89e6e46SMatthew G. Knepley   ierr = PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE);CHKERRQ(ierr);
648d89e6e46SMatthew G. Knepley   if (debug) {
649d89e6e46SMatthew G. Knepley     ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
650d89e6e46SMatthew G. Knepley     if (!rank) {ierr = PetscSynchronizedPrintf(comm, "Referenced roots\n");CHKERRQ(ierr);}
651d89e6e46SMatthew G. Knepley   }
652d89e6e46SMatthew G. Knepley   ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL);CHKERRQ(ierr);
6539e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
654d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
655d89e6e46SMatthew G. Knepley     const PetscInt *cone;
656d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
657d89e6e46SMatthew G. Knepley 
658d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
659d89e6e46SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
6609e24d8a0SVaclav Hapla     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
6619e24d8a0SVaclav Hapla     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
662d89e6e46SMatthew G. Knepley     if (debug) {
663d89e6e46SMatthew G. Knepley       ierr = 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)]",
664d89e6e46SMatthew G. Knepley        rank, p, cone[0], cone[1], cone[2], cone[3],
665d89e6e46SMatthew 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],
666d89e6e46SMatthew G. Knepley        leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1], leavesRanks[p][2], leaves[p][2], leavesRanks[p][3], leaves[p][3]);CHKERRQ(ierr);
667d89e6e46SMatthew G. Knepley     }
668d89e6e46SMatthew G. Knepley     if (leavesRanks[p][0] != rootsRanks[p][0] || leaves[p][0] != roots[p][0] ||
669d89e6e46SMatthew G. Knepley         leavesRanks[p][1] != rootsRanks[p][1] || leaves[p][1] != roots[p][1] ||
670d89e6e46SMatthew G. Knepley         leavesRanks[p][2] != rootsRanks[p][2] || leaves[p][2] != roots[p][2] ||
671d89e6e46SMatthew G. Knepley         leavesRanks[p][3] != rootsRanks[p][3] || leaves[p][3] != roots[p][3]) {
672d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
673d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
674d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
675d89e6e46SMatthew G. Knepley 
67627d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
677d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
6789dddd249SSatish Balay           mainCone[c] = leaves[p][c];
67927d0e99aSVaclav Hapla           continue;
68027d0e99aSVaclav Hapla         }
681f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
682f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
683f80536cbSVaclav Hapla         ierr = PetscFindMPIInt((PetscMPIInt) leavesRanks[p][c], nranks, ranks, &r);CHKERRQ(ierr);
684*2c71b3e2SJacob 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]);
685*2c71b3e2SJacob 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]);
686f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
687d89e6e46SMatthew G. Knepley         rS = roffset[r];
688d89e6e46SMatthew G. Knepley         rN = roffset[r+1] - rS;
689d89e6e46SMatthew G. Knepley         ierr = PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0);CHKERRQ(ierr);
690*2c71b3e2SJacob 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]);
691f80536cbSVaclav Hapla         /* Get the corresponding local point */
692d89e6e46SMatthew G. Knepley         mainCone[c] = rmine1[rS + ind0];CHKERRQ(ierr);
693f80536cbSVaclav Hapla       }
694d89e6e46SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, " mainCone=[%4D %4D %4D %4D]\n", mainCone[0], mainCone[1], mainCone[2], mainCone[3]);CHKERRQ(ierr);}
69527d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
696d89e6e46SMatthew G. Knepley       ierr = DMPolytopeGetOrientation(ct, cone, mainCone, &o);CHKERRQ(ierr);
697d89e6e46SMatthew G. Knepley       ierr = DMPlexOrientPoint(dm, p, o);CHKERRQ(ierr);
69827d0e99aSVaclav Hapla     } else if (debug) {ierr = PetscSynchronizedPrintf(comm, " ==\n");CHKERRQ(ierr);}
69923aaf07bSVaclav Hapla   }
70027d0e99aSVaclav Hapla   if (debug) {
70127d0e99aSVaclav Hapla     ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
702ffc4695bSBarry Smith     ierr = MPI_Barrier(comm);CHKERRMPI(ierr);
7032e745bdaSMatthew G. Knepley   }
704d89e6e46SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view");CHKERRQ(ierr);
7058a650c75SVaclav Hapla   ierr = PetscFree4(roots, leaves, rootsRanks, leavesRanks);CHKERRQ(ierr);
7067c7bb832SVaclav Hapla   ierr = PetscFree2(rmine1, rremote1);CHKERRQ(ierr);
7072e745bdaSMatthew G. Knepley   PetscFunctionReturn(0);
7082e745bdaSMatthew G. Knepley }
7092e745bdaSMatthew G. Knepley 
7102e72742cSMatthew 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[])
7117bffde78SMichael Lange {
7122e72742cSMatthew G. Knepley   PetscInt       idx;
7132e72742cSMatthew G. Knepley   PetscMPIInt    rank;
7142e72742cSMatthew G. Knepley   PetscBool      flg;
7157bffde78SMichael Lange   PetscErrorCode ierr;
7167bffde78SMichael Lange 
7177bffde78SMichael Lange   PetscFunctionBegin;
7182e72742cSMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr);
7192e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
720ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
7212e72742cSMatthew G. Knepley   ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr);
7222e72742cSMatthew G. Knepley   for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]%s %D %s %D\n", rank, idxname, idx, valname, a[idx]);CHKERRQ(ierr);}
7232e72742cSMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
7242e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7252e72742cSMatthew G. Knepley }
7262e72742cSMatthew G. Knepley 
7272e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
7282e72742cSMatthew G. Knepley {
7292e72742cSMatthew G. Knepley   PetscInt       idx;
7302e72742cSMatthew G. Knepley   PetscMPIInt    rank;
7312e72742cSMatthew G. Knepley   PetscBool      flg;
7322e72742cSMatthew G. Knepley   PetscErrorCode ierr;
7332e72742cSMatthew G. Knepley 
7342e72742cSMatthew G. Knepley   PetscFunctionBegin;
7352e72742cSMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr);
7362e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
737ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
7382e72742cSMatthew G. Knepley   ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr);
7392e72742cSMatthew G. Knepley   if (idxname) {
7402e72742cSMatthew G. Knepley     for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]%s %D rank %D index %D\n", rank, idxname, idx, a[idx].rank, a[idx].index);CHKERRQ(ierr);}
7412e72742cSMatthew G. Knepley   } else {
7422e72742cSMatthew G. Knepley     for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]rank %D index %D\n", rank, a[idx].rank, a[idx].index);CHKERRQ(ierr);}
7432e72742cSMatthew G. Knepley   }
7442e72742cSMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
7452e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7462e72742cSMatthew G. Knepley }
7472e72742cSMatthew G. Knepley 
7483be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint)
7492e72742cSMatthew G. Knepley {
7503be36e83SMatthew G. Knepley   PetscSF         sf;
7513be36e83SMatthew G. Knepley   const PetscInt *locals;
7523be36e83SMatthew G. Knepley   PetscMPIInt     rank;
7532e72742cSMatthew G. Knepley   PetscErrorCode  ierr;
7542e72742cSMatthew G. Knepley 
7552e72742cSMatthew G. Knepley   PetscFunctionBegin;
756ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
7573be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
7583be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, NULL, &locals, NULL);CHKERRQ(ierr);
7592e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
7602e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
7612e72742cSMatthew G. Knepley   } else {
7622e72742cSMatthew G. Knepley     PetscHashIJKey key;
7633be36e83SMatthew G. Knepley     PetscInt       l;
7642e72742cSMatthew G. Knepley 
7652e72742cSMatthew G. Knepley     key.i = remotePoint.index;
7662e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
7673be36e83SMatthew G. Knepley     ierr = PetscHMapIJGet(remotehash, key, &l);CHKERRQ(ierr);
7683be36e83SMatthew G. Knepley     if (l >= 0) {
7693be36e83SMatthew G. Knepley       *localPoint = locals[l];
7702e72742cSMatthew G. Knepley     } else PetscFunctionReturn(1);
7712e72742cSMatthew G. Knepley   }
7722e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7732e72742cSMatthew G. Knepley }
7742e72742cSMatthew G. Knepley 
7753be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint)
7763be36e83SMatthew G. Knepley {
7773be36e83SMatthew G. Knepley   PetscSF            sf;
7783be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
7793be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
7803be36e83SMatthew G. Knepley   PetscInt           Nl, l;
7813be36e83SMatthew G. Knepley   PetscMPIInt        rank;
7823be36e83SMatthew G. Knepley   PetscErrorCode     ierr;
7833be36e83SMatthew G. Knepley 
7843be36e83SMatthew G. Knepley   PetscFunctionBegin;
785ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
7863be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
7873be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes);CHKERRQ(ierr);
7883be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
7893be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr);
7903be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr);
7913be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
7923be36e83SMatthew G. Knepley   ierr = PetscFindInt(localPoint, Nl, locals, &l);CHKERRQ(ierr);
7933be36e83SMatthew G. Knepley   if (l < 0) PetscFunctionReturn(1);
7943be36e83SMatthew G. Knepley   *remotePoint = remotes[l];
7953be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
7963be36e83SMatthew G. Knepley   owned:
7973be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
7983be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
7993be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8003be36e83SMatthew G. Knepley }
8013be36e83SMatthew G. Knepley 
8023be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
8033be36e83SMatthew G. Knepley {
8043be36e83SMatthew G. Knepley   PetscSF         sf;
8053be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
8063be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
8073be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
8083be36e83SMatthew G. Knepley 
8093be36e83SMatthew G. Knepley   PetscFunctionBegin;
8103be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
8113be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
8123be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL);CHKERRQ(ierr);
8133be36e83SMatthew G. Knepley   if (Nl < 0) PetscFunctionReturn(0);
8143be36e83SMatthew G. Knepley   ierr = PetscFindInt(p, Nl, locals, &idx);CHKERRQ(ierr);
8153be36e83SMatthew G. Knepley   if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);}
8163be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr);
8173be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr);
8183be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
8193be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8203be36e83SMatthew G. Knepley }
8213be36e83SMatthew G. Knepley 
8223be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
8233be36e83SMatthew G. Knepley {
8243be36e83SMatthew G. Knepley   const PetscInt *cone;
8253be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
8263be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
8273be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
8283be36e83SMatthew G. Knepley 
8293be36e83SMatthew G. Knepley   PetscFunctionBegin;
8303be36e83SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
8313be36e83SMatthew G. Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
8323be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
8333be36e83SMatthew G. Knepley     PetscBool pointShared;
8343be36e83SMatthew G. Knepley 
8353be36e83SMatthew G. Knepley     ierr = DMPlexPointIsShared(dm, cone[c], &pointShared);CHKERRQ(ierr);
8363be36e83SMatthew G. Knepley     cShared = (PetscBool) (cShared && pointShared);
8373be36e83SMatthew G. Knepley   }
8383be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
8393be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8403be36e83SMatthew G. Knepley }
8413be36e83SMatthew G. Knepley 
8423be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
8433be36e83SMatthew G. Knepley {
8443be36e83SMatthew G. Knepley   const PetscInt *cone;
8453be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
8463be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
8473be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
8483be36e83SMatthew G. Knepley 
8493be36e83SMatthew G. Knepley   PetscFunctionBegin;
8503be36e83SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
8513be36e83SMatthew G. Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
8523be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
8533be36e83SMatthew G. Knepley     PetscSFNode rcp;
8543be36e83SMatthew G. Knepley 
8553be36e83SMatthew G. Knepley     ierr = DMPlexMapToGlobalPoint(dm, cone[c], &rcp);
8563be36e83SMatthew G. Knepley     if (ierr) {
8573be36e83SMatthew G. Knepley       cmin = missing;
8583be36e83SMatthew G. Knepley     } else {
8593be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
8603be36e83SMatthew G. Knepley     }
8613be36e83SMatthew G. Knepley   }
8623be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
8633be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8643be36e83SMatthew G. Knepley }
8653be36e83SMatthew G. Knepley 
8663be36e83SMatthew G. Knepley /*
8673be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
8683be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
8693be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
8703be36e83SMatthew G. Knepley */
8713be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
8723be36e83SMatthew G. Knepley {
8733be36e83SMatthew G. Knepley   MPI_Comm        comm;
8743be36e83SMatthew G. Knepley   const PetscInt *support;
875cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
8763be36e83SMatthew G. Knepley   PetscMPIInt     rank;
8773be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
8783be36e83SMatthew G. Knepley 
8793be36e83SMatthew G. Knepley   PetscFunctionBegin;
8803be36e83SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
881ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
882cf4dc471SVaclav Hapla   ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr);
883cf4dc471SVaclav Hapla   ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
884cf4dc471SVaclav Hapla   ierr = DMPlexGetPointHeight(dm, p, &height);CHKERRQ(ierr);
885cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight+1) {
886cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
887cf4dc471SVaclav Hapla     if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Skipping face %D to avoid adding cell to hashmap since this is nonoverlapping mesh\n", rank, p);CHKERRQ(ierr);}
888cf4dc471SVaclav Hapla     PetscFunctionReturn(0);
889cf4dc471SVaclav Hapla   }
8903be36e83SMatthew G. Knepley   ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
8913be36e83SMatthew G. Knepley   ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
8923be36e83SMatthew G. Knepley   if (candidates) {ierr = PetscSectionGetOffset(candidateSection, p, &off);CHKERRQ(ierr);}
8933be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
8943be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
8953be36e83SMatthew G. Knepley     const PetscInt *cone;
8963be36e83SMatthew G. Knepley     PetscSFNode     cpmin={-1,-1}, rp={-1,-1};
8973be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
8983be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
8993be36e83SMatthew G. Knepley     PetscHashIJKey  key;
9003be36e83SMatthew G. Knepley 
9013be36e83SMatthew G. Knepley     /* Only add point once */
9023be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Support face %D\n", rank, face);CHKERRQ(ierr);}
9033be36e83SMatthew G. Knepley     key.i = p;
9043be36e83SMatthew G. Knepley     key.j = face;
9053be36e83SMatthew G. Knepley     ierr = PetscHMapIJGet(faceHash, key, &f);CHKERRQ(ierr);
9063be36e83SMatthew G. Knepley     if (f >= 0) continue;
9073be36e83SMatthew G. Knepley     ierr = DMPlexConeIsShared(dm, face, &isShared);CHKERRQ(ierr);
9083be36e83SMatthew G. Knepley     ierr = DMPlexGetConeMinimum(dm, face, &cpmin);CHKERRQ(ierr);
9093be36e83SMatthew G. Knepley     ierr = DMPlexMapToGlobalPoint(dm, p, &rp);CHKERRQ(ierr);
9103be36e83SMatthew G. Knepley     if (debug) {
9113be36e83SMatthew G. Knepley       ierr = PetscSynchronizedPrintf(comm, "[%d]      Face point %D is shared: %d\n", rank, face, (int) isShared);CHKERRQ(ierr);
9123be36e83SMatthew G. Knepley       ierr = PetscSynchronizedPrintf(comm, "[%d]      Global point (%D, %D) Min Cone Point (%D, %D)\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index);CHKERRQ(ierr);
9133be36e83SMatthew G. Knepley     }
9143be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
9153be36e83SMatthew G. Knepley       ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr);
9163be36e83SMatthew G. Knepley       if (candidates) {
9173be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %D at idx %D\n[%d]     ", rank, face, idx, rank);CHKERRQ(ierr);}
9183be36e83SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr);
9193be36e83SMatthew G. Knepley         ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr);
9203be36e83SMatthew G. Knepley         candidates[off+idx].rank    = -1;
9213be36e83SMatthew G. Knepley         candidates[off+idx++].index = coneSize-1;
9223be36e83SMatthew G. Knepley         candidates[off+idx].rank    = rank;
9233be36e83SMatthew G. Knepley         candidates[off+idx++].index = face;
9243be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
9253be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
9263be36e83SMatthew G. Knepley 
9273be36e83SMatthew G. Knepley           if (cp == p) continue;
9283be36e83SMatthew G. Knepley           ierr = DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx]);CHKERRQ(ierr);
9293be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index);CHKERRQ(ierr);}
9303be36e83SMatthew G. Knepley           ++idx;
9313be36e83SMatthew G. Knepley         }
9323be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "\n");CHKERRQ(ierr);}
9333be36e83SMatthew G. Knepley       } else {
9343be36e83SMatthew G. Knepley         /* Add cone size to section */
9353be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %D\n", rank, face);CHKERRQ(ierr);}
9363be36e83SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr);
9373be36e83SMatthew G. Knepley         ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr);
9383be36e83SMatthew G. Knepley         ierr = PetscSectionAddDof(candidateSection, p, coneSize+1);CHKERRQ(ierr);
9393be36e83SMatthew G. Knepley       }
9403be36e83SMatthew G. Knepley     }
9413be36e83SMatthew G. Knepley   }
9423be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9433be36e83SMatthew G. Knepley }
9443be36e83SMatthew G. Knepley 
9452e72742cSMatthew G. Knepley /*@
9462e72742cSMatthew G. Knepley   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation
9472e72742cSMatthew G. Knepley 
948d083f849SBarry Smith   Collective on dm
9492e72742cSMatthew G. Knepley 
9502e72742cSMatthew G. Knepley   Input Parameters:
9512e72742cSMatthew G. Knepley + dm      - The interpolated DM
9522e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points
9532e72742cSMatthew G. Knepley 
9542e72742cSMatthew G. Knepley   Output Parameter:
9552e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points
9562e72742cSMatthew G. Knepley 
957f0cfc026SVaclav Hapla   Level: developer
9582e72742cSMatthew G. Knepley 
9592e72742cSMatthew 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
9602e72742cSMatthew G. Knepley 
9612e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate()
9622e72742cSMatthew G. Knepley @*/
963e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
9642e72742cSMatthew G. Knepley {
9653be36e83SMatthew G. Knepley   MPI_Comm           comm;
9663be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
9673be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
9683be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
9693be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
9702e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
9712e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
9723be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
9733be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
9743be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
975f0cfc026SVaclav Hapla   PetscMPIInt        rank;
9762e72742cSMatthew G. Knepley   PetscErrorCode     ierr;
9772e72742cSMatthew G. Knepley 
9782e72742cSMatthew G. Knepley   PetscFunctionBegin;
979f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
980064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
981f0cfc026SVaclav Hapla   ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr);
982f0cfc026SVaclav Hapla   if (!flg) PetscFunctionReturn(0);
9833be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
9843be36e83SMatthew G. Knepley   ierr = DMSetPointSF(dm, pointSF);CHKERRQ(ierr);
9853be36e83SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
986ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
9873be36e83SMatthew G. Knepley   ierr = DMPlexGetOverlap(dm, &ov);CHKERRQ(ierr);
988*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ov,comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
9893be36e83SMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug);CHKERRQ(ierr);
9902e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view");CHKERRQ(ierr);
9912e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view");CHKERRQ(ierr);
99225afeb17SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr);
9933be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
9943be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints);CHKERRQ(ierr);
995*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nr < 0,comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
9963be36e83SMatthew G. Knepley   ierr = PetscHMapIJCreate(&remoteHash);CHKERRQ(ierr);
9973be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
9983be36e83SMatthew G. Knepley     PetscHashIJKey key;
9992e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
10002e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
10013be36e83SMatthew G. Knepley     ierr = PetscHMapIJSet(remoteHash, key, l);CHKERRQ(ierr);
10027bffde78SMichael Lange   }
100366aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
10042e72742cSMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr);
10052e72742cSMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr);
10063be36e83SMatthew G. Knepley   ierr = IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree);CHKERRQ(ierr);
10073be36e83SMatthew G. Knepley   /*
10083be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
10093be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
10103be36e83SMatthew G. Knepley   \begin{itemize}
10113be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
10123be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
10133be36e83SMatthew G. Knepley   \end{itemize}
10143be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
10153be36e83SMatthew 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
10163be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
10173be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
10183be36e83SMatthew G. Knepley   */
10193be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
10203be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
10213be36e83SMatthew G. Knepley        The array holds candidate shared faces, each face is refered to by the leaf point */
10223be36e83SMatthew G. Knepley   ierr = PetscSectionCreate(comm, &candidateSection);CHKERRQ(ierr);
10233be36e83SMatthew G. Knepley   ierr = PetscSectionSetChart(candidateSection, 0, Nr);CHKERRQ(ierr);
10247bffde78SMichael Lange   {
10253be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
10262e72742cSMatthew G. Knepley 
10273be36e83SMatthew G. Knepley     ierr = PetscHMapIJCreate(&faceHash);CHKERRQ(ierr);
10283be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
10293be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
10302e72742cSMatthew G. Knepley 
10313be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %D\n", rank, p);CHKERRQ(ierr);}
10323be36e83SMatthew G. Knepley       ierr = DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug);CHKERRQ(ierr);
10332e72742cSMatthew G. Knepley     }
10343be36e83SMatthew G. Knepley     ierr = PetscHMapIJClear(faceHash);CHKERRQ(ierr);
10357bffde78SMichael Lange     ierr = PetscSectionSetUp(candidateSection);CHKERRQ(ierr);
10367bffde78SMichael Lange     ierr = PetscSectionGetStorageSize(candidateSection, &candidatesSize);CHKERRQ(ierr);
10377bffde78SMichael Lange     ierr = PetscMalloc1(candidatesSize, &candidates);CHKERRQ(ierr);
10383be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
10393be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
10402e72742cSMatthew G. Knepley 
10413be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %D\n", rank, p);CHKERRQ(ierr);}
10423be36e83SMatthew G. Knepley       ierr = DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug);CHKERRQ(ierr);
10432e72742cSMatthew G. Knepley     }
10443be36e83SMatthew G. Knepley     ierr = PetscHMapIJDestroy(&faceHash);CHKERRQ(ierr);
10453be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
10467bffde78SMichael Lange   }
10473be36e83SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) candidateSection, "Candidate Section");CHKERRQ(ierr);
10482e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view");CHKERRQ(ierr);
10493be36e83SMatthew G. Knepley   ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates);CHKERRQ(ierr);
10503be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
10512e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
10527bffde78SMichael Lange   {
10537bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
10547bffde78SMichael Lange     PetscInt *remoteOffsets;
10552e72742cSMatthew G. Knepley 
10567bffde78SMichael Lange     ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr);
10577bffde78SMichael Lange     ierr = PetscSFCreateInverseSF(sfMulti, &sfInverse);CHKERRQ(ierr);
10583be36e83SMatthew G. Knepley     ierr = PetscSectionCreate(comm, &candidateRemoteSection);CHKERRQ(ierr);
10593be36e83SMatthew G. Knepley     ierr = PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection);CHKERRQ(ierr);
10603be36e83SMatthew G. Knepley     ierr = PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates);CHKERRQ(ierr);
10613be36e83SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize);CHKERRQ(ierr);
10627bffde78SMichael Lange     ierr = PetscMalloc1(candidatesRemoteSize, &candidatesRemote);CHKERRQ(ierr);
1063ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE);CHKERRQ(ierr);
1064ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE);CHKERRQ(ierr);
10657bffde78SMichael Lange     ierr = PetscSFDestroy(&sfInverse);CHKERRQ(ierr);
10667bffde78SMichael Lange     ierr = PetscSFDestroy(&sfCandidates);CHKERRQ(ierr);
10677bffde78SMichael Lange     ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
10682e72742cSMatthew G. Knepley 
10693be36e83SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section");CHKERRQ(ierr);
10703be36e83SMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view");CHKERRQ(ierr);
10713be36e83SMatthew G. Knepley     ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote);CHKERRQ(ierr);
10727bffde78SMichael Lange   }
10733be36e83SMatthew 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 */
10747bffde78SMichael Lange   {
10753be36e83SMatthew G. Knepley     PetscHashIJKLRemote faceTable;
10763be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
10773be36e83SMatthew G. Knepley 
10783be36e83SMatthew G. Knepley     ierr = PetscHashIJKLRemoteCreate(&faceTable);CHKERRQ(ierr);
10792e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
10803be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
10812e72742cSMatthew G. Knepley       PetscInt deg;
10823be36e83SMatthew G. Knepley 
10832e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
10842e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
10852e72742cSMatthew G. Knepley 
10863be36e83SMatthew G. Knepley         ierr = PetscSectionGetDof(candidateRemoteSection, idx, &dof);CHKERRQ(ierr);
10873be36e83SMatthew G. Knepley         ierr = PetscSectionGetOffset(candidateRemoteSection, idx, &offset);CHKERRQ(ierr);
10883be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
10892e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
10903be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
10913be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
10923be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx+1];
10933be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
10943be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
10953be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
10962e72742cSMatthew G. Knepley           const PetscInt        *join  = NULL;
10973be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
10983be36e83SMatthew G. Knepley           PetscHashIter          iter;
10993be36e83SMatthew G. Knepley           PetscBool              missing;
11002e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
11012e72742cSMatthew G. Knepley 
110266e92ce5SVaclav Hapla           if (debug) {ierr = 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);CHKERRQ(ierr);}
1103*2c71b3e2SJacob 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);
11043be36e83SMatthew G. Knepley           fcp0.rank  = rank;
11053be36e83SMatthew G. Knepley           fcp0.index = r;
11063be36e83SMatthew G. Knepley           d += Np;
11073be36e83SMatthew G. Knepley           /* Put remote face in hash table */
11083be36e83SMatthew G. Knepley           key.i = fcp0;
11093be36e83SMatthew G. Knepley           key.j = fcone[0];
11103be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
11113be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
11123be36e83SMatthew G. Knepley           ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr);
11133be36e83SMatthew G. Knepley           ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
11143be36e83SMatthew G. Knepley           if (missing) {
11153be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Setting remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);}
11163be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr);
11173be36e83SMatthew G. Knepley           } else {
11183be36e83SMatthew G. Knepley             PetscSFNode oface;
11193be36e83SMatthew G. Knepley 
11203be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr);
11213be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
11223be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);}
11233be36e83SMatthew G. Knepley               ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr);
11243be36e83SMatthew G. Knepley             }
11253be36e83SMatthew G. Knepley           }
11263be36e83SMatthew G. Knepley           /* Check for local face */
11272e72742cSMatthew G. Knepley           points[0] = r;
11283be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
11293be36e83SMatthew G. Knepley             ierr = DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p]);
11303be36e83SMatthew G. Knepley             if (ierr) break; /* We got a point not in our overlap */
11313be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Checking local candidate %D\n", rank, points[p]);CHKERRQ(ierr);}
11327bffde78SMichael Lange           }
11332e72742cSMatthew G. Knepley           if (ierr) continue;
11343be36e83SMatthew G. Knepley           ierr = DMPlexGetJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr);
11357bffde78SMichael Lange           if (joinSize == 1) {
11363be36e83SMatthew G. Knepley             PetscSFNode lface;
11373be36e83SMatthew G. Knepley             PetscSFNode oface;
11383be36e83SMatthew G. Knepley 
11393be36e83SMatthew G. Knepley             /* Always replace with local face */
11403be36e83SMatthew G. Knepley             lface.rank  = rank;
11413be36e83SMatthew G. Knepley             lface.index = join[0];
11423be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr);
11433be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing (%D, %D) with local face (%D, %D)\n", rank, oface.index, oface.rank, lface.index, lface.rank);CHKERRQ(ierr);}
11443be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, lface);CHKERRQ(ierr);
11457bffde78SMichael Lange           }
11463be36e83SMatthew G. Knepley           ierr = DMPlexRestoreJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr);
11473be36e83SMatthew G. Knepley         }
11483be36e83SMatthew G. Knepley       }
11493be36e83SMatthew G. Knepley       /* Put back faces for this root */
11503be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
11513be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
11523be36e83SMatthew G. Knepley 
11533be36e83SMatthew G. Knepley         ierr = PetscSectionGetDof(candidateRemoteSection, idx2, &dof);CHKERRQ(ierr);
11543be36e83SMatthew G. Knepley         ierr = PetscSectionGetOffset(candidateRemoteSection, idx2, &offset);CHKERRQ(ierr);
11553be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
11563be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11573be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
11583be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
11593be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
11603be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
11613be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
11623be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
11633be36e83SMatthew G. Knepley           PetscHashIter          iter;
11643be36e83SMatthew G. Knepley           PetscBool              missing;
11653be36e83SMatthew G. Knepley 
11663be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Entering face at (%D, %D)\n", rank, r, idx);CHKERRQ(ierr);}
1167*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(Np > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np);
11683be36e83SMatthew G. Knepley           fcp0.rank  = rank;
11693be36e83SMatthew G. Knepley           fcp0.index = r;
11703be36e83SMatthew G. Knepley           d += Np;
11713be36e83SMatthew G. Knepley           /* Find remote face in hash table */
11723be36e83SMatthew G. Knepley           key.i = fcp0;
11733be36e83SMatthew G. Knepley           key.j = fcone[0];
11743be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
11753be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
11763be36e83SMatthew G. Knepley           ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr);
11773be36e83SMatthew G. Knepley           if (debug) {ierr = 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);CHKERRQ(ierr);}
11783be36e83SMatthew G. Knepley           ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
1179*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(missing,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an associated face", r, idx2);
11803be36e83SMatthew G. Knepley           else        {ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]);CHKERRQ(ierr);}
11817bffde78SMichael Lange         }
11827bffde78SMichael Lange       }
11837bffde78SMichael Lange     }
11842e72742cSMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL);CHKERRQ(ierr);}
11853be36e83SMatthew G. Knepley     ierr = PetscHashIJKLRemoteDestroy(&faceTable);CHKERRQ(ierr);
11867bffde78SMichael Lange   }
11873be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
11887bffde78SMichael Lange   {
11897bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
11907bffde78SMichael Lange     PetscSFNode *remotePointsNew;
11912e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
11923be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
11932e72742cSMatthew G. Knepley 
11943be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
11957bffde78SMichael Lange     ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr);
11963be36e83SMatthew G. Knepley     ierr = PetscSectionCreate(comm, &claimSection);CHKERRQ(ierr);
11973be36e83SMatthew G. Knepley     ierr = PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection);CHKERRQ(ierr);
11983be36e83SMatthew G. Knepley     ierr = PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims);CHKERRQ(ierr);
11992e72742cSMatthew G. Knepley     ierr = PetscSectionGetStorageSize(claimSection, &claimsSize);CHKERRQ(ierr);
12002e72742cSMatthew G. Knepley     ierr = PetscMalloc1(claimsSize, &claims);CHKERRQ(ierr);
12013be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
1202ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE);CHKERRQ(ierr);
1203ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE);CHKERRQ(ierr);
12047bffde78SMichael Lange     ierr = PetscSFDestroy(&sfClaims);CHKERRQ(ierr);
12057bffde78SMichael Lange     ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
12063be36e83SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) claimSection, "Claim Section");CHKERRQ(ierr);
12072e72742cSMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view");CHKERRQ(ierr);
12083be36e83SMatthew G. Knepley     ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims);CHKERRQ(ierr);
12093be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
12103be36e83SMatthew 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 */
1211e8f14785SLisandro Dalcin     ierr = PetscHMapICreate(&claimshash);CHKERRQ(ierr);
12123be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
12133be36e83SMatthew G. Knepley       PetscInt dof, off, d;
12142e72742cSMatthew G. Knepley 
12153be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %D\n", rank, r);CHKERRQ(ierr);}
12163be36e83SMatthew G. Knepley       ierr = PetscSectionGetDof(candidateSection, r, &dof);CHKERRQ(ierr);
12173be36e83SMatthew G. Knepley       ierr = PetscSectionGetOffset(candidateSection, r, &off);CHKERRQ(ierr);
12182e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
12193be36e83SMatthew G. Knepley         if (claims[off+d].rank >= 0) {
12203be36e83SMatthew G. Knepley           const PetscInt  faceInd = off+d;
12213be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off+d].index;
12222e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
12232e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
12242e72742cSMatthew G. Knepley 
12253be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%D, %D)\n", rank, claims[faceInd].rank, claims[faceInd].index);CHKERRQ(ierr);}
12263be36e83SMatthew G. Knepley           points[0] = r;
12273be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]      point %D\n", rank, points[0]);CHKERRQ(ierr);}
12283be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
12293be36e83SMatthew G. Knepley             ierr = DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1]);CHKERRQ(ierr);
12303be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]      point %D\n", rank, points[c+1]);CHKERRQ(ierr);}
12312e72742cSMatthew G. Knepley           }
12323be36e83SMatthew G. Knepley           ierr = DMPlexGetJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr);
12332e72742cSMatthew G. Knepley           if (joinSize == 1) {
12343be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
12353be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %D for non-remote partner\n", rank, join[0]);CHKERRQ(ierr);}
12363be36e83SMatthew G. Knepley             } else {
12373be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Found local face %D\n", rank, join[0]);CHKERRQ(ierr);}
12382e72742cSMatthew G. Knepley               ierr = PetscHMapISet(claimshash, join[0], faceInd);CHKERRQ(ierr);
12392e72742cSMatthew G. Knepley             }
12403be36e83SMatthew G. Knepley           } else {
12413be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank);CHKERRQ(ierr);}
12423be36e83SMatthew G. Knepley           }
12433be36e83SMatthew G. Knepley           ierr = DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr);
12443be36e83SMatthew G. Knepley         } else {
12453be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    No claim for point %D\n", rank, r);CHKERRQ(ierr);}
12463be36e83SMatthew G. Knepley           d += claims[off+d].index+1;
12477bffde78SMichael Lange         }
12487bffde78SMichael Lange       }
12493be36e83SMatthew G. Knepley     }
12503be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
12513be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
12523be36e83SMatthew G. Knepley     ierr = PetscHMapIGetSize(claimshash, &NlNew);CHKERRQ(ierr);
12537bffde78SMichael Lange     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
12543be36e83SMatthew G. Knepley     ierr = PetscMalloc1(Nl + NlNew, &localPointsNew);CHKERRQ(ierr);
12553be36e83SMatthew G. Knepley     ierr = PetscMalloc1(Nl + NlNew, &remotePointsNew);CHKERRQ(ierr);
12563be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12573be36e83SMatthew G. Knepley       localPointsNew[l] = localPoints[l];
12583be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
12593be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
12607bffde78SMichael Lange     }
12613be36e83SMatthew G. Knepley     p = Nl;
1262e8f14785SLisandro Dalcin     ierr = PetscHMapIGetKeys(claimshash, &p, localPointsNew);CHKERRQ(ierr);
12633be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
12643be36e83SMatthew G. Knepley     ierr = PetscSortInt(NlNew, &localPointsNew[Nl]);CHKERRQ(ierr);
12653be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
12663be36e83SMatthew G. Knepley       PetscInt off;
12673be36e83SMatthew G. Knepley       ierr = PetscHMapIGet(claimshash, localPointsNew[p], &off);CHKERRQ(ierr);
1268*2c71b3e2SJacob 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);
12693be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
12707bffde78SMichael Lange     }
12713be36e83SMatthew G. Knepley     ierr = PetscSFCreate(comm, &sfPointNew);CHKERRQ(ierr);
12723be36e83SMatthew G. Knepley     ierr = PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
12733be36e83SMatthew G. Knepley     ierr = PetscSFSetUp(sfPointNew);CHKERRQ(ierr);
12747bffde78SMichael Lange     ierr = DMSetPointSF(dm, sfPointNew);CHKERRQ(ierr);
12753be36e83SMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view");CHKERRQ(ierr);
12767bffde78SMichael Lange     ierr = PetscSFDestroy(&sfPointNew);CHKERRQ(ierr);
1277e8f14785SLisandro Dalcin     ierr = PetscHMapIDestroy(&claimshash);CHKERRQ(ierr);
12787bffde78SMichael Lange   }
12793be36e83SMatthew G. Knepley   ierr = PetscHMapIJDestroy(&remoteHash);CHKERRQ(ierr);
12807bffde78SMichael Lange   ierr = PetscSectionDestroy(&candidateSection);CHKERRQ(ierr);
12813be36e83SMatthew G. Knepley   ierr = PetscSectionDestroy(&candidateRemoteSection);CHKERRQ(ierr);
12827bffde78SMichael Lange   ierr = PetscSectionDestroy(&claimSection);CHKERRQ(ierr);
12837bffde78SMichael Lange   ierr = PetscFree(candidates);CHKERRQ(ierr);
12847bffde78SMichael Lange   ierr = PetscFree(candidatesRemote);CHKERRQ(ierr);
12857bffde78SMichael Lange   ierr = PetscFree(claims);CHKERRQ(ierr);
128625afeb17SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr);
12877bffde78SMichael Lange   PetscFunctionReturn(0);
12887bffde78SMichael Lange }
12897bffde78SMichael Lange 
1290248eb259SVaclav Hapla /*@
129180330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
129280330477SMatthew G. Knepley 
1293d083f849SBarry Smith   Collective on dm
129480330477SMatthew G. Knepley 
1295e56d480eSMatthew G. Knepley   Input Parameters:
1296e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices
129710a67516SMatthew G. Knepley - dmInt - The interpolated DM
129880330477SMatthew G. Knepley 
129980330477SMatthew G. Knepley   Output Parameter:
13004e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object
130180330477SMatthew G. Knepley 
130280330477SMatthew G. Knepley   Level: intermediate
130380330477SMatthew G. Knepley 
130495452b02SPatrick Sanan   Notes:
130595452b02SPatrick Sanan     It does not copy over the coordinates.
130643eeeb2dSStefano Zampini 
13079ade3219SVaclav Hapla   Developer Notes:
13089ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL.
13099ade3219SVaclav Hapla 
1310a4a685f2SJacob Faibussowitsch .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates()
131180330477SMatthew G. Knepley @*/
13129f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
13139f074e33SMatthew G Knepley {
1314a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
13159a5b13a2SMatthew G Knepley   DM             idm, odm = dm;
13167bffde78SMichael Lange   PetscSF        sfPoint;
13172e1b13c2SMatthew G. Knepley   PetscInt       depth, dim, d;
131810a67516SMatthew G. Knepley   const char    *name;
1319b325530aSVaclav Hapla   PetscBool      flg=PETSC_TRUE;
13209f074e33SMatthew G Knepley   PetscErrorCode ierr;
13219f074e33SMatthew G Knepley 
13229f074e33SMatthew G Knepley   PetscFunctionBegin;
132310a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
132410a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
1325a72f3261SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr);
13262e1b13c2SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1327c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1328827c4036SVaclav Hapla   ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr);
1329*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(interpolated == DMPLEX_INTERPOLATED_PARTIAL,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1330827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
133176b791aaSMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
133276b791aaSMatthew G. Knepley     idm  = dm;
1333b21b8912SMatthew G. Knepley   } else {
13349a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
13359a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
133610a67516SMatthew G. Knepley       ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr);
13379a5b13a2SMatthew G Knepley       ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr);
1338c73cfb54SMatthew G. Knepley       ierr = DMSetDimension(idm, dim);CHKERRQ(ierr);
13397bffde78SMichael Lange       if (depth > 0) {
13407bffde78SMichael Lange         ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr);
13417bffde78SMichael Lange         ierr = DMGetPointSF(odm, &sfPoint);CHKERRQ(ierr);
134294488200SVaclav Hapla         {
13433be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
134494488200SVaclav Hapla           PetscInt nroots;
134594488200SVaclav Hapla           ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
134694488200SVaclav Hapla           if (nroots >= 0) {ierr = DMPlexInterpolatePointSF(idm, sfPoint);CHKERRQ(ierr);}
134794488200SVaclav Hapla         }
13487bffde78SMichael Lange       }
13499a5b13a2SMatthew G Knepley       if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);}
13509a5b13a2SMatthew G Knepley       odm = idm;
13519f074e33SMatthew G Knepley     }
135210a67516SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) dm,  &name);CHKERRQ(ierr);
135310a67516SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) idm,  name);CHKERRQ(ierr);
135410a67516SMatthew G. Knepley     ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr);
13552cbb9b06SVaclav Hapla     ierr = DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL);CHKERRQ(ierr);
1356b325530aSVaclav Hapla     ierr = PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL);CHKERRQ(ierr);
135727d0e99aSVaclav Hapla     if (flg) {ierr = DMPlexOrientInterface_Internal(idm);CHKERRQ(ierr);}
135884699f70SSatish Balay   }
135943eeeb2dSStefano Zampini   {
136043eeeb2dSStefano Zampini     PetscBool            isper;
136143eeeb2dSStefano Zampini     const PetscReal      *maxCell, *L;
136243eeeb2dSStefano Zampini     const DMBoundaryType *bd;
136343eeeb2dSStefano Zampini 
136443eeeb2dSStefano Zampini     ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr);
136543eeeb2dSStefano Zampini     ierr = DMSetPeriodicity(idm,isper,maxCell,L,bd);CHKERRQ(ierr);
136643eeeb2dSStefano Zampini   }
1367827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1368827c4036SVaclav Hapla   {
1369d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) idm->data;
1370827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1371827c4036SVaclav Hapla   }
13729a5b13a2SMatthew G Knepley   *dmInt = idm;
1373a72f3261SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr);
13749f074e33SMatthew G Knepley   PetscFunctionReturn(0);
13759f074e33SMatthew G Knepley }
137607b0a1fcSMatthew G Knepley 
137780330477SMatthew G. Knepley /*@
137880330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
137980330477SMatthew G. Knepley 
1380d083f849SBarry Smith   Collective on dmA
138180330477SMatthew G. Knepley 
138280330477SMatthew G. Knepley   Input Parameter:
138380330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates
138480330477SMatthew G. Knepley 
138580330477SMatthew G. Knepley   Output Parameter:
138680330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates
138780330477SMatthew G. Knepley 
138880330477SMatthew G. Knepley   Level: intermediate
138980330477SMatthew G. Knepley 
139080330477SMatthew G. Knepley   Note: This is typically used when adding pieces other than vertices to a mesh
139180330477SMatthew G. Knepley 
139265f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
139380330477SMatthew G. Knepley @*/
139407b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
139507b0a1fcSMatthew G Knepley {
139607b0a1fcSMatthew G Knepley   Vec            coordinatesA, coordinatesB;
139743eeeb2dSStefano Zampini   VecType        vtype;
139807b0a1fcSMatthew G Knepley   PetscSection   coordSectionA, coordSectionB;
139907b0a1fcSMatthew G Knepley   PetscScalar   *coordsA, *coordsB;
14000bedd6beSMatthew G. Knepley   PetscInt       spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
140190a8aa44SJed Brown   PetscInt       cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
140243eeeb2dSStefano Zampini   PetscBool      lc = PETSC_FALSE;
140307b0a1fcSMatthew G Knepley   PetscErrorCode ierr;
140407b0a1fcSMatthew G Knepley 
140507b0a1fcSMatthew G Knepley   PetscFunctionBegin;
140643eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
140743eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
140876b791aaSMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
140990a8aa44SJed Brown   ierr = DMGetCoordinateDim(dmA, &cdim);CHKERRQ(ierr);
141090a8aa44SJed Brown   ierr = DMSetCoordinateDim(dmB, cdim);CHKERRQ(ierr);
141107b0a1fcSMatthew G Knepley   ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr);
141207b0a1fcSMatthew G Knepley   ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr);
1413*2c71b3e2SJacob 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);
141461a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
141561a622f3SMatthew G. Knepley   {
141661a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
141761a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
141861a622f3SMatthew G. Knepley     PetscObject        objA, objB;
141961a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
142061a622f3SMatthew G. Knepley     const PetscScalar *constants;
142161a622f3SMatthew G. Knepley     PetscInt            cdim, Nc;
142261a622f3SMatthew G. Knepley 
142361a622f3SMatthew G. Knepley     ierr = DMGetCoordinateDM(dmA, &cdmA);CHKERRQ(ierr);
142461a622f3SMatthew G. Knepley     ierr = DMGetCoordinateDM(dmB, &cdmB);CHKERRQ(ierr);
142561a622f3SMatthew G. Knepley     ierr = DMGetField(cdmA, 0, NULL, &objA);CHKERRQ(ierr);
142661a622f3SMatthew G. Knepley     ierr = DMGetField(cdmB, 0, NULL, &objB);CHKERRQ(ierr);
142761a622f3SMatthew G. Knepley     ierr = PetscObjectGetClassId(objA, &idA);CHKERRQ(ierr);
142861a622f3SMatthew G. Knepley     ierr = PetscObjectGetClassId(objB, &idB);CHKERRQ(ierr);
142961a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
143061a622f3SMatthew G. Knepley       ierr = DMSetField(cdmB, 0, NULL, objA);CHKERRQ(ierr);
143161a622f3SMatthew G. Knepley       ierr = DMCreateDS(cdmB);CHKERRQ(ierr);
143261a622f3SMatthew G. Knepley       ierr = DMGetDS(cdmA, &dsA);CHKERRQ(ierr);
143361a622f3SMatthew G. Knepley       ierr = DMGetDS(cdmB, &dsB);CHKERRQ(ierr);
143461a622f3SMatthew G. Knepley       ierr = PetscDSGetCoordinateDimension(dsA, &cdim);CHKERRQ(ierr);
143561a622f3SMatthew G. Knepley       ierr = PetscDSSetCoordinateDimension(dsB, cdim);CHKERRQ(ierr);
143661a622f3SMatthew G. Knepley       ierr = PetscDSGetConstants(dsA, &Nc, &constants);CHKERRQ(ierr);
143761a622f3SMatthew G. Knepley       ierr = PetscDSSetConstants(dsB, Nc, (PetscScalar *) constants);CHKERRQ(ierr);
143861a622f3SMatthew G. Knepley     }
143961a622f3SMatthew G. Knepley   }
144043eeeb2dSStefano Zampini   ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr);
144143eeeb2dSStefano Zampini   ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr);
144269d8a9ceSMatthew G. Knepley   ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr);
144369d8a9ceSMatthew G. Knepley   ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr);
1444972bc18aSToby Isaac   if (coordSectionA == coordSectionB) PetscFunctionReturn(0);
14450bedd6beSMatthew G. Knepley   ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr);
14460bedd6beSMatthew G. Knepley   if (!Nf) PetscFunctionReturn(0);
1447*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nf > 1,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf);
1448df26b574SMatthew G. Knepley   if (!coordSectionB) {
1449df26b574SMatthew G. Knepley     PetscInt dim;
1450df26b574SMatthew G. Knepley 
1451df26b574SMatthew G. Knepley     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr);
1452df26b574SMatthew G. Knepley     ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr);
1453df26b574SMatthew G. Knepley     ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr);
1454df26b574SMatthew G. Knepley     ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr);
1455df26b574SMatthew G. Knepley   }
145607b0a1fcSMatthew G Knepley   ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr);
145707b0a1fcSMatthew G Knepley   ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr);
145807b0a1fcSMatthew G Knepley   ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr);
145943eeeb2dSStefano Zampini   ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr);
146043eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
1461*2c71b3e2SJacob 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);
146243eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
146343eeeb2dSStefano Zampini     cE = vEndB;
146443eeeb2dSStefano Zampini     lc = PETSC_TRUE;
146543eeeb2dSStefano Zampini   } else {
146643eeeb2dSStefano Zampini     cS = vStartB;
146743eeeb2dSStefano Zampini     cE = vEndB;
146843eeeb2dSStefano Zampini   }
146943eeeb2dSStefano Zampini   ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr);
147007b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
147107b0a1fcSMatthew G Knepley     ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr);
147207b0a1fcSMatthew G Knepley     ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr);
147307b0a1fcSMatthew G Knepley   }
147443eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
147543eeeb2dSStefano Zampini     PetscInt c;
147643eeeb2dSStefano Zampini 
147743eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
147843eeeb2dSStefano Zampini       PetscInt dof;
147943eeeb2dSStefano Zampini 
148043eeeb2dSStefano Zampini       ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr);
148143eeeb2dSStefano Zampini       ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr);
148243eeeb2dSStefano Zampini       ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr);
148343eeeb2dSStefano Zampini     }
148443eeeb2dSStefano Zampini   }
148507b0a1fcSMatthew G Knepley   ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr);
148607b0a1fcSMatthew G Knepley   ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr);
148707b0a1fcSMatthew G Knepley   ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr);
14888b9ced59SLisandro Dalcin   ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr);
148907b0a1fcSMatthew G Knepley   ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr);
149007b0a1fcSMatthew G Knepley   ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr);
149143eeeb2dSStefano Zampini   ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr);
149243eeeb2dSStefano Zampini   ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr);
149343eeeb2dSStefano Zampini   ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr);
149443eeeb2dSStefano Zampini   ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr);
149507b0a1fcSMatthew G Knepley   ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr);
149607b0a1fcSMatthew G Knepley   ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr);
149707b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB-vStartB; ++v) {
149843eeeb2dSStefano Zampini     PetscInt offA, offB;
149943eeeb2dSStefano Zampini 
150043eeeb2dSStefano Zampini     ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr);
150143eeeb2dSStefano Zampini     ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr);
150207b0a1fcSMatthew G Knepley     for (d = 0; d < spaceDim; ++d) {
150343eeeb2dSStefano Zampini       coordsB[offB+d] = coordsA[offA+d];
150443eeeb2dSStefano Zampini     }
150543eeeb2dSStefano Zampini   }
150643eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
150743eeeb2dSStefano Zampini     PetscInt c;
150843eeeb2dSStefano Zampini 
150943eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
151043eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
151143eeeb2dSStefano Zampini 
151243eeeb2dSStefano Zampini       ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr);
151343eeeb2dSStefano Zampini       ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr);
151443eeeb2dSStefano Zampini       ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr);
1515580bdb30SBarry Smith       ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr);
151607b0a1fcSMatthew G Knepley     }
151707b0a1fcSMatthew G Knepley   }
151807b0a1fcSMatthew G Knepley   ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr);
151907b0a1fcSMatthew G Knepley   ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr);
152007b0a1fcSMatthew G Knepley   ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr);
152107b0a1fcSMatthew G Knepley   ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr);
152207b0a1fcSMatthew G Knepley   PetscFunctionReturn(0);
152307b0a1fcSMatthew G Knepley }
15245c386225SMatthew G. Knepley 
15254e3744c5SMatthew G. Knepley /*@
15264e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
15274e3744c5SMatthew G. Knepley 
1528d083f849SBarry Smith   Collective on dm
15294e3744c5SMatthew G. Knepley 
15304e3744c5SMatthew G. Knepley   Input Parameter:
15314e3744c5SMatthew G. Knepley . dm - The complete DMPlex object
15324e3744c5SMatthew G. Knepley 
15334e3744c5SMatthew G. Knepley   Output Parameter:
15344e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices
15354e3744c5SMatthew G. Knepley 
15364e3744c5SMatthew G. Knepley   Level: intermediate
15374e3744c5SMatthew G. Knepley 
153895452b02SPatrick Sanan   Notes:
153995452b02SPatrick Sanan     It does not copy over the coordinates.
154043eeeb2dSStefano Zampini 
15419ade3219SVaclav Hapla   Developer Notes:
15429ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
15439ade3219SVaclav Hapla 
1544a4a685f2SJacob Faibussowitsch .seealso: DMPlexInterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates()
15454e3744c5SMatthew G. Knepley @*/
15464e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
15474e3744c5SMatthew G. Knepley {
1548827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
15494e3744c5SMatthew G. Knepley   DM             udm;
1550412e9a14SMatthew G. Knepley   PetscInt       dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
15514e3744c5SMatthew G. Knepley   PetscErrorCode ierr;
15524e3744c5SMatthew G. Knepley 
15534e3744c5SMatthew G. Knepley   PetscFunctionBegin;
155443eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
155543eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
1556c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1557827c4036SVaclav Hapla   ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr);
1558*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(interpolated == DMPLEX_INTERPOLATED_PARTIAL,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1559827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1560827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
15614e3744c5SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
1562595d4abbSMatthew G. Knepley     *dmUnint = dm;
1563595d4abbSMatthew G. Knepley     PetscFunctionReturn(0);
15644e3744c5SMatthew G. Knepley   }
1565595d4abbSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1566595d4abbSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
15674e3744c5SMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr);
15684e3744c5SMatthew G. Knepley   ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr);
1569c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(udm, dim);CHKERRQ(ierr);
15704e3744c5SMatthew G. Knepley   ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr);
15714e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1572595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
15734e3744c5SMatthew G. Knepley 
15744e3744c5SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
15754e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
15764e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
15774e3744c5SMatthew G. Knepley 
15784e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
15794e3744c5SMatthew G. Knepley     }
15804e3744c5SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
15814e3744c5SMatthew G. Knepley     ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr);
1582595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
15834e3744c5SMatthew G. Knepley   }
15844e3744c5SMatthew G. Knepley   ierr = DMSetUp(udm);CHKERRQ(ierr);
1585785e854fSJed Brown   ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr);
15864e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1587595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
15884e3744c5SMatthew G. Knepley 
15894e3744c5SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
15904e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
15914e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
15924e3744c5SMatthew G. Knepley 
15934e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
15944e3744c5SMatthew G. Knepley     }
15954e3744c5SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
15964e3744c5SMatthew G. Knepley     ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr);
15974e3744c5SMatthew G. Knepley   }
15984e3744c5SMatthew G. Knepley   ierr = PetscFree(cone);CHKERRQ(ierr);
15994e3744c5SMatthew G. Knepley   ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr);
16004e3744c5SMatthew G. Knepley   ierr = DMPlexStratify(udm);CHKERRQ(ierr);
16015c7de58aSMatthew G. Knepley   /* Reduce SF */
16025c7de58aSMatthew G. Knepley   {
16035c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
16045c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
16055c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
16065c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
16075c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
16085c7de58aSMatthew G. Knepley     PetscInt           vEnd, numRoots, numLeaves, l;
16095c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
16105c7de58aSMatthew G. Knepley     PetscErrorCode     ierr;
16115c7de58aSMatthew G. Knepley 
16125c7de58aSMatthew G. Knepley     /* Get original SF information */
16135c7de58aSMatthew G. Knepley     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
16145c7de58aSMatthew G. Knepley     ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr);
16155c7de58aSMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr);
16165c7de58aSMatthew G. Knepley     ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
16175c7de58aSMatthew G. Knepley     /* Allocate space for cells and vertices */
16185c7de58aSMatthew G. Knepley     for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++;
16195c7de58aSMatthew G. Knepley     /* Fill in leaves */
16205c7de58aSMatthew G. Knepley     if (vEnd >= 0) {
16215c7de58aSMatthew G. Knepley       ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr);
16225c7de58aSMatthew G. Knepley       ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr);
16235c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
16245c7de58aSMatthew G. Knepley         if (localPoints[l] < vEnd) {
16255c7de58aSMatthew G. Knepley           localPointsUn[n]        = localPoints[l];
16265c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
16275c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
16285c7de58aSMatthew G. Knepley           ++n;
16295c7de58aSMatthew G. Knepley         }
16305c7de58aSMatthew G. Knepley       }
1631*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(n != numLeavesUn,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn);
16325c7de58aSMatthew G. Knepley       ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr);
16335c7de58aSMatthew G. Knepley     }
16345c7de58aSMatthew G. Knepley   }
163543eeeb2dSStefano Zampini   {
163643eeeb2dSStefano Zampini     PetscBool            isper;
163743eeeb2dSStefano Zampini     const PetscReal      *maxCell, *L;
163843eeeb2dSStefano Zampini     const DMBoundaryType *bd;
163943eeeb2dSStefano Zampini 
164043eeeb2dSStefano Zampini     ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr);
164143eeeb2dSStefano Zampini     ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr);
164243eeeb2dSStefano Zampini   }
1643827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1644827c4036SVaclav Hapla   {
1645d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) udm->data;
1646827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1647827c4036SVaclav Hapla   }
16484e3744c5SMatthew G. Knepley   *dmUnint = udm;
16494e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
16504e3744c5SMatthew G. Knepley }
1651a7748839SVaclav Hapla 
1652a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1653a7748839SVaclav Hapla {
1654a7748839SVaclav Hapla   PetscInt       coneSize, depth, dim, h, p, pStart, pEnd;
1655a7748839SVaclav Hapla   MPI_Comm       comm;
1656a7748839SVaclav Hapla   PetscErrorCode ierr;
1657a7748839SVaclav Hapla 
1658a7748839SVaclav Hapla   PetscFunctionBegin;
1659a7748839SVaclav Hapla   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
1660a7748839SVaclav Hapla   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1661a7748839SVaclav Hapla   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1662a7748839SVaclav Hapla 
1663a7748839SVaclav Hapla   if (depth == dim) {
1664a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1665a7748839SVaclav Hapla     if (!dim) goto finish;
1666a7748839SVaclav Hapla 
1667a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
1668a7748839SVaclav Hapla     ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr);
1669a7748839SVaclav Hapla     for (p=pStart; p<pEnd; p++) {
1670a7748839SVaclav Hapla       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1671a7748839SVaclav Hapla       if (coneSize) {
1672a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1673a7748839SVaclav Hapla         goto finish;
1674a7748839SVaclav Hapla       }
1675a7748839SVaclav Hapla     }
1676a7748839SVaclav Hapla 
1677a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1678a7748839SVaclav Hapla     for (h=0; h<dim; h++) {
1679a7748839SVaclav Hapla       ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr);
1680a7748839SVaclav Hapla       for (p=pStart; p<pEnd; p++) {
1681a7748839SVaclav Hapla         ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1682a7748839SVaclav Hapla         if (!coneSize) {
1683a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1684a7748839SVaclav Hapla           goto finish;
1685a7748839SVaclav Hapla         }
1686a7748839SVaclav Hapla       }
1687a7748839SVaclav Hapla     }
1688a7748839SVaclav Hapla   } else if (depth == 1) {
1689a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1690a7748839SVaclav Hapla   } else {
1691a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1692a7748839SVaclav Hapla   }
1693a7748839SVaclav Hapla finish:
1694a7748839SVaclav Hapla   PetscFunctionReturn(0);
1695a7748839SVaclav Hapla }
1696a7748839SVaclav Hapla 
1697a7748839SVaclav Hapla /*@
16989ade3219SVaclav Hapla   DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated.
1699a7748839SVaclav Hapla 
1700a7748839SVaclav Hapla   Not Collective
1701a7748839SVaclav Hapla 
1702a7748839SVaclav Hapla   Input Parameter:
1703a7748839SVaclav Hapla . dm      - The DM object
1704a7748839SVaclav Hapla 
1705a7748839SVaclav Hapla   Output Parameter:
1706a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1707a7748839SVaclav Hapla 
1708a7748839SVaclav Hapla   Level: intermediate
1709a7748839SVaclav Hapla 
1710a7748839SVaclav Hapla   Notes:
17119ade3219SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this is NOT collective
17129ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
1713a7748839SVaclav Hapla   However, DMPlexInterpolate() guarantees the result is the same on all.
17149ade3219SVaclav Hapla 
1715a7748839SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED.
1716a7748839SVaclav Hapla 
17179ade3219SVaclav Hapla   Developer Notes:
17189ade3219SVaclav Hapla   Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID.
17199ade3219SVaclav Hapla 
17209ade3219SVaclav Hapla   If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called.
17219ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
17229ade3219SVaclav Hapla   DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL.
17239ade3219SVaclav Hapla 
17249ade3219SVaclav Hapla   If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated.
17259ade3219SVaclav Hapla 
17269ade3219SVaclav Hapla   DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL,
17279ade3219SVaclav Hapla   and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
17289ade3219SVaclav Hapla 
1729a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective()
1730a7748839SVaclav Hapla @*/
1731a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1732a7748839SVaclav Hapla {
1733a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1734a7748839SVaclav Hapla   PetscErrorCode  ierr;
1735a7748839SVaclav Hapla 
1736a7748839SVaclav Hapla   PetscFunctionBegin;
1737a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1738a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
1739a7748839SVaclav Hapla   if (plex->interpolated < 0) {
1740a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr);
174176bd3646SJed Brown   } else if (PetscDefined (USE_DEBUG)) {
1742a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1743a7748839SVaclav Hapla 
1744a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr);
1745*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(flg != plex->interpolated,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1746a7748839SVaclav Hapla   }
1747a7748839SVaclav Hapla   *interpolated = plex->interpolated;
1748a7748839SVaclav Hapla   PetscFunctionReturn(0);
1749a7748839SVaclav Hapla }
1750a7748839SVaclav Hapla 
1751a7748839SVaclav Hapla /*@
17529ade3219SVaclav Hapla   DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner).
1753a7748839SVaclav Hapla 
17542666ff3cSVaclav Hapla   Collective
1755a7748839SVaclav Hapla 
1756a7748839SVaclav Hapla   Input Parameter:
1757a7748839SVaclav Hapla . dm      - The DM object
1758a7748839SVaclav Hapla 
1759a7748839SVaclav Hapla   Output Parameter:
1760a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1761a7748839SVaclav Hapla 
1762a7748839SVaclav Hapla   Level: intermediate
1763a7748839SVaclav Hapla 
1764a7748839SVaclav Hapla   Notes:
17659ade3219SVaclav Hapla   Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks.
17669ade3219SVaclav Hapla 
17679ade3219SVaclav Hapla   This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks.
17689ade3219SVaclav Hapla 
17699ade3219SVaclav Hapla   Developer Notes:
17709ade3219SVaclav Hapla   Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID.
17719ade3219SVaclav Hapla 
17729ade3219SVaclav Hapla   If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated.
17739ade3219SVaclav Hapla   MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
17749ade3219SVaclav Hapla   if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED,
17759ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
17769ade3219SVaclav Hapla 
17779ade3219SVaclav Hapla   If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective.
1778a7748839SVaclav Hapla 
1779a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated()
1780a7748839SVaclav Hapla @*/
1781a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1782a7748839SVaclav Hapla {
1783a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1784a7748839SVaclav Hapla   PetscBool       debug=PETSC_FALSE;
1785a7748839SVaclav Hapla   PetscErrorCode  ierr;
1786a7748839SVaclav Hapla 
1787a7748839SVaclav Hapla   PetscFunctionBegin;
1788a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1789a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
1790a7748839SVaclav Hapla   ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr);
1791a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1792a7748839SVaclav Hapla     DMPlexInterpolatedFlag  min, max;
1793a7748839SVaclav Hapla     MPI_Comm                comm;
1794a7748839SVaclav Hapla 
1795a7748839SVaclav Hapla     ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
1796a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr);
1797ffc4695bSBarry Smith     ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRMPI(ierr);
1798ffc4695bSBarry Smith     ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRMPI(ierr);
1799a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1800a7748839SVaclav Hapla     if (debug) {
1801a7748839SVaclav Hapla       PetscMPIInt rank;
1802a7748839SVaclav Hapla 
1803ffc4695bSBarry Smith       ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1804a7748839SVaclav Hapla       ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr);
1805a7748839SVaclav Hapla       ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr);
1806a7748839SVaclav Hapla     }
1807a7748839SVaclav Hapla   }
1808a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
1809a7748839SVaclav Hapla   PetscFunctionReturn(0);
1810a7748839SVaclav Hapla }
1811