xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision da9060c4ebf05b549ae65df4db64c7bee7b2b8a9)
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 
20e8f14785SLisandro Dalcin 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 
333be36e83SMatthew G. Knepley 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;
283*da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
284*da9060c4SMatthew G. Knepley       /*
285*da9060c4SMatthew G. Knepley        4----
286*da9060c4SMatthew G. Knepley        |\-\ \-----
287*da9060c4SMatthew G. Knepley        | \ -\     \
288*da9060c4SMatthew G. Knepley        |  1--\-----2
289*da9060c4SMatthew G. Knepley        | /    \   /
290*da9060c4SMatthew G. Knepley        |/      \ /
291*da9060c4SMatthew G. Knepley        0--------3
292*da9060c4SMatthew G. Knepley        */
293*da9060c4SMatthew G. Knepley       if (numFaces) *numFaces = 5;
294*da9060c4SMatthew G. Knepley       if (faceTypes) {
295*da9060c4SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
296*da9060c4SMatthew G. Knepley         typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; typesTmp[4] = DM_POLYTOPE_TRIANGLE;
297*da9060c4SMatthew G. Knepley         *faceTypes = typesTmp;
298*da9060c4SMatthew G. Knepley       }
299*da9060c4SMatthew G. Knepley       if (faceSizes) {
300*da9060c4SMatthew G. Knepley         sizesTmp[0] = 4;
301*da9060c4SMatthew G. Knepley         sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; sizesTmp[4] = 3;
302*da9060c4SMatthew G. Knepley         *faceSizes = sizesTmp;
303*da9060c4SMatthew G. Knepley       }
304*da9060c4SMatthew G. Knepley       if (faces) {
305*da9060c4SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
306*da9060c4SMatthew G. Knepley         facesTmp[4]  = cone[0]; facesTmp[5]  = cone[3]; facesTmp[6]  = cone[4];                         /* Front */
307*da9060c4SMatthew G. Knepley         facesTmp[7]  = cone[3]; facesTmp[8]  = cone[2]; facesTmp[9]  = cone[4];                         /* Right */
308*da9060c4SMatthew G. Knepley         facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[4];                         /* Back */
309*da9060c4SMatthew G. Knepley         facesTmp[13] = cone[1]; facesTmp[14] = cone[0]; facesTmp[15] = cone[4];                         /* Left */
310*da9060c4SMatthew G. Knepley         *faces = facesTmp;
311*da9060c4SMatthew G. Knepley       }
312*da9060c4SMatthew G. Knepley       break;
313ba2698f1SMatthew G. Knepley     default: SETERRQ1(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];
335412e9a14SMatthew G. Knepley   PetscInt       depth, d, 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 
363412e9a14SMatthew G. Knepley       if (faceSize > 4) SETERRQ1(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 
403412e9a14SMatthew G. Knepley           if (faceSize > 4) SETERRQ1(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) {
415412e9a14SMatthew G. Knepley         if (faceTypeStart[ct] != faceTypeStart[ct-1] + faceTypeNum[ct]) SETERRQ4(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 */
420412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, NULL, &Np);CHKERRQ(ierr);
421412e9a14SMatthew G. Knepley   ierr = DMPlexSetChart(idm, 0, 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 
459412e9a14SMatthew G. Knepley       if (faceSize > 4) SETERRQ1(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);
466412e9a14SMatthew G. Knepley       if (missing) SETERRQ2(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 
517412e9a14SMatthew G. Knepley       if (faceSize > 4) SETERRQ1(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       /* TODO This should be unnecessary since we have autoamtic orientation */
529412e9a14SMatthew G. Knepley       {
530a74221b0SStefano Zampini         /* when matching hybrid faces in 3D, only few cases are possible.
531a74221b0SStefano Zampini            Face traversal however can no longer follow the usual convention, this seems a serious issue to me */
532a74221b0SStefano Zampini         PetscInt        tquad_map[4][4] = { {PETSC_MIN_INT,            0,PETSC_MIN_INT,PETSC_MIN_INT},
533a74221b0SStefano Zampini                                             {           -1,PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT},
534a74221b0SStefano Zampini                                             {PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT,            1},
535a74221b0SStefano Zampini                                             {PETSC_MIN_INT,PETSC_MIN_INT,           -2,PETSC_MIN_INT} };
536412e9a14SMatthew G. Knepley         PetscInt        i, i2, j;
537412e9a14SMatthew G. Knepley         const PetscInt *cone;
538412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
539a74221b0SStefano Zampini 
540412e9a14SMatthew G. Knepley         /* Orient face: Do not allow reverse orientation at the first vertex */
541412e9a14SMatthew G. Knepley         ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr);
542412e9a14SMatthew G. Knepley         ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr);
543412e9a14SMatthew G. Knepley         if (coneSize != faceSize) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %D for face %D should be %D", coneSize, f, faceSize);
544412e9a14SMatthew G. Knepley         /* - First find the initial vertex */
545412e9a14SMatthew G. Knepley         for (i = 0; i < faceSize; ++i) if (face[0] == cone[i]) break;
546412e9a14SMatthew G. Knepley         /* If we want to compare tensor faces to regular faces, we have to flip them and take the else branch here */
547412e9a14SMatthew G. Knepley         if (faceType == DM_POLYTOPE_SEG_PRISM_TENSOR) {
548a74221b0SStefano Zampini           /* find the second vertex */
549412e9a14SMatthew G. Knepley           for (i2 = 0; i2 < faceSize; ++i2) if (face[1] == cone[i2]) break;
550412e9a14SMatthew G. Knepley           switch (faceSize) {
551a74221b0SStefano Zampini           case 2:
552a74221b0SStefano Zampini             ornt = i ? -2 : 0;
553a74221b0SStefano Zampini             break;
554a74221b0SStefano Zampini           case 4:
555a74221b0SStefano Zampini             ornt = tquad_map[i][i2];
556a74221b0SStefano Zampini             break;
557412e9a14SMatthew G. Knepley           default: SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unhandled face size %D for face %D in cell %D", faceSize, f, c);
558412e9a14SMatthew G. Knepley           }
559412e9a14SMatthew G. Knepley         } else {
560412e9a14SMatthew G. Knepley           /* Try forward comparison */
561412e9a14SMatthew G. Knepley           for (j = 0; j < faceSize; ++j) if (face[j] != cone[(i+j)%faceSize]) break;
562412e9a14SMatthew G. Knepley           if (j == faceSize) {
563412e9a14SMatthew G. Knepley             if ((faceSize == 2) && (i == 1)) ornt = -2;
564412e9a14SMatthew G. Knepley             else                             ornt = i;
565412e9a14SMatthew G. Knepley           } else {
566412e9a14SMatthew G. Knepley             /* Try backward comparison */
567412e9a14SMatthew G. Knepley             for (j = 0; j < faceSize; ++j) if (face[j] != cone[(i+faceSize-j)%faceSize]) break;
568412e9a14SMatthew G. Knepley             if (j == faceSize) {
569412e9a14SMatthew G. Knepley               if (i == 0) ornt = -faceSize;
570412e9a14SMatthew G. Knepley               else        ornt = -i;
571412e9a14SMatthew G. Knepley             } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not determine orientation of face %D in cell %D", f, c);
572a74221b0SStefano Zampini           }
573a74221b0SStefano Zampini         }
57499836e0eSStefano Zampini         ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr);
57599836e0eSStefano Zampini       }
57699836e0eSStefano Zampini     }
577412e9a14SMatthew G. Knepley     ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
57899836e0eSStefano Zampini   }
5799a5b13a2SMatthew G Knepley   ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr);
5809a5b13a2SMatthew G Knepley   ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr);
5819a5b13a2SMatthew G Knepley   ierr = DMPlexStratify(idm);CHKERRQ(ierr);
5829f074e33SMatthew G Knepley   PetscFunctionReturn(0);
5839f074e33SMatthew G Knepley }
5849f074e33SMatthew G Knepley 
585f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
586f80536cbSVaclav Hapla {
587f80536cbSVaclav Hapla   PetscInt            nleaves;
588f80536cbSVaclav Hapla   PetscInt            nranks;
589a0d42dbcSVaclav Hapla   const PetscMPIInt  *ranks=NULL;
590a0d42dbcSVaclav Hapla   const PetscInt     *roffset=NULL, *rmine=NULL, *rremote=NULL;
591f80536cbSVaclav Hapla   PetscInt            n, o, r;
592f80536cbSVaclav Hapla   PetscErrorCode      ierr;
593f80536cbSVaclav Hapla 
594f80536cbSVaclav Hapla   PetscFunctionBegin;
595dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote);CHKERRQ(ierr);
596f80536cbSVaclav Hapla   nleaves = roffset[nranks];
597f80536cbSVaclav Hapla   ierr = PetscMalloc2(nleaves, rmine1, nleaves, rremote1);CHKERRQ(ierr);
598f80536cbSVaclav Hapla   for (r=0; r<nranks; r++) {
599f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
600f80536cbSVaclav Hapla        - to unify order with the other side */
601f80536cbSVaclav Hapla     o = roffset[r];
602f80536cbSVaclav Hapla     n = roffset[r+1] - o;
603580bdb30SBarry Smith     ierr = PetscArraycpy(&(*rmine1)[o], &rmine[o], n);CHKERRQ(ierr);
604580bdb30SBarry Smith     ierr = PetscArraycpy(&(*rremote1)[o], &rremote[o], n);CHKERRQ(ierr);
605f80536cbSVaclav Hapla     ierr = PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]);CHKERRQ(ierr);
606f80536cbSVaclav Hapla   }
607f80536cbSVaclav Hapla   PetscFunctionReturn(0);
608f80536cbSVaclav Hapla }
609f80536cbSVaclav Hapla 
61027d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
6112e745bdaSMatthew G. Knepley {
61227d0e99aSVaclav Hapla   /* Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */
61327d0e99aSVaclav Hapla   PetscInt          masterCone[2];
614cae7fe92SVaclav Hapla   PetscInt          (*roots)[2], (*leaves)[2];
6158a650c75SVaclav Hapla   PetscMPIInt       (*rootsRanks)[2], (*leavesRanks)[2];
61627d0e99aSVaclav Hapla 
61727d0e99aSVaclav Hapla   PetscSF           sf=NULL;
618a0d42dbcSVaclav Hapla   const PetscInt    *locals=NULL;
619a0d42dbcSVaclav Hapla   const PetscSFNode *remotes=NULL;
6208a650c75SVaclav Hapla   PetscInt           nroots, nleaves, p, c;
621f80536cbSVaclav Hapla   PetscInt           nranks, n, o, r;
622a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks=NULL;
623a0d42dbcSVaclav Hapla   const PetscInt    *roffset=NULL;
624a0d42dbcSVaclav Hapla   PetscInt          *rmine1=NULL, *rremote1=NULL; /* rmine and rremote copies simultaneously sorted by rank and rremote */
625a0d42dbcSVaclav Hapla   const PetscInt    *cone=NULL;
626adeface4SVaclav Hapla   PetscInt           coneSize, ind0;
6272e745bdaSMatthew G. Knepley   MPI_Comm           comm;
62827d0e99aSVaclav Hapla   PetscMPIInt        rank,size;
6292e745bdaSMatthew G. Knepley   PetscInt           debug = 0;
6302e745bdaSMatthew G. Knepley   PetscErrorCode     ierr;
6312e745bdaSMatthew G. Knepley 
6322e745bdaSMatthew G. Knepley   PetscFunctionBegin;
633df6a9fadSVaclav Hapla   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
6342e745bdaSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes);CHKERRQ(ierr);
6353ede9f65SMatthew G. Knepley   if (nroots < 0) PetscFunctionReturn(0);
636f80536cbSVaclav Hapla   ierr = PetscSFSetUp(sf);CHKERRQ(ierr);
637dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL);CHKERRQ(ierr);
638dc21a0bfSVaclav Hapla   ierr = DMViewFromOptions(dm, NULL, "-before_fix_dm_view");CHKERRQ(ierr);
63976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr);}
640f80536cbSVaclav Hapla   ierr = SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1);CHKERRQ(ierr);
6418a650c75SVaclav Hapla   ierr = PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks);CHKERRQ(ierr);
6422e745bdaSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
6432e745bdaSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
64427d0e99aSVaclav Hapla   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
6459e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
6469e24d8a0SVaclav Hapla     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
6479e24d8a0SVaclav Hapla     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
64827d0e99aSVaclav Hapla     if (coneSize < 2) {
64927d0e99aSVaclav Hapla       for (c = 0; c < 2; c++) {
65027d0e99aSVaclav Hapla         roots[p][c] = -1;
65127d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
65227d0e99aSVaclav Hapla       }
65327d0e99aSVaclav Hapla       continue;
65427d0e99aSVaclav Hapla     }
6552e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
6568a650c75SVaclav Hapla     for (c = 0; c < 2; c++) {
6578a650c75SVaclav Hapla       ierr = PetscFindInt(cone[c], nleaves, locals, &ind0);CHKERRQ(ierr);
6588a650c75SVaclav Hapla       if (ind0 < 0) {
6598a650c75SVaclav Hapla         roots[p][c] = cone[c];
6608a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
661c8148b97SVaclav Hapla       } else {
6628a650c75SVaclav Hapla         roots[p][c] = remotes[ind0].index;
6638a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
6648a650c75SVaclav Hapla       }
6652e745bdaSMatthew G. Knepley     }
6662e745bdaSMatthew G. Knepley   }
6679e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
6688ccb905dSVaclav Hapla     for (c = 0; c < 2; c++) {
6698ccb905dSVaclav Hapla       leaves[p][c] = -2;
6708ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
6718ccb905dSVaclav Hapla     }
672c8148b97SVaclav Hapla   }
6732e745bdaSMatthew G. Knepley   ierr = PetscSFBcastBegin(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr);
6748a650c75SVaclav Hapla   ierr = PetscSFBcastBegin(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr);
6752e745bdaSMatthew G. Knepley   ierr = PetscSFBcastEnd(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr);
6768a650c75SVaclav Hapla   ierr = PetscSFBcastEnd(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr);
677c8148b97SVaclav Hapla   if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
67827d0e99aSVaclav Hapla   if (debug && rank == 0) {ierr = PetscSynchronizedPrintf(comm, "Referenced roots\n");CHKERRQ(ierr);}
6799e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
6809e24d8a0SVaclav Hapla     if (leaves[p][0] < 0) continue;
6819e24d8a0SVaclav Hapla     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
6829e24d8a0SVaclav Hapla     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
68327d0e99aSVaclav Hapla     if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  %4D: cone=[%4D %4D] roots=[(%d,%4D) (%d,%4D)] leaves=[(%d,%4D) (%d,%4D)]", rank, p, cone[0], cone[1], rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1]);CHKERRQ(ierr);}
68482f5c0aeSVaclav Hapla     if ((leaves[p][0] != roots[p][0]) || (leaves[p][1] != roots[p][1]) || (leavesRanks[p][0] != rootsRanks[p][0]) || (leavesRanks[p][1] != rootsRanks[p][1])) {
68527d0e99aSVaclav Hapla       /* Translate these two leaves to my cone points; masterCone means desired order p's cone points */
686f80536cbSVaclav Hapla       for (c = 0; c < 2; c++) {
68727d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
68827d0e99aSVaclav Hapla           /* A local leave is just taken as it is */
68927d0e99aSVaclav Hapla           masterCone[c] = leaves[p][c];
69027d0e99aSVaclav Hapla           continue;
69127d0e99aSVaclav Hapla         }
692f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
693f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
694f80536cbSVaclav Hapla         ierr = PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r);CHKERRQ(ierr);
69527d0e99aSVaclav Hapla         if (PetscUnlikely(r < 0)) SETERRQ7(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leave (%d,%D): leave rank not found among remote ranks",p,c,cone[c],rootsRanks[p][c],roots[p][c],leavesRanks[p][c],leaves[p][c]);
69627d0e99aSVaclav Hapla         if (PetscUnlikely(ranks[r] < 0 || ranks[r] >= size)) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%D c=%D commsize=%d: ranks[%D] = %d makes no sense",p,c,size,r,ranks[r]);
697f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
698f80536cbSVaclav Hapla         o = roffset[r];
699f80536cbSVaclav Hapla         n = roffset[r+1] - o;
700f80536cbSVaclav Hapla         ierr = PetscFindInt(leaves[p][c], n, &rremote1[o], &ind0);CHKERRQ(ierr);
70127d0e99aSVaclav Hapla         if (PetscUnlikely(ind0 < 0)) SETERRQ7(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]);
702f80536cbSVaclav Hapla         /* Get the corresponding local point */
703f80536cbSVaclav Hapla         masterCone[c] = rmine1[o+ind0];CHKERRQ(ierr);
704f80536cbSVaclav Hapla       }
70527d0e99aSVaclav Hapla       if (debug) {ierr = PetscSynchronizedPrintf(comm, " masterCone=[%4D %4D]\n", masterCone[0], masterCone[1]);CHKERRQ(ierr);}
70627d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
707f80536cbSVaclav Hapla       /* Vaclav's note: Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */
708f80536cbSVaclav Hapla       ierr = DMPlexOrientCell(dm, p, 2, masterCone);CHKERRQ(ierr);
70927d0e99aSVaclav Hapla     } else if (debug) {ierr = PetscSynchronizedPrintf(comm, " ==\n");CHKERRQ(ierr);}
71023aaf07bSVaclav Hapla   }
71127d0e99aSVaclav Hapla   if (debug) {
71227d0e99aSVaclav Hapla     ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
71327d0e99aSVaclav Hapla     ierr = MPI_Barrier(comm);CHKERRQ(ierr);
7142e745bdaSMatthew G. Knepley   }
715adeface4SVaclav Hapla   ierr = DMViewFromOptions(dm, NULL, "-after_fix_dm_view");CHKERRQ(ierr);
7168a650c75SVaclav Hapla   ierr = PetscFree4(roots, leaves, rootsRanks, leavesRanks);CHKERRQ(ierr);
7177c7bb832SVaclav Hapla   ierr = PetscFree2(rmine1, rremote1);CHKERRQ(ierr);
7182e745bdaSMatthew G. Knepley   PetscFunctionReturn(0);
7192e745bdaSMatthew G. Knepley }
7202e745bdaSMatthew G. Knepley 
7212e72742cSMatthew 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[])
7227bffde78SMichael Lange {
7232e72742cSMatthew G. Knepley   PetscInt       idx;
7242e72742cSMatthew G. Knepley   PetscMPIInt    rank;
7252e72742cSMatthew G. Knepley   PetscBool      flg;
7267bffde78SMichael Lange   PetscErrorCode ierr;
7277bffde78SMichael Lange 
7287bffde78SMichael Lange   PetscFunctionBegin;
7292e72742cSMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr);
7302e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
7312e72742cSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
7322e72742cSMatthew G. Knepley   ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr);
7332e72742cSMatthew 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);}
7342e72742cSMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
7352e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7362e72742cSMatthew G. Knepley }
7372e72742cSMatthew G. Knepley 
7382e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
7392e72742cSMatthew G. Knepley {
7402e72742cSMatthew G. Knepley   PetscInt       idx;
7412e72742cSMatthew G. Knepley   PetscMPIInt    rank;
7422e72742cSMatthew G. Knepley   PetscBool      flg;
7432e72742cSMatthew G. Knepley   PetscErrorCode ierr;
7442e72742cSMatthew G. Knepley 
7452e72742cSMatthew G. Knepley   PetscFunctionBegin;
7462e72742cSMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr);
7472e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
7482e72742cSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
7492e72742cSMatthew G. Knepley   ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr);
7502e72742cSMatthew G. Knepley   if (idxname) {
7512e72742cSMatthew 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);}
7522e72742cSMatthew G. Knepley   } else {
7532e72742cSMatthew 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);}
7542e72742cSMatthew G. Knepley   }
7552e72742cSMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
7562e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7572e72742cSMatthew G. Knepley }
7582e72742cSMatthew G. Knepley 
7593be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint)
7602e72742cSMatthew G. Knepley {
7613be36e83SMatthew G. Knepley   PetscSF         sf;
7623be36e83SMatthew G. Knepley   const PetscInt *locals;
7633be36e83SMatthew G. Knepley   PetscMPIInt     rank;
7642e72742cSMatthew G. Knepley   PetscErrorCode  ierr;
7652e72742cSMatthew G. Knepley 
7662e72742cSMatthew G. Knepley   PetscFunctionBegin;
7673be36e83SMatthew G. Knepley   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
7683be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
7693be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, NULL, &locals, NULL);CHKERRQ(ierr);
7702e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
7712e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
7722e72742cSMatthew G. Knepley   } else {
7732e72742cSMatthew G. Knepley     PetscHashIJKey key;
7743be36e83SMatthew G. Knepley     PetscInt       l;
7752e72742cSMatthew G. Knepley 
7762e72742cSMatthew G. Knepley     key.i = remotePoint.index;
7772e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
7783be36e83SMatthew G. Knepley     ierr = PetscHMapIJGet(remotehash, key, &l);CHKERRQ(ierr);
7793be36e83SMatthew G. Knepley     if (l >= 0) {
7803be36e83SMatthew G. Knepley       *localPoint = locals[l];
7812e72742cSMatthew G. Knepley     } else PetscFunctionReturn(1);
7822e72742cSMatthew G. Knepley   }
7832e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7842e72742cSMatthew G. Knepley }
7852e72742cSMatthew G. Knepley 
7863be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint)
7873be36e83SMatthew G. Knepley {
7883be36e83SMatthew G. Knepley   PetscSF            sf;
7893be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
7903be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
7913be36e83SMatthew G. Knepley   PetscInt           Nl, l;
7923be36e83SMatthew G. Knepley   PetscMPIInt        rank;
7933be36e83SMatthew G. Knepley   PetscErrorCode     ierr;
7943be36e83SMatthew G. Knepley 
7953be36e83SMatthew G. Knepley   PetscFunctionBegin;
7963be36e83SMatthew G. Knepley   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
7973be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
7983be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes);CHKERRQ(ierr);
7993be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
8003be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr);
8013be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr);
8023be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
8033be36e83SMatthew G. Knepley   ierr = PetscFindInt(localPoint, Nl, locals, &l);CHKERRQ(ierr);
8043be36e83SMatthew G. Knepley   if (l < 0) PetscFunctionReturn(1);
8053be36e83SMatthew G. Knepley   *remotePoint = remotes[l];
8063be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8073be36e83SMatthew G. Knepley   owned:
8083be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
8093be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
8103be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8113be36e83SMatthew G. Knepley }
8123be36e83SMatthew G. Knepley 
8133be36e83SMatthew G. Knepley 
8143be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
8153be36e83SMatthew G. Knepley {
8163be36e83SMatthew G. Knepley   PetscSF         sf;
8173be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
8183be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
8193be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
8203be36e83SMatthew G. Knepley 
8213be36e83SMatthew G. Knepley   PetscFunctionBegin;
8223be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
8233be36e83SMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
8243be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL);CHKERRQ(ierr);
8253be36e83SMatthew G. Knepley   if (Nl < 0) PetscFunctionReturn(0);
8263be36e83SMatthew G. Knepley   ierr = PetscFindInt(p, Nl, locals, &idx);CHKERRQ(ierr);
8273be36e83SMatthew G. Knepley   if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);}
8283be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr);
8293be36e83SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr);
8303be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
8313be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8323be36e83SMatthew G. Knepley }
8333be36e83SMatthew G. Knepley 
8343be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
8353be36e83SMatthew G. Knepley {
8363be36e83SMatthew G. Knepley   const PetscInt *cone;
8373be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
8383be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
8393be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
8403be36e83SMatthew G. Knepley 
8413be36e83SMatthew G. Knepley   PetscFunctionBegin;
8423be36e83SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
8433be36e83SMatthew G. Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
8443be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
8453be36e83SMatthew G. Knepley     PetscBool pointShared;
8463be36e83SMatthew G. Knepley 
8473be36e83SMatthew G. Knepley     ierr = DMPlexPointIsShared(dm, cone[c], &pointShared);CHKERRQ(ierr);
8483be36e83SMatthew G. Knepley     cShared = (PetscBool) (cShared && pointShared);
8493be36e83SMatthew G. Knepley   }
8503be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
8513be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8523be36e83SMatthew G. Knepley }
8533be36e83SMatthew G. Knepley 
8543be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
8553be36e83SMatthew G. Knepley {
8563be36e83SMatthew G. Knepley   const PetscInt *cone;
8573be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
8583be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
8593be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
8603be36e83SMatthew G. Knepley 
8613be36e83SMatthew G. Knepley   PetscFunctionBegin;
8623be36e83SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
8633be36e83SMatthew G. Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
8643be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
8653be36e83SMatthew G. Knepley     PetscSFNode rcp;
8663be36e83SMatthew G. Knepley 
8673be36e83SMatthew G. Knepley     ierr = DMPlexMapToGlobalPoint(dm, cone[c], &rcp);
8683be36e83SMatthew G. Knepley     if (ierr) {
8693be36e83SMatthew G. Knepley       cmin = missing;
8703be36e83SMatthew G. Knepley     } else {
8713be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
8723be36e83SMatthew G. Knepley     }
8733be36e83SMatthew G. Knepley   }
8743be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
8753be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8763be36e83SMatthew G. Knepley }
8773be36e83SMatthew G. Knepley 
8783be36e83SMatthew G. Knepley /*
8793be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
8803be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
8813be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
8823be36e83SMatthew G. Knepley */
8833be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
8843be36e83SMatthew G. Knepley {
8853be36e83SMatthew G. Knepley   MPI_Comm        comm;
8863be36e83SMatthew G. Knepley   const PetscInt *support;
887cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
8883be36e83SMatthew G. Knepley   PetscMPIInt     rank;
8893be36e83SMatthew G. Knepley   PetscErrorCode  ierr;
8903be36e83SMatthew G. Knepley 
8913be36e83SMatthew G. Knepley   PetscFunctionBegin;
8923be36e83SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
8933be36e83SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
894cf4dc471SVaclav Hapla   ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr);
895cf4dc471SVaclav Hapla   ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
896cf4dc471SVaclav Hapla   ierr = DMPlexGetPointHeight(dm, p, &height);CHKERRQ(ierr);
897cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight+1) {
898cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
899cf4dc471SVaclav 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);}
900cf4dc471SVaclav Hapla     PetscFunctionReturn(0);
901cf4dc471SVaclav Hapla   }
9023be36e83SMatthew G. Knepley   ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
9033be36e83SMatthew G. Knepley   ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
9043be36e83SMatthew G. Knepley   if (candidates) {ierr = PetscSectionGetOffset(candidateSection, p, &off);CHKERRQ(ierr);}
9053be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
9063be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
9073be36e83SMatthew G. Knepley     const PetscInt *cone;
9083be36e83SMatthew G. Knepley     PetscSFNode     cpmin={-1,-1}, rp={-1,-1};
9093be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
9103be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
9113be36e83SMatthew G. Knepley     PetscHashIJKey  key;
9123be36e83SMatthew G. Knepley 
9133be36e83SMatthew G. Knepley     /* Only add point once */
9143be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Support face %D\n", rank, face);CHKERRQ(ierr);}
9153be36e83SMatthew G. Knepley     key.i = p;
9163be36e83SMatthew G. Knepley     key.j = face;
9173be36e83SMatthew G. Knepley     ierr = PetscHMapIJGet(faceHash, key, &f);CHKERRQ(ierr);
9183be36e83SMatthew G. Knepley     if (f >= 0) continue;
9193be36e83SMatthew G. Knepley     ierr = DMPlexConeIsShared(dm, face, &isShared);CHKERRQ(ierr);
9203be36e83SMatthew G. Knepley     ierr = DMPlexGetConeMinimum(dm, face, &cpmin);CHKERRQ(ierr);
9213be36e83SMatthew G. Knepley     ierr = DMPlexMapToGlobalPoint(dm, p, &rp);CHKERRQ(ierr);
9223be36e83SMatthew G. Knepley     if (debug) {
9233be36e83SMatthew G. Knepley       ierr = PetscSynchronizedPrintf(comm, "[%d]      Face point %D is shared: %d\n", rank, face, (int) isShared);CHKERRQ(ierr);
9243be36e83SMatthew 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);
9253be36e83SMatthew G. Knepley     }
9263be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
9273be36e83SMatthew G. Knepley       ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr);
9283be36e83SMatthew G. Knepley       if (candidates) {
9293be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %D at idx %D\n[%d]     ", rank, face, idx, rank);CHKERRQ(ierr);}
9303be36e83SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr);
9313be36e83SMatthew G. Knepley         ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr);
9323be36e83SMatthew G. Knepley         candidates[off+idx].rank    = -1;
9333be36e83SMatthew G. Knepley         candidates[off+idx++].index = coneSize-1;
9343be36e83SMatthew G. Knepley         candidates[off+idx].rank    = rank;
9353be36e83SMatthew G. Knepley         candidates[off+idx++].index = face;
9363be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
9373be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
9383be36e83SMatthew G. Knepley 
9393be36e83SMatthew G. Knepley           if (cp == p) continue;
9403be36e83SMatthew G. Knepley           ierr = DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx]);CHKERRQ(ierr);
9413be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index);CHKERRQ(ierr);}
9423be36e83SMatthew G. Knepley           ++idx;
9433be36e83SMatthew G. Knepley         }
9443be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "\n");CHKERRQ(ierr);}
9453be36e83SMatthew G. Knepley       } else {
9463be36e83SMatthew G. Knepley         /* Add cone size to section */
9473be36e83SMatthew G. Knepley         if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %D\n", rank, face);CHKERRQ(ierr);}
9483be36e83SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr);
9493be36e83SMatthew G. Knepley         ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr);
9503be36e83SMatthew G. Knepley         ierr = PetscSectionAddDof(candidateSection, p, coneSize+1);CHKERRQ(ierr);
9513be36e83SMatthew G. Knepley       }
9523be36e83SMatthew G. Knepley     }
9533be36e83SMatthew G. Knepley   }
9543be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9553be36e83SMatthew G. Knepley }
9563be36e83SMatthew G. Knepley 
9572e72742cSMatthew G. Knepley /*@
9582e72742cSMatthew G. Knepley   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation
9592e72742cSMatthew G. Knepley 
960d083f849SBarry Smith   Collective on dm
9612e72742cSMatthew G. Knepley 
9622e72742cSMatthew G. Knepley   Input Parameters:
9632e72742cSMatthew G. Knepley + dm      - The interpolated DM
9642e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points
9652e72742cSMatthew G. Knepley 
9662e72742cSMatthew G. Knepley   Output Parameter:
9672e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points
9682e72742cSMatthew G. Knepley 
969f0cfc026SVaclav Hapla   Level: developer
9702e72742cSMatthew G. Knepley 
9712e72742cSMatthew 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
9722e72742cSMatthew G. Knepley 
9732e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate()
9742e72742cSMatthew G. Knepley @*/
975e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
9762e72742cSMatthew G. Knepley {
9773be36e83SMatthew G. Knepley   MPI_Comm           comm;
9783be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
9793be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
9803be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
9813be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
9822e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
9832e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
9843be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
9853be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
9863be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
987f0cfc026SVaclav Hapla   PetscMPIInt        rank;
9882e72742cSMatthew G. Knepley   PetscErrorCode     ierr;
9892e72742cSMatthew G. Knepley 
9902e72742cSMatthew G. Knepley   PetscFunctionBegin;
991f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9923be36e83SMatthew G. Knepley   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 3);
993f0cfc026SVaclav Hapla   ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr);
994f0cfc026SVaclav Hapla   if (!flg) PetscFunctionReturn(0);
9953be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
9963be36e83SMatthew G. Knepley   ierr = DMSetPointSF(dm, pointSF);CHKERRQ(ierr);
9973be36e83SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
9983be36e83SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
9993be36e83SMatthew G. Knepley   ierr = DMPlexGetOverlap(dm, &ov);CHKERRQ(ierr);
10003be36e83SMatthew G. Knepley   if (ov) SETERRQ(comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
10013be36e83SMatthew G. Knepley   ierr = PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug);CHKERRQ(ierr);
10022e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view");CHKERRQ(ierr);
10032e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view");CHKERRQ(ierr);
100425afeb17SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr);
10053be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
10063be36e83SMatthew G. Knepley   ierr = PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints);CHKERRQ(ierr);
10073be36e83SMatthew G. Knepley   if (Nr < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
10083be36e83SMatthew G. Knepley   ierr = PetscHMapIJCreate(&remoteHash);CHKERRQ(ierr);
10093be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
10103be36e83SMatthew G. Knepley     PetscHashIJKey key;
10112e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
10122e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
10133be36e83SMatthew G. Knepley     ierr = PetscHMapIJSet(remoteHash, key, l);CHKERRQ(ierr);
10147bffde78SMichael Lange   }
101566aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
10162e72742cSMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr);
10172e72742cSMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr);
10183be36e83SMatthew G. Knepley   ierr = IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree);CHKERRQ(ierr);
10193be36e83SMatthew G. Knepley   /*
10203be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
10213be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
10223be36e83SMatthew G. Knepley   \begin{itemize}
10233be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
10243be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
10253be36e83SMatthew G. Knepley   \end{itemize}
10263be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
10273be36e83SMatthew 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
10283be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
10293be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
10303be36e83SMatthew G. Knepley   */
10313be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
10323be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
10333be36e83SMatthew G. Knepley        The array holds candidate shared faces, each face is refered to by the leaf point */
10343be36e83SMatthew G. Knepley   ierr = PetscSectionCreate(comm, &candidateSection);CHKERRQ(ierr);
10353be36e83SMatthew G. Knepley   ierr = PetscSectionSetChart(candidateSection, 0, Nr);CHKERRQ(ierr);
10367bffde78SMichael Lange   {
10373be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
10382e72742cSMatthew G. Knepley 
10393be36e83SMatthew G. Knepley     ierr = PetscHMapIJCreate(&faceHash);CHKERRQ(ierr);
10403be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
10413be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
10422e72742cSMatthew G. Knepley 
10433be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %D\n", rank, p);CHKERRQ(ierr);}
10443be36e83SMatthew G. Knepley       ierr = DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug);CHKERRQ(ierr);
10452e72742cSMatthew G. Knepley     }
10463be36e83SMatthew G. Knepley     ierr = PetscHMapIJClear(faceHash);CHKERRQ(ierr);
10477bffde78SMichael Lange     ierr = PetscSectionSetUp(candidateSection);CHKERRQ(ierr);
10487bffde78SMichael Lange     ierr = PetscSectionGetStorageSize(candidateSection, &candidatesSize);CHKERRQ(ierr);
10497bffde78SMichael Lange     ierr = PetscMalloc1(candidatesSize, &candidates);CHKERRQ(ierr);
10503be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
10513be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
10522e72742cSMatthew G. Knepley 
10533be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %D\n", rank, p);CHKERRQ(ierr);}
10543be36e83SMatthew G. Knepley       ierr = DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug);CHKERRQ(ierr);
10552e72742cSMatthew G. Knepley     }
10563be36e83SMatthew G. Knepley     ierr = PetscHMapIJDestroy(&faceHash);CHKERRQ(ierr);
10573be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
10587bffde78SMichael Lange   }
10593be36e83SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) candidateSection, "Candidate Section");CHKERRQ(ierr);
10602e72742cSMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view");CHKERRQ(ierr);
10613be36e83SMatthew G. Knepley   ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates);CHKERRQ(ierr);
10623be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
10632e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
10647bffde78SMichael Lange   {
10657bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
10667bffde78SMichael Lange     PetscInt *remoteOffsets;
10672e72742cSMatthew G. Knepley 
10687bffde78SMichael Lange     ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr);
10697bffde78SMichael Lange     ierr = PetscSFCreateInverseSF(sfMulti, &sfInverse);CHKERRQ(ierr);
10703be36e83SMatthew G. Knepley     ierr = PetscSectionCreate(comm, &candidateRemoteSection);CHKERRQ(ierr);
10713be36e83SMatthew G. Knepley     ierr = PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection);CHKERRQ(ierr);
10723be36e83SMatthew G. Knepley     ierr = PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates);CHKERRQ(ierr);
10733be36e83SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize);CHKERRQ(ierr);
10747bffde78SMichael Lange     ierr = PetscMalloc1(candidatesRemoteSize, &candidatesRemote);CHKERRQ(ierr);
10757bffde78SMichael Lange     ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr);
10767bffde78SMichael Lange     ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr);
10777bffde78SMichael Lange     ierr = PetscSFDestroy(&sfInverse);CHKERRQ(ierr);
10787bffde78SMichael Lange     ierr = PetscSFDestroy(&sfCandidates);CHKERRQ(ierr);
10797bffde78SMichael Lange     ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
10802e72742cSMatthew G. Knepley 
10813be36e83SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section");CHKERRQ(ierr);
10823be36e83SMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view");CHKERRQ(ierr);
10833be36e83SMatthew G. Knepley     ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote);CHKERRQ(ierr);
10847bffde78SMichael Lange   }
10853be36e83SMatthew 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 */
10867bffde78SMichael Lange   {
10873be36e83SMatthew G. Knepley     PetscHashIJKLRemote faceTable;
10883be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
10893be36e83SMatthew G. Knepley 
10903be36e83SMatthew G. Knepley     ierr = PetscHashIJKLRemoteCreate(&faceTable);CHKERRQ(ierr);
10912e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
10923be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
10932e72742cSMatthew G. Knepley       PetscInt deg;
10943be36e83SMatthew G. Knepley 
10952e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
10962e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
10972e72742cSMatthew G. Knepley 
10983be36e83SMatthew G. Knepley         ierr = PetscSectionGetDof(candidateRemoteSection, idx, &dof);CHKERRQ(ierr);
10993be36e83SMatthew G. Knepley         ierr = PetscSectionGetOffset(candidateRemoteSection, idx, &offset);CHKERRQ(ierr);
11003be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
11012e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11023be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
11033be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
11043be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx+1];
11053be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
11063be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
11073be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
11082e72742cSMatthew G. Knepley           const PetscInt        *join  = NULL;
11093be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
11103be36e83SMatthew G. Knepley           PetscHashIter          iter;
11113be36e83SMatthew G. Knepley           PetscBool              missing;
11122e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
11132e72742cSMatthew G. Knepley 
111466e92ce5SVaclav 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);}
111566e92ce5SVaclav Hapla           if (Np > 4) SETERRQ6(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);
11163be36e83SMatthew G. Knepley           fcp0.rank  = rank;
11173be36e83SMatthew G. Knepley           fcp0.index = r;
11183be36e83SMatthew G. Knepley           d += Np;
11193be36e83SMatthew G. Knepley           /* Put remote face in hash table */
11203be36e83SMatthew G. Knepley           key.i = fcp0;
11213be36e83SMatthew G. Knepley           key.j = fcone[0];
11223be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
11233be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
11243be36e83SMatthew G. Knepley           ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr);
11253be36e83SMatthew G. Knepley           ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
11263be36e83SMatthew G. Knepley           if (missing) {
11273be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Setting remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);}
11283be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr);
11293be36e83SMatthew G. Knepley           } else {
11303be36e83SMatthew G. Knepley             PetscSFNode oface;
11313be36e83SMatthew G. Knepley 
11323be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr);
11333be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
11343be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);}
11353be36e83SMatthew G. Knepley               ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr);
11363be36e83SMatthew G. Knepley             }
11373be36e83SMatthew G. Knepley           }
11383be36e83SMatthew G. Knepley           /* Check for local face */
11392e72742cSMatthew G. Knepley           points[0] = r;
11403be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
11413be36e83SMatthew G. Knepley             ierr = DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p]);
11423be36e83SMatthew G. Knepley             if (ierr) break; /* We got a point not in our overlap */
11433be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Checking local candidate %D\n", rank, points[p]);CHKERRQ(ierr);}
11447bffde78SMichael Lange           }
11452e72742cSMatthew G. Knepley           if (ierr) continue;
11463be36e83SMatthew G. Knepley           ierr = DMPlexGetJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr);
11477bffde78SMichael Lange           if (joinSize == 1) {
11483be36e83SMatthew G. Knepley             PetscSFNode lface;
11493be36e83SMatthew G. Knepley             PetscSFNode oface;
11503be36e83SMatthew G. Knepley 
11513be36e83SMatthew G. Knepley             /* Always replace with local face */
11523be36e83SMatthew G. Knepley             lface.rank  = rank;
11533be36e83SMatthew G. Knepley             lface.index = join[0];
11543be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr);
11553be36e83SMatthew 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);}
11563be36e83SMatthew G. Knepley             ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, lface);CHKERRQ(ierr);
11577bffde78SMichael Lange           }
11583be36e83SMatthew G. Knepley           ierr = DMPlexRestoreJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr);
11593be36e83SMatthew G. Knepley         }
11603be36e83SMatthew G. Knepley       }
11613be36e83SMatthew G. Knepley       /* Put back faces for this root */
11623be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
11633be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
11643be36e83SMatthew G. Knepley 
11653be36e83SMatthew G. Knepley         ierr = PetscSectionGetDof(candidateRemoteSection, idx2, &dof);CHKERRQ(ierr);
11663be36e83SMatthew G. Knepley         ierr = PetscSectionGetOffset(candidateRemoteSection, idx2, &offset);CHKERRQ(ierr);
11673be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
11683be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11693be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
11703be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
11713be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
11723be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
11733be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
11743be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
11753be36e83SMatthew G. Knepley           PetscHashIter          iter;
11763be36e83SMatthew G. Knepley           PetscBool              missing;
11773be36e83SMatthew G. Knepley 
11783be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Entering face at (%D, %D)\n", rank, r, idx);CHKERRQ(ierr);}
11793be36e83SMatthew G. Knepley           if (Np > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np);
11803be36e83SMatthew G. Knepley           fcp0.rank  = rank;
11813be36e83SMatthew G. Knepley           fcp0.index = r;
11823be36e83SMatthew G. Knepley           d += Np;
11833be36e83SMatthew G. Knepley           /* Find remote face in hash table */
11843be36e83SMatthew G. Knepley           key.i = fcp0;
11853be36e83SMatthew G. Knepley           key.j = fcone[0];
11863be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
11873be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
11883be36e83SMatthew G. Knepley           ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr);
11893be36e83SMatthew 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);}
11903be36e83SMatthew G. Knepley           ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr);
11912479783cSJose E. Roman           if (missing) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an associated face", r, idx2);
11923be36e83SMatthew G. Knepley           else        {ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]);CHKERRQ(ierr);}
11937bffde78SMichael Lange         }
11947bffde78SMichael Lange       }
11957bffde78SMichael Lange     }
11962e72742cSMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL);CHKERRQ(ierr);}
11973be36e83SMatthew G. Knepley     ierr = PetscHashIJKLRemoteDestroy(&faceTable);CHKERRQ(ierr);
11987bffde78SMichael Lange   }
11993be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
12007bffde78SMichael Lange   {
12017bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
12027bffde78SMichael Lange     PetscSFNode *remotePointsNew;
12032e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
12043be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
12052e72742cSMatthew G. Knepley 
12063be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
12077bffde78SMichael Lange     ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr);
12083be36e83SMatthew G. Knepley     ierr = PetscSectionCreate(comm, &claimSection);CHKERRQ(ierr);
12093be36e83SMatthew G. Knepley     ierr = PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection);CHKERRQ(ierr);
12103be36e83SMatthew G. Knepley     ierr = PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims);CHKERRQ(ierr);
12112e72742cSMatthew G. Knepley     ierr = PetscSectionGetStorageSize(claimSection, &claimsSize);CHKERRQ(ierr);
12122e72742cSMatthew G. Knepley     ierr = PetscMalloc1(claimsSize, &claims);CHKERRQ(ierr);
12133be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
12147bffde78SMichael Lange     ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr);
12157bffde78SMichael Lange     ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr);
12167bffde78SMichael Lange     ierr = PetscSFDestroy(&sfClaims);CHKERRQ(ierr);
12177bffde78SMichael Lange     ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
12183be36e83SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) claimSection, "Claim Section");CHKERRQ(ierr);
12192e72742cSMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view");CHKERRQ(ierr);
12203be36e83SMatthew G. Knepley     ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims);CHKERRQ(ierr);
12213be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
12223be36e83SMatthew 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 */
1223e8f14785SLisandro Dalcin     ierr = PetscHMapICreate(&claimshash);CHKERRQ(ierr);
12243be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
12253be36e83SMatthew G. Knepley       PetscInt dof, off, d;
12262e72742cSMatthew G. Knepley 
12273be36e83SMatthew G. Knepley       if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %D\n", rank, r);CHKERRQ(ierr);}
12283be36e83SMatthew G. Knepley       ierr = PetscSectionGetDof(candidateSection, r, &dof);CHKERRQ(ierr);
12293be36e83SMatthew G. Knepley       ierr = PetscSectionGetOffset(candidateSection, r, &off);CHKERRQ(ierr);
12302e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
12313be36e83SMatthew G. Knepley         if (claims[off+d].rank >= 0) {
12323be36e83SMatthew G. Knepley           const PetscInt  faceInd = off+d;
12333be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off+d].index;
12342e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
12352e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
12362e72742cSMatthew G. Knepley 
12373be36e83SMatthew 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);}
12383be36e83SMatthew G. Knepley           points[0] = r;
12393be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]      point %D\n", rank, points[0]);CHKERRQ(ierr);}
12403be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
12413be36e83SMatthew G. Knepley             ierr = DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1]);CHKERRQ(ierr);
12423be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]      point %D\n", rank, points[c+1]);CHKERRQ(ierr);}
12432e72742cSMatthew G. Knepley           }
12443be36e83SMatthew G. Knepley           ierr = DMPlexGetJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr);
12452e72742cSMatthew G. Knepley           if (joinSize == 1) {
12463be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
12473be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %D for non-remote partner\n", rank, join[0]);CHKERRQ(ierr);}
12483be36e83SMatthew G. Knepley             } else {
12493be36e83SMatthew G. Knepley               if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Found local face %D\n", rank, join[0]);CHKERRQ(ierr);}
12502e72742cSMatthew G. Knepley               ierr = PetscHMapISet(claimshash, join[0], faceInd);CHKERRQ(ierr);
12512e72742cSMatthew G. Knepley             }
12523be36e83SMatthew G. Knepley           } else {
12533be36e83SMatthew G. Knepley             if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank);CHKERRQ(ierr);}
12543be36e83SMatthew G. Knepley           }
12553be36e83SMatthew G. Knepley           ierr = DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr);
12563be36e83SMatthew G. Knepley         } else {
12573be36e83SMatthew G. Knepley           if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d]    No claim for point %D\n", rank, r);CHKERRQ(ierr);}
12583be36e83SMatthew G. Knepley           d += claims[off+d].index+1;
12597bffde78SMichael Lange         }
12607bffde78SMichael Lange       }
12613be36e83SMatthew G. Knepley     }
12623be36e83SMatthew G. Knepley     if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
12633be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
12643be36e83SMatthew G. Knepley     ierr = PetscHMapIGetSize(claimshash, &NlNew);CHKERRQ(ierr);
12657bffde78SMichael Lange     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
12663be36e83SMatthew G. Knepley     ierr = PetscMalloc1(Nl + NlNew, &localPointsNew);CHKERRQ(ierr);
12673be36e83SMatthew G. Knepley     ierr = PetscMalloc1(Nl + NlNew, &remotePointsNew);CHKERRQ(ierr);
12683be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12693be36e83SMatthew G. Knepley       localPointsNew[l] = localPoints[l];
12703be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
12713be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
12727bffde78SMichael Lange     }
12733be36e83SMatthew G. Knepley     p = Nl;
1274e8f14785SLisandro Dalcin     ierr = PetscHMapIGetKeys(claimshash, &p, localPointsNew);CHKERRQ(ierr);
12753be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
12763be36e83SMatthew G. Knepley     ierr = PetscSortInt(NlNew, &localPointsNew[Nl]);CHKERRQ(ierr);
12773be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
12783be36e83SMatthew G. Knepley       PetscInt off;
12793be36e83SMatthew G. Knepley       ierr = PetscHMapIGet(claimshash, localPointsNew[p], &off);CHKERRQ(ierr);
12803be36e83SMatthew G. Knepley       if (claims[off].rank < 0 || claims[off].index < 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %D, (%D, %D)", localPointsNew[p], claims[off].rank, claims[off].index);
12813be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
12827bffde78SMichael Lange     }
12833be36e83SMatthew G. Knepley     ierr = PetscSFCreate(comm, &sfPointNew);CHKERRQ(ierr);
12843be36e83SMatthew G. Knepley     ierr = PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
12853be36e83SMatthew G. Knepley     ierr = PetscSFSetUp(sfPointNew);CHKERRQ(ierr);
12867bffde78SMichael Lange     ierr = DMSetPointSF(dm, sfPointNew);CHKERRQ(ierr);
12873be36e83SMatthew G. Knepley     ierr = PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view");CHKERRQ(ierr);
12887bffde78SMichael Lange     ierr = PetscSFDestroy(&sfPointNew);CHKERRQ(ierr);
1289e8f14785SLisandro Dalcin     ierr = PetscHMapIDestroy(&claimshash);CHKERRQ(ierr);
12907bffde78SMichael Lange   }
12913be36e83SMatthew G. Knepley   ierr = PetscHMapIJDestroy(&remoteHash);CHKERRQ(ierr);
12927bffde78SMichael Lange   ierr = PetscSectionDestroy(&candidateSection);CHKERRQ(ierr);
12933be36e83SMatthew G. Knepley   ierr = PetscSectionDestroy(&candidateRemoteSection);CHKERRQ(ierr);
12947bffde78SMichael Lange   ierr = PetscSectionDestroy(&claimSection);CHKERRQ(ierr);
12957bffde78SMichael Lange   ierr = PetscFree(candidates);CHKERRQ(ierr);
12967bffde78SMichael Lange   ierr = PetscFree(candidatesRemote);CHKERRQ(ierr);
12977bffde78SMichael Lange   ierr = PetscFree(claims);CHKERRQ(ierr);
129825afeb17SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr);
12997bffde78SMichael Lange   PetscFunctionReturn(0);
13007bffde78SMichael Lange }
13017bffde78SMichael Lange 
1302248eb259SVaclav Hapla /*@
130380330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
130480330477SMatthew G. Knepley 
1305d083f849SBarry Smith   Collective on dm
130680330477SMatthew G. Knepley 
1307e56d480eSMatthew G. Knepley   Input Parameters:
1308e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices
130910a67516SMatthew G. Knepley - dmInt - The interpolated DM
131080330477SMatthew G. Knepley 
131180330477SMatthew G. Knepley   Output Parameter:
13124e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object
131380330477SMatthew G. Knepley 
131480330477SMatthew G. Knepley   Level: intermediate
131580330477SMatthew G. Knepley 
131695452b02SPatrick Sanan   Notes:
131795452b02SPatrick Sanan     It does not copy over the coordinates.
131843eeeb2dSStefano Zampini 
13199ade3219SVaclav Hapla   Developer Notes:
13209ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL.
13219ade3219SVaclav Hapla 
1322a4a685f2SJacob Faibussowitsch .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates()
132380330477SMatthew G. Knepley @*/
13249f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
13259f074e33SMatthew G Knepley {
1326a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
13279a5b13a2SMatthew G Knepley   DM             idm, odm = dm;
13287bffde78SMichael Lange   PetscSF        sfPoint;
13292e1b13c2SMatthew G. Knepley   PetscInt       depth, dim, d;
133010a67516SMatthew G. Knepley   const char    *name;
1331b325530aSVaclav Hapla   PetscBool      flg=PETSC_TRUE;
13329f074e33SMatthew G Knepley   PetscErrorCode ierr;
13339f074e33SMatthew G Knepley 
13349f074e33SMatthew G Knepley   PetscFunctionBegin;
133510a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
133610a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
1337a72f3261SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr);
13382e1b13c2SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1339c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1340827c4036SVaclav Hapla   ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr);
1341827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1342827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
134376b791aaSMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
134476b791aaSMatthew G. Knepley     idm  = dm;
1345b21b8912SMatthew G. Knepley   } else {
13469a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
13479a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
134810a67516SMatthew G. Knepley       ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr);
13499a5b13a2SMatthew G Knepley       ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr);
1350c73cfb54SMatthew G. Knepley       ierr = DMSetDimension(idm, dim);CHKERRQ(ierr);
13517bffde78SMichael Lange       if (depth > 0) {
13527bffde78SMichael Lange         ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr);
13537bffde78SMichael Lange         ierr = DMGetPointSF(odm, &sfPoint);CHKERRQ(ierr);
135494488200SVaclav Hapla         {
13553be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
135694488200SVaclav Hapla           PetscInt nroots;
135794488200SVaclav Hapla           ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
135894488200SVaclav Hapla           if (nroots >= 0) {ierr = DMPlexInterpolatePointSF(idm, sfPoint);CHKERRQ(ierr);}
135994488200SVaclav Hapla         }
13607bffde78SMichael Lange       }
13619a5b13a2SMatthew G Knepley       if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);}
13629a5b13a2SMatthew G Knepley       odm = idm;
13639f074e33SMatthew G Knepley     }
136410a67516SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) dm,  &name);CHKERRQ(ierr);
136510a67516SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) idm,  name);CHKERRQ(ierr);
136610a67516SMatthew G. Knepley     ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr);
13675d80c0bfSVaclav Hapla     ierr = DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE);CHKERRQ(ierr);
1368b325530aSVaclav Hapla     ierr = PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL);CHKERRQ(ierr);
136927d0e99aSVaclav Hapla     if (flg) {ierr = DMPlexOrientInterface_Internal(idm);CHKERRQ(ierr);}
137084699f70SSatish Balay   }
137143eeeb2dSStefano Zampini   {
137243eeeb2dSStefano Zampini     PetscBool            isper;
137343eeeb2dSStefano Zampini     const PetscReal      *maxCell, *L;
137443eeeb2dSStefano Zampini     const DMBoundaryType *bd;
137543eeeb2dSStefano Zampini 
137643eeeb2dSStefano Zampini     ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr);
137743eeeb2dSStefano Zampini     ierr = DMSetPeriodicity(idm,isper,maxCell,L,bd);CHKERRQ(ierr);
137843eeeb2dSStefano Zampini   }
1379827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1380827c4036SVaclav Hapla   {
1381d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) idm->data;
1382827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1383827c4036SVaclav Hapla   }
13849a5b13a2SMatthew G Knepley   *dmInt = idm;
1385a72f3261SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr);
13869f074e33SMatthew G Knepley   PetscFunctionReturn(0);
13879f074e33SMatthew G Knepley }
138807b0a1fcSMatthew G Knepley 
138980330477SMatthew G. Knepley /*@
139080330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
139180330477SMatthew G. Knepley 
1392d083f849SBarry Smith   Collective on dmA
139380330477SMatthew G. Knepley 
139480330477SMatthew G. Knepley   Input Parameter:
139580330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates
139680330477SMatthew G. Knepley 
139780330477SMatthew G. Knepley   Output Parameter:
139880330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates
139980330477SMatthew G. Knepley 
140080330477SMatthew G. Knepley   Level: intermediate
140180330477SMatthew G. Knepley 
140280330477SMatthew G. Knepley   Note: This is typically used when adding pieces other than vertices to a mesh
140380330477SMatthew G. Knepley 
140465f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
140580330477SMatthew G. Knepley @*/
140607b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
140707b0a1fcSMatthew G Knepley {
140807b0a1fcSMatthew G Knepley   Vec            coordinatesA, coordinatesB;
140943eeeb2dSStefano Zampini   VecType        vtype;
141007b0a1fcSMatthew G Knepley   PetscSection   coordSectionA, coordSectionB;
141107b0a1fcSMatthew G Knepley   PetscScalar   *coordsA, *coordsB;
14120bedd6beSMatthew G. Knepley   PetscInt       spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
141390a8aa44SJed Brown   PetscInt       cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
141443eeeb2dSStefano Zampini   PetscBool      lc = PETSC_FALSE;
141507b0a1fcSMatthew G Knepley   PetscErrorCode ierr;
141607b0a1fcSMatthew G Knepley 
141707b0a1fcSMatthew G Knepley   PetscFunctionBegin;
141843eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
141943eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
142076b791aaSMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
142190a8aa44SJed Brown   ierr = DMGetCoordinateDim(dmA, &cdim);CHKERRQ(ierr);
142290a8aa44SJed Brown   ierr = DMSetCoordinateDim(dmB, cdim);CHKERRQ(ierr);
142307b0a1fcSMatthew G Knepley   ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr);
142407b0a1fcSMatthew G Knepley   ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr);
142507b0a1fcSMatthew G Knepley   if ((vEndA-vStartA) != (vEndB-vStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %d != %d in the second DM", vEndA-vStartA, vEndB-vStartB);
142643eeeb2dSStefano Zampini   ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr);
142743eeeb2dSStefano Zampini   ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr);
142869d8a9ceSMatthew G. Knepley   ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr);
142969d8a9ceSMatthew G. Knepley   ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr);
1430972bc18aSToby Isaac   if (coordSectionA == coordSectionB) PetscFunctionReturn(0);
14310bedd6beSMatthew G. Knepley   ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr);
14320bedd6beSMatthew G. Knepley   if (!Nf) PetscFunctionReturn(0);
14330bedd6beSMatthew G. Knepley   if (Nf > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf);
1434df26b574SMatthew G. Knepley   if (!coordSectionB) {
1435df26b574SMatthew G. Knepley     PetscInt dim;
1436df26b574SMatthew G. Knepley 
1437df26b574SMatthew G. Knepley     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr);
1438df26b574SMatthew G. Knepley     ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr);
1439df26b574SMatthew G. Knepley     ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr);
1440df26b574SMatthew G. Knepley     ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr);
1441df26b574SMatthew G. Knepley   }
144207b0a1fcSMatthew G Knepley   ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr);
144307b0a1fcSMatthew G Knepley   ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr);
144407b0a1fcSMatthew G Knepley   ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr);
144543eeeb2dSStefano Zampini   ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr);
144643eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
1447367003a6SStefano Zampini     if ((cEndA-cStartA) != (cEndB-cStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %D != %D in the second DM", cEndA-cStartA, cEndB-cStartB);
144843eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
144943eeeb2dSStefano Zampini     cE = vEndB;
145043eeeb2dSStefano Zampini     lc = PETSC_TRUE;
145143eeeb2dSStefano Zampini   } else {
145243eeeb2dSStefano Zampini     cS = vStartB;
145343eeeb2dSStefano Zampini     cE = vEndB;
145443eeeb2dSStefano Zampini   }
145543eeeb2dSStefano Zampini   ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr);
145607b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
145707b0a1fcSMatthew G Knepley     ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr);
145807b0a1fcSMatthew G Knepley     ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr);
145907b0a1fcSMatthew G Knepley   }
146043eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
146143eeeb2dSStefano Zampini     PetscInt c;
146243eeeb2dSStefano Zampini 
146343eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
146443eeeb2dSStefano Zampini       PetscInt dof;
146543eeeb2dSStefano Zampini 
146643eeeb2dSStefano Zampini       ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr);
146743eeeb2dSStefano Zampini       ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr);
146843eeeb2dSStefano Zampini       ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr);
146943eeeb2dSStefano Zampini     }
147043eeeb2dSStefano Zampini   }
147107b0a1fcSMatthew G Knepley   ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr);
147207b0a1fcSMatthew G Knepley   ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr);
147307b0a1fcSMatthew G Knepley   ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr);
14748b9ced59SLisandro Dalcin   ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr);
147507b0a1fcSMatthew G Knepley   ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr);
147607b0a1fcSMatthew G Knepley   ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr);
147743eeeb2dSStefano Zampini   ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr);
147843eeeb2dSStefano Zampini   ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr);
147943eeeb2dSStefano Zampini   ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr);
148043eeeb2dSStefano Zampini   ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr);
148107b0a1fcSMatthew G Knepley   ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr);
148207b0a1fcSMatthew G Knepley   ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr);
148307b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB-vStartB; ++v) {
148443eeeb2dSStefano Zampini     PetscInt offA, offB;
148543eeeb2dSStefano Zampini 
148643eeeb2dSStefano Zampini     ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr);
148743eeeb2dSStefano Zampini     ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr);
148807b0a1fcSMatthew G Knepley     for (d = 0; d < spaceDim; ++d) {
148943eeeb2dSStefano Zampini       coordsB[offB+d] = coordsA[offA+d];
149043eeeb2dSStefano Zampini     }
149143eeeb2dSStefano Zampini   }
149243eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
149343eeeb2dSStefano Zampini     PetscInt c;
149443eeeb2dSStefano Zampini 
149543eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
149643eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
149743eeeb2dSStefano Zampini 
149843eeeb2dSStefano Zampini       ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr);
149943eeeb2dSStefano Zampini       ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr);
150043eeeb2dSStefano Zampini       ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr);
1501580bdb30SBarry Smith       ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr);
150207b0a1fcSMatthew G Knepley     }
150307b0a1fcSMatthew G Knepley   }
150407b0a1fcSMatthew G Knepley   ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr);
150507b0a1fcSMatthew G Knepley   ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr);
150607b0a1fcSMatthew G Knepley   ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr);
150707b0a1fcSMatthew G Knepley   ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr);
150807b0a1fcSMatthew G Knepley   PetscFunctionReturn(0);
150907b0a1fcSMatthew G Knepley }
15105c386225SMatthew G. Knepley 
15114e3744c5SMatthew G. Knepley /*@
15124e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
15134e3744c5SMatthew G. Knepley 
1514d083f849SBarry Smith   Collective on dm
15154e3744c5SMatthew G. Knepley 
15164e3744c5SMatthew G. Knepley   Input Parameter:
15174e3744c5SMatthew G. Knepley . dm - The complete DMPlex object
15184e3744c5SMatthew G. Knepley 
15194e3744c5SMatthew G. Knepley   Output Parameter:
15204e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices
15214e3744c5SMatthew G. Knepley 
15224e3744c5SMatthew G. Knepley   Level: intermediate
15234e3744c5SMatthew G. Knepley 
152495452b02SPatrick Sanan   Notes:
152595452b02SPatrick Sanan     It does not copy over the coordinates.
152643eeeb2dSStefano Zampini 
15279ade3219SVaclav Hapla   Developer Notes:
15289ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
15299ade3219SVaclav Hapla 
1530a4a685f2SJacob Faibussowitsch .seealso: DMPlexInterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates()
15314e3744c5SMatthew G. Knepley @*/
15324e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
15334e3744c5SMatthew G. Knepley {
1534827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
15354e3744c5SMatthew G. Knepley   DM             udm;
1536412e9a14SMatthew G. Knepley   PetscInt       dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
15374e3744c5SMatthew G. Knepley   PetscErrorCode ierr;
15384e3744c5SMatthew G. Knepley 
15394e3744c5SMatthew G. Knepley   PetscFunctionBegin;
154043eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
154143eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
1542c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1543827c4036SVaclav Hapla   ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr);
1544827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1545827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1546827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
15474e3744c5SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
1548595d4abbSMatthew G. Knepley     *dmUnint = dm;
1549595d4abbSMatthew G. Knepley     PetscFunctionReturn(0);
15504e3744c5SMatthew G. Knepley   }
1551595d4abbSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1552595d4abbSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
15534e3744c5SMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr);
15544e3744c5SMatthew G. Knepley   ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr);
1555c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(udm, dim);CHKERRQ(ierr);
15564e3744c5SMatthew G. Knepley   ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr);
15574e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1558595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
15594e3744c5SMatthew G. Knepley 
15604e3744c5SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
15614e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
15624e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
15634e3744c5SMatthew G. Knepley 
15644e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
15654e3744c5SMatthew G. Knepley     }
15664e3744c5SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
15674e3744c5SMatthew G. Knepley     ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr);
1568595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
15694e3744c5SMatthew G. Knepley   }
15704e3744c5SMatthew G. Knepley   ierr = DMSetUp(udm);CHKERRQ(ierr);
1571785e854fSJed Brown   ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr);
15724e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1573595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
15744e3744c5SMatthew G. Knepley 
15754e3744c5SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
15764e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
15774e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
15784e3744c5SMatthew G. Knepley 
15794e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
15804e3744c5SMatthew G. Knepley     }
15814e3744c5SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
15824e3744c5SMatthew G. Knepley     ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr);
15834e3744c5SMatthew G. Knepley   }
15844e3744c5SMatthew G. Knepley   ierr = PetscFree(cone);CHKERRQ(ierr);
15854e3744c5SMatthew G. Knepley   ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr);
15864e3744c5SMatthew G. Knepley   ierr = DMPlexStratify(udm);CHKERRQ(ierr);
15875c7de58aSMatthew G. Knepley   /* Reduce SF */
15885c7de58aSMatthew G. Knepley   {
15895c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
15905c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
15915c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
15925c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
15935c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
15945c7de58aSMatthew G. Knepley     PetscInt           vEnd, numRoots, numLeaves, l;
15955c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
15965c7de58aSMatthew G. Knepley     PetscErrorCode     ierr;
15975c7de58aSMatthew G. Knepley 
15985c7de58aSMatthew G. Knepley     /* Get original SF information */
15995c7de58aSMatthew G. Knepley     ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
16005c7de58aSMatthew G. Knepley     ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr);
16015c7de58aSMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr);
16025c7de58aSMatthew G. Knepley     ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
16035c7de58aSMatthew G. Knepley     /* Allocate space for cells and vertices */
16045c7de58aSMatthew G. Knepley     for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++;
16055c7de58aSMatthew G. Knepley     /* Fill in leaves */
16065c7de58aSMatthew G. Knepley     if (vEnd >= 0) {
16075c7de58aSMatthew G. Knepley       ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr);
16085c7de58aSMatthew G. Knepley       ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr);
16095c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
16105c7de58aSMatthew G. Knepley         if (localPoints[l] < vEnd) {
16115c7de58aSMatthew G. Knepley           localPointsUn[n]        = localPoints[l];
16125c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
16135c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
16145c7de58aSMatthew G. Knepley           ++n;
16155c7de58aSMatthew G. Knepley         }
16165c7de58aSMatthew G. Knepley       }
16175c7de58aSMatthew G. Knepley       if (n != numLeavesUn) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn);
16185c7de58aSMatthew G. Knepley       ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr);
16195c7de58aSMatthew G. Knepley     }
16205c7de58aSMatthew G. Knepley   }
162143eeeb2dSStefano Zampini   {
162243eeeb2dSStefano Zampini     PetscBool            isper;
162343eeeb2dSStefano Zampini     const PetscReal      *maxCell, *L;
162443eeeb2dSStefano Zampini     const DMBoundaryType *bd;
162543eeeb2dSStefano Zampini 
162643eeeb2dSStefano Zampini     ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr);
162743eeeb2dSStefano Zampini     ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr);
162843eeeb2dSStefano Zampini   }
1629827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1630827c4036SVaclav Hapla   {
1631d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) udm->data;
1632827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1633827c4036SVaclav Hapla   }
16344e3744c5SMatthew G. Knepley   *dmUnint = udm;
16354e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
16364e3744c5SMatthew G. Knepley }
1637a7748839SVaclav Hapla 
1638a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1639a7748839SVaclav Hapla {
1640a7748839SVaclav Hapla   PetscInt       coneSize, depth, dim, h, p, pStart, pEnd;
1641a7748839SVaclav Hapla   MPI_Comm       comm;
1642a7748839SVaclav Hapla   PetscErrorCode ierr;
1643a7748839SVaclav Hapla 
1644a7748839SVaclav Hapla   PetscFunctionBegin;
1645a7748839SVaclav Hapla   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
1646a7748839SVaclav Hapla   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1647a7748839SVaclav Hapla   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1648a7748839SVaclav Hapla 
1649a7748839SVaclav Hapla   if (depth == dim) {
1650a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1651a7748839SVaclav Hapla     if (!dim) goto finish;
1652a7748839SVaclav Hapla 
1653a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
1654a7748839SVaclav Hapla     ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr);
1655a7748839SVaclav Hapla     for (p=pStart; p<pEnd; p++) {
1656a7748839SVaclav Hapla       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1657a7748839SVaclav Hapla       if (coneSize) {
1658a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1659a7748839SVaclav Hapla         goto finish;
1660a7748839SVaclav Hapla       }
1661a7748839SVaclav Hapla     }
1662a7748839SVaclav Hapla 
1663a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1664a7748839SVaclav Hapla     for (h=0; h<dim; h++) {
1665a7748839SVaclav Hapla       ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr);
1666a7748839SVaclav Hapla       for (p=pStart; p<pEnd; p++) {
1667a7748839SVaclav Hapla         ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1668a7748839SVaclav Hapla         if (!coneSize) {
1669a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1670a7748839SVaclav Hapla           goto finish;
1671a7748839SVaclav Hapla         }
1672a7748839SVaclav Hapla       }
1673a7748839SVaclav Hapla     }
1674a7748839SVaclav Hapla   } else if (depth == 1) {
1675a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1676a7748839SVaclav Hapla   } else {
1677a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1678a7748839SVaclav Hapla   }
1679a7748839SVaclav Hapla finish:
1680a7748839SVaclav Hapla   PetscFunctionReturn(0);
1681a7748839SVaclav Hapla }
1682a7748839SVaclav Hapla 
1683a7748839SVaclav Hapla /*@
16849ade3219SVaclav Hapla   DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated.
1685a7748839SVaclav Hapla 
1686a7748839SVaclav Hapla   Not Collective
1687a7748839SVaclav Hapla 
1688a7748839SVaclav Hapla   Input Parameter:
1689a7748839SVaclav Hapla . dm      - The DM object
1690a7748839SVaclav Hapla 
1691a7748839SVaclav Hapla   Output Parameter:
1692a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1693a7748839SVaclav Hapla 
1694a7748839SVaclav Hapla   Level: intermediate
1695a7748839SVaclav Hapla 
1696a7748839SVaclav Hapla   Notes:
16979ade3219SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this is NOT collective
16989ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
1699a7748839SVaclav Hapla   However, DMPlexInterpolate() guarantees the result is the same on all.
17009ade3219SVaclav Hapla 
1701a7748839SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED.
1702a7748839SVaclav Hapla 
17039ade3219SVaclav Hapla   Developer Notes:
17049ade3219SVaclav Hapla   Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID.
17059ade3219SVaclav Hapla 
17069ade3219SVaclav Hapla   If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called.
17079ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
17089ade3219SVaclav Hapla   DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL.
17099ade3219SVaclav Hapla 
17109ade3219SVaclav Hapla   If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated.
17119ade3219SVaclav Hapla 
17129ade3219SVaclav Hapla   DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL,
17139ade3219SVaclav Hapla   and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
17149ade3219SVaclav Hapla 
1715a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective()
1716a7748839SVaclav Hapla @*/
1717a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1718a7748839SVaclav Hapla {
1719a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1720a7748839SVaclav Hapla   PetscErrorCode  ierr;
1721a7748839SVaclav Hapla 
1722a7748839SVaclav Hapla   PetscFunctionBegin;
1723a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1724a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
1725a7748839SVaclav Hapla   if (plex->interpolated < 0) {
1726a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr);
172776bd3646SJed Brown   } else if (PetscDefined (USE_DEBUG)) {
1728a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1729a7748839SVaclav Hapla 
1730a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr);
17317fc06600SVaclav Hapla     if (flg != plex->interpolated) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1732a7748839SVaclav Hapla   }
1733a7748839SVaclav Hapla   *interpolated = plex->interpolated;
1734a7748839SVaclav Hapla   PetscFunctionReturn(0);
1735a7748839SVaclav Hapla }
1736a7748839SVaclav Hapla 
1737a7748839SVaclav Hapla /*@
17389ade3219SVaclav Hapla   DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner).
1739a7748839SVaclav Hapla 
17402666ff3cSVaclav Hapla   Collective
1741a7748839SVaclav Hapla 
1742a7748839SVaclav Hapla   Input Parameter:
1743a7748839SVaclav Hapla . dm      - The DM object
1744a7748839SVaclav Hapla 
1745a7748839SVaclav Hapla   Output Parameter:
1746a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1747a7748839SVaclav Hapla 
1748a7748839SVaclav Hapla   Level: intermediate
1749a7748839SVaclav Hapla 
1750a7748839SVaclav Hapla   Notes:
17519ade3219SVaclav Hapla   Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks.
17529ade3219SVaclav Hapla 
17539ade3219SVaclav Hapla   This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks.
17549ade3219SVaclav Hapla 
17559ade3219SVaclav Hapla   Developer Notes:
17569ade3219SVaclav Hapla   Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID.
17579ade3219SVaclav Hapla 
17589ade3219SVaclav Hapla   If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated.
17599ade3219SVaclav Hapla   MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
17609ade3219SVaclav Hapla   if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED,
17619ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
17629ade3219SVaclav Hapla 
17639ade3219SVaclav Hapla   If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective.
1764a7748839SVaclav Hapla 
1765a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated()
1766a7748839SVaclav Hapla @*/
1767a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1768a7748839SVaclav Hapla {
1769a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1770a7748839SVaclav Hapla   PetscBool       debug=PETSC_FALSE;
1771a7748839SVaclav Hapla   PetscErrorCode  ierr;
1772a7748839SVaclav Hapla 
1773a7748839SVaclav Hapla   PetscFunctionBegin;
1774a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1775a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
1776a7748839SVaclav Hapla   ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr);
1777a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1778a7748839SVaclav Hapla     DMPlexInterpolatedFlag  min, max;
1779a7748839SVaclav Hapla     MPI_Comm                comm;
1780a7748839SVaclav Hapla 
1781a7748839SVaclav Hapla     ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
1782a7748839SVaclav Hapla     ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr);
1783a7748839SVaclav Hapla     ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRQ(ierr);
1784a7748839SVaclav Hapla     ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRQ(ierr);
1785a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1786a7748839SVaclav Hapla     if (debug) {
1787a7748839SVaclav Hapla       PetscMPIInt rank;
1788a7748839SVaclav Hapla 
1789a7748839SVaclav Hapla       ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1790a7748839SVaclav Hapla       ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr);
1791a7748839SVaclav Hapla       ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr);
1792a7748839SVaclav Hapla     }
1793a7748839SVaclav Hapla   }
1794a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
1795a7748839SVaclav Hapla   PetscFunctionReturn(0);
1796a7748839SVaclav Hapla }
1797