xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 5de52c6d2b8d6de382140bd9fae367e1f02f2f13)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2e8f14785SLisandro Dalcin #include <petsc/private/hashmapi.h>
3e8f14785SLisandro Dalcin #include <petsc/private/hashmapij.h>
4e8f14785SLisandro Dalcin 
5ea78f98cSLisandro Dalcin const char * const DMPlexInterpolatedFlags[] = {"none", "partial", "mixed", "full", "DMPlexInterpolatedFlag", "DMPLEX_INTERPOLATED_", NULL};
6a7748839SVaclav Hapla 
7e8f14785SLisandro Dalcin /* HashIJKL */
8e8f14785SLisandro Dalcin 
9e8f14785SLisandro Dalcin #include <petsc/private/hashmap.h>
10e8f14785SLisandro Dalcin 
11e8f14785SLisandro Dalcin typedef struct _PetscHashIJKLKey { PetscInt i, j, k, l; } PetscHashIJKLKey;
12e8f14785SLisandro Dalcin 
13e8f14785SLisandro Dalcin #define PetscHashIJKLKeyHash(key) \
14e8f14785SLisandro Dalcin   PetscHashCombine(PetscHashCombine(PetscHashInt((key).i),PetscHashInt((key).j)), \
15e8f14785SLisandro Dalcin                    PetscHashCombine(PetscHashInt((key).k),PetscHashInt((key).l)))
16e8f14785SLisandro Dalcin 
17e8f14785SLisandro Dalcin #define PetscHashIJKLKeyEqual(k1,k2) \
18e8f14785SLisandro Dalcin   (((k1).i==(k2).i) ? ((k1).j==(k2).j) ? ((k1).k==(k2).k) ? ((k1).l==(k2).l) : 0 : 0 : 0)
19e8f14785SLisandro Dalcin 
20999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKL, PetscHashIJKLKey, PetscInt, PetscHashIJKLKeyHash, PetscHashIJKLKeyEqual, -1))
21e8f14785SLisandro Dalcin 
223be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1};
233be36e83SMatthew G. Knepley 
243be36e83SMatthew G. Knepley typedef struct _PetscHashIJKLRemoteKey { PetscSFNode i, j, k, l; } PetscHashIJKLRemoteKey;
253be36e83SMatthew G. Knepley 
263be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \
273be36e83SMatthew G. Knepley   PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index),PetscHashInt((key).j.rank + (key).j.index)), \
283be36e83SMatthew G. Knepley                    PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index),PetscHashInt((key).l.rank + (key).l.index)))
293be36e83SMatthew G. Knepley 
303be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyEqual(k1,k2) \
313be36e83SMatthew G. Knepley   (((k1).i.rank==(k2).i.rank) ? ((k1).i.index==(k2).i.index) ? ((k1).j.rank==(k2).j.rank) ? ((k1).j.index==(k2).j.index) ? ((k1).k.rank==(k2).k.rank) ? ((k1).k.index==(k2).k.index) ? ((k1).l.rank==(k2).l.rank) ? ((k1).l.index==(k2).l.index) : 0 : 0 : 0 : 0 : 0 : 0 : 0)
323be36e83SMatthew G. Knepley 
33999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode))
343be36e83SMatthew G. Knepley 
353be36e83SMatthew G. Knepley static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[])
363be36e83SMatthew G. Knepley {
373be36e83SMatthew G. Knepley   PetscInt i;
383be36e83SMatthew G. Knepley 
393be36e83SMatthew G. Knepley   PetscFunctionBegin;
403be36e83SMatthew G. Knepley   for (i = 1; i < n; ++i) {
413be36e83SMatthew G. Knepley     PetscSFNode x = A[i];
423be36e83SMatthew G. Knepley     PetscInt    j;
433be36e83SMatthew G. Knepley 
443be36e83SMatthew G. Knepley     for (j = i-1; j >= 0; --j) {
453be36e83SMatthew G. Knepley       if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break;
463be36e83SMatthew G. Knepley       A[j+1] = A[j];
473be36e83SMatthew G. Knepley     }
483be36e83SMatthew G. Knepley     A[j+1] = x;
493be36e83SMatthew G. Knepley   }
503be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
513be36e83SMatthew G. Knepley }
529f074e33SMatthew G Knepley 
539f074e33SMatthew G Knepley /*
54439ece16SMatthew G. Knepley   DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone
55439ece16SMatthew G. Knepley */
56412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
57439ece16SMatthew G. Knepley {
58412e9a14SMatthew G. Knepley   DMPolytopeType *typesTmp;
59412e9a14SMatthew G. Knepley   PetscInt       *sizesTmp, *facesTmp;
60439ece16SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize;
61439ece16SMatthew G. Knepley 
62439ece16SMatthew G. Knepley   PetscFunctionBegin;
63439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(cone, 3);
659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
669566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize),           MPIU_INT, &typesTmp));
679566063dSJacob Faibussowitsch   if (faceSizes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize),           MPIU_INT, &sizesTmp));
689566063dSJacob Faibussowitsch   if (faces)     PetscCall(DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp));
69ba2698f1SMatthew G. Knepley   switch (ct) {
70ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_POINT:
71ba2698f1SMatthew G. Knepley       if (numFaces) *numFaces = 0;
72ba2698f1SMatthew G. Knepley       break;
73ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
74412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 2;
75412e9a14SMatthew G. Knepley       if (faceTypes) {
76412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT;
77412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
78412e9a14SMatthew G. Knepley       }
79412e9a14SMatthew G. Knepley       if (faceSizes) {
80412e9a14SMatthew G. Knepley         sizesTmp[0] = 1; sizesTmp[1] = 1;
81412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
82412e9a14SMatthew G. Knepley       }
83c49d9212SMatthew G. Knepley       if (faces) {
84c49d9212SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
85c49d9212SMatthew G. Knepley         *faces = facesTmp;
86c49d9212SMatthew G. Knepley       }
87412e9a14SMatthew G. Knepley       break;
88412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
89c49d9212SMatthew G. Knepley       if (numFaces) *numFaces = 2;
90412e9a14SMatthew G. Knepley       if (faceTypes) {
91412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT;
92412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
93412e9a14SMatthew G. Knepley       }
94412e9a14SMatthew G. Knepley       if (faceSizes) {
95412e9a14SMatthew G. Knepley         sizesTmp[0] = 1; sizesTmp[1] = 1;
96412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
97412e9a14SMatthew G. Knepley       }
98412e9a14SMatthew G. Knepley       if (faces) {
99412e9a14SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
100412e9a14SMatthew G. Knepley         *faces = facesTmp;
101412e9a14SMatthew G. Knepley       }
102c49d9212SMatthew G. Knepley       break;
103ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
104412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 3;
105412e9a14SMatthew G. Knepley       if (faceTypes) {
106412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT;
107412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
108412e9a14SMatthew G. Knepley       }
109412e9a14SMatthew G. Knepley       if (faceSizes) {
110412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2;
111412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
112412e9a14SMatthew G. Knepley       }
1139a5b13a2SMatthew G Knepley       if (faces) {
1149a5b13a2SMatthew G Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
1159a5b13a2SMatthew G Knepley         facesTmp[2] = cone[1]; facesTmp[3] = cone[2];
1169a5b13a2SMatthew G Knepley         facesTmp[4] = cone[2]; facesTmp[5] = cone[0];
1179a5b13a2SMatthew G Knepley         *faces = facesTmp;
1189a5b13a2SMatthew G Knepley       }
1199f074e33SMatthew G Knepley       break;
120ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1219a5b13a2SMatthew G Knepley       /* Vertices follow right hand rule */
122412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 4;
123412e9a14SMatthew G. Knepley       if (faceTypes) {
124412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT; typesTmp[3] = DM_POLYTOPE_SEGMENT;
125412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
126412e9a14SMatthew G. Knepley       }
127412e9a14SMatthew G. Knepley       if (faceSizes) {
128412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2;
129412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
130412e9a14SMatthew G. Knepley       }
1319a5b13a2SMatthew G Knepley       if (faces) {
1329a5b13a2SMatthew G Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
1339a5b13a2SMatthew G Knepley         facesTmp[2] = cone[1]; facesTmp[3] = cone[2];
1349a5b13a2SMatthew G Knepley         facesTmp[4] = cone[2]; facesTmp[5] = cone[3];
1359a5b13a2SMatthew G Knepley         facesTmp[6] = cone[3]; facesTmp[7] = cone[0];
1369a5b13a2SMatthew G Knepley         *faces = facesTmp;
1379a5b13a2SMatthew G Knepley       }
138412e9a14SMatthew G. Knepley       break;
139412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1409a5b13a2SMatthew G Knepley       if (numFaces) *numFaces = 4;
141412e9a14SMatthew G. Knepley       if (faceTypes) {
142412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR; typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
143412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
144412e9a14SMatthew G. Knepley       }
145412e9a14SMatthew G. Knepley       if (faceSizes) {
146412e9a14SMatthew G. Knepley         sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2;
147412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
148412e9a14SMatthew G. Knepley       }
149412e9a14SMatthew G. Knepley       if (faces) {
150412e9a14SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1] = cone[1];
151412e9a14SMatthew G. Knepley         facesTmp[2] = cone[2]; facesTmp[3] = cone[3];
152412e9a14SMatthew G. Knepley         facesTmp[4] = cone[0]; facesTmp[5] = cone[2];
153412e9a14SMatthew G. Knepley         facesTmp[6] = cone[1]; facesTmp[7] = cone[3];
154412e9a14SMatthew G. Knepley         *faces = facesTmp;
155412e9a14SMatthew G. Knepley       }
1569f074e33SMatthew G Knepley       break;
157ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
1582e1b13c2SMatthew G. Knepley       /* Vertices of first face follow right hand rule and normal points away from last vertex */
159412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 4;
160412e9a14SMatthew G. Knepley       if (faceTypes) {
161412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE;
162412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
163412e9a14SMatthew G. Knepley       }
164412e9a14SMatthew G. Knepley       if (faceSizes) {
165412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3;
166412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
167412e9a14SMatthew G. Knepley       }
1689a5b13a2SMatthew G Knepley       if (faces) {
1692e1b13c2SMatthew G. Knepley         facesTmp[0] = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];
1702e1b13c2SMatthew G. Knepley         facesTmp[3] = cone[0]; facesTmp[4]  = cone[3]; facesTmp[5]  = cone[1];
1712e1b13c2SMatthew G. Knepley         facesTmp[6] = cone[0]; facesTmp[7]  = cone[2]; facesTmp[8]  = cone[3];
1722e1b13c2SMatthew G. Knepley         facesTmp[9] = cone[2]; facesTmp[10] = cone[1]; facesTmp[11] = cone[3];
1739a5b13a2SMatthew G Knepley         *faces = facesTmp;
1749a5b13a2SMatthew G Knepley       }
1759a5b13a2SMatthew G Knepley       break;
176ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
177e368ef20SMatthew G. Knepley       /*  7--------6
178e368ef20SMatthew G. Knepley          /|       /|
179e368ef20SMatthew G. Knepley         / |      / |
180e368ef20SMatthew G. Knepley        4--------5  |
181e368ef20SMatthew G. Knepley        |  |     |  |
182e368ef20SMatthew G. Knepley        |  |     |  |
183e368ef20SMatthew G. Knepley        |  1--------2
184e368ef20SMatthew G. Knepley        | /      | /
185e368ef20SMatthew G. Knepley        |/       |/
186e368ef20SMatthew G. Knepley        0--------3
187e368ef20SMatthew G. Knepley        */
188412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 6;
189412e9a14SMatthew G. Knepley       if (faceTypes) {
190412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
191412e9a14SMatthew G. Knepley         typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
192412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
193412e9a14SMatthew G. Knepley       }
194412e9a14SMatthew G. Knepley       if (faceSizes) {
195412e9a14SMatthew G. Knepley         sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4;
196412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
197412e9a14SMatthew G. Knepley       }
1989a5b13a2SMatthew G Knepley       if (faces) {
19951cfd6a4SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
20051cfd6a4SMatthew G. Knepley         facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5]; facesTmp[6]  = cone[6]; facesTmp[7]  = cone[7]; /* Top */
20151cfd6a4SMatthew G. Knepley         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[3]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; /* Front */
20251cfd6a4SMatthew G. Knepley         facesTmp[12] = cone[2]; facesTmp[13] = cone[1]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; /* Back */
20351cfd6a4SMatthew G. Knepley         facesTmp[16] = cone[3]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; /* Right */
20451cfd6a4SMatthew G. Knepley         facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[1]; /* Left */
2059a5b13a2SMatthew G Knepley         *faces = facesTmp;
2069a5b13a2SMatthew G Knepley       }
20799836e0eSStefano Zampini       break;
208ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
209412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 5;
210412e9a14SMatthew G. Knepley       if (faceTypes) {
211412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE;
212412e9a14SMatthew G. Knepley         typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
213412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
214412e9a14SMatthew G. Knepley       }
215412e9a14SMatthew G. Knepley       if (faceSizes) {
216412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3;
217412e9a14SMatthew G. Knepley         sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4;
218412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
219412e9a14SMatthew G. Knepley       }
220ba2698f1SMatthew G. Knepley       if (faces) {
221412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];                         /* Bottom */
222412e9a14SMatthew G. Knepley         facesTmp[3]  = cone[3]; facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5];                         /* Top */
223412e9a14SMatthew G. Knepley         facesTmp[6]  = cone[0]; facesTmp[7]  = cone[2]; facesTmp[8]  = cone[4]; facesTmp[9]  = cone[3]; /* Back left */
224412e9a14SMatthew G. Knepley         facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[5]; facesTmp[13] = cone[4]; /* Front */
225412e9a14SMatthew G. Knepley         facesTmp[14] = cone[1]; facesTmp[15] = cone[0]; facesTmp[16] = cone[3]; facesTmp[17] = cone[5]; /* Back right */
226ba2698f1SMatthew G. Knepley         *faces = facesTmp;
22799836e0eSStefano Zampini       }
22899836e0eSStefano Zampini       break;
229ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
230412e9a14SMatthew G. Knepley       if (numFaces)     *numFaces = 5;
231412e9a14SMatthew G. Knepley       if (faceTypes) {
232412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE;
233412e9a14SMatthew G. Knepley         typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
234412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
235412e9a14SMatthew G. Knepley       }
236412e9a14SMatthew G. Knepley       if (faceSizes) {
237412e9a14SMatthew G. Knepley         sizesTmp[0] = 3; sizesTmp[1] = 3;
238412e9a14SMatthew G. Knepley         sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4;
239412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
240412e9a14SMatthew G. Knepley       }
24199836e0eSStefano Zampini       if (faces) {
242412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2];                         /* Bottom */
243412e9a14SMatthew G. Knepley         facesTmp[3]  = cone[3]; facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5];                         /* Top */
244412e9a14SMatthew G. Knepley         facesTmp[6]  = cone[0]; facesTmp[7]  = cone[1]; facesTmp[8]  = cone[3]; facesTmp[9]  = cone[4]; /* Back left */
245412e9a14SMatthew G. Knepley         facesTmp[10] = cone[1]; facesTmp[11] = cone[2]; facesTmp[12] = cone[4]; facesTmp[13] = cone[5]; /* Back right */
246412e9a14SMatthew G. Knepley         facesTmp[14] = cone[2]; facesTmp[15] = cone[0]; facesTmp[16] = cone[5]; facesTmp[17] = cone[3]; /* Front */
24799836e0eSStefano Zampini         *faces = facesTmp;
24899836e0eSStefano Zampini       }
249412e9a14SMatthew G. Knepley       break;
250412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
251412e9a14SMatthew G. Knepley       /*  7--------6
252412e9a14SMatthew G. Knepley          /|       /|
253412e9a14SMatthew G. Knepley         / |      / |
254412e9a14SMatthew G. Knepley        4--------5  |
255412e9a14SMatthew G. Knepley        |  |     |  |
256412e9a14SMatthew G. Knepley        |  |     |  |
257412e9a14SMatthew G. Knepley        |  3--------2
258412e9a14SMatthew G. Knepley        | /      | /
259412e9a14SMatthew G. Knepley        |/       |/
260412e9a14SMatthew G. Knepley        0--------1
261412e9a14SMatthew G. Knepley        */
262412e9a14SMatthew G. Knepley       if (numFaces) *numFaces = 6;
263412e9a14SMatthew G. Knepley       if (faceTypes) {
264412e9a14SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;    typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;    typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
265412e9a14SMatthew G. Knepley         typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
266412e9a14SMatthew G. Knepley         *faceTypes = typesTmp;
267412e9a14SMatthew G. Knepley       }
268412e9a14SMatthew G. Knepley       if (faceSizes) {
269412e9a14SMatthew G. Knepley         sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4;
270412e9a14SMatthew G. Knepley         *faceSizes = sizesTmp;
271412e9a14SMatthew G. Knepley       }
272412e9a14SMatthew G. Knepley       if (faces) {
273412e9a14SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
274412e9a14SMatthew G. Knepley         facesTmp[4]  = cone[4]; facesTmp[5]  = cone[5]; facesTmp[6]  = cone[6]; facesTmp[7]  = cone[7]; /* Top */
275412e9a14SMatthew G. Knepley         facesTmp[8]  = cone[0]; facesTmp[9]  = cone[1]; facesTmp[10] = cone[4]; facesTmp[11] = cone[5]; /* Front */
276412e9a14SMatthew G. Knepley         facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[5]; facesTmp[15] = cone[6]; /* Right */
277412e9a14SMatthew G. Knepley         facesTmp[16] = cone[2]; facesTmp[17] = cone[3]; facesTmp[18] = cone[6]; facesTmp[19] = cone[7]; /* Back */
278412e9a14SMatthew G. Knepley         facesTmp[20] = cone[3]; facesTmp[21] = cone[0]; facesTmp[22] = cone[7]; facesTmp[23] = cone[4]; /* Left */
279412e9a14SMatthew G. Knepley         *faces = facesTmp;
280412e9a14SMatthew G. Knepley       }
28199836e0eSStefano Zampini       break;
282da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
283da9060c4SMatthew G. Knepley       /*
284da9060c4SMatthew G. Knepley        4----
285da9060c4SMatthew G. Knepley        |\-\ \-----
286da9060c4SMatthew G. Knepley        | \ -\     \
287da9060c4SMatthew G. Knepley        |  1--\-----2
288da9060c4SMatthew G. Knepley        | /    \   /
289da9060c4SMatthew G. Knepley        |/      \ /
290da9060c4SMatthew G. Knepley        0--------3
291da9060c4SMatthew G. Knepley        */
292da9060c4SMatthew G. Knepley       if (numFaces) *numFaces = 5;
293da9060c4SMatthew G. Knepley       if (faceTypes) {
294da9060c4SMatthew G. Knepley         typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
295da9060c4SMatthew G. Knepley         typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; typesTmp[4] = DM_POLYTOPE_TRIANGLE;
296da9060c4SMatthew G. Knepley         *faceTypes = typesTmp;
297da9060c4SMatthew G. Knepley       }
298da9060c4SMatthew G. Knepley       if (faceSizes) {
299da9060c4SMatthew G. Knepley         sizesTmp[0] = 4;
300da9060c4SMatthew G. Knepley         sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; sizesTmp[4] = 3;
301da9060c4SMatthew G. Knepley         *faceSizes = sizesTmp;
302da9060c4SMatthew G. Knepley       }
303da9060c4SMatthew G. Knepley       if (faces) {
304da9060c4SMatthew G. Knepley         facesTmp[0]  = cone[0]; facesTmp[1]  = cone[1]; facesTmp[2]  = cone[2]; facesTmp[3]  = cone[3]; /* Bottom */
305da9060c4SMatthew G. Knepley         facesTmp[4]  = cone[0]; facesTmp[5]  = cone[3]; facesTmp[6]  = cone[4];                         /* Front */
306da9060c4SMatthew G. Knepley         facesTmp[7]  = cone[3]; facesTmp[8]  = cone[2]; facesTmp[9]  = cone[4];                         /* Right */
307da9060c4SMatthew G. Knepley         facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[4];                         /* Back */
308da9060c4SMatthew G. Knepley         facesTmp[13] = cone[1]; facesTmp[14] = cone[0]; facesTmp[15] = cone[4];                         /* Left */
309da9060c4SMatthew G. Knepley         *faces = facesTmp;
310da9060c4SMatthew G. Knepley       }
311da9060c4SMatthew G. Knepley       break;
31298921bdaSJacob Faibussowitsch     default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
31399836e0eSStefano Zampini   }
31499836e0eSStefano Zampini   PetscFunctionReturn(0);
31599836e0eSStefano Zampini }
31699836e0eSStefano Zampini 
317412e9a14SMatthew G. Knepley PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
31899836e0eSStefano Zampini {
31999836e0eSStefano Zampini   PetscFunctionBegin;
3209566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceTypes));
3219566063dSJacob Faibussowitsch   if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceSizes));
3229566063dSJacob Faibussowitsch   if (faces)     PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces));
32399836e0eSStefano Zampini   PetscFunctionReturn(0);
32499836e0eSStefano Zampini }
32599836e0eSStefano Zampini 
3269a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
3279a5b13a2SMatthew G Knepley static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
3289f074e33SMatthew G Knepley {
329412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
3309a5b13a2SMatthew G Knepley   PetscHashIJKL  faceTable;
331412e9a14SMatthew G. Knepley   PetscInt       faceTypeNum[DM_NUM_POLYTOPES];
3329318fe57SMatthew G. Knepley   PetscInt       depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd;
3339f074e33SMatthew G Knepley 
3349f074e33SMatthew G Knepley   PetscFunctionBegin;
3359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3369566063dSJacob Faibussowitsch   PetscCall(PetscHashIJKLCreate(&faceTable));
3379566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
3389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
339412e9a14SMatthew G. Knepley   /* Number new faces and save face vertices in hash table */
3409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
341412e9a14SMatthew G. Knepley   fEnd = fStart;
342412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
343412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
344412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
345ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
346412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
34799836e0eSStefano Zampini 
3489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
3499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
3509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
351412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
352412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
353412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
354412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
3559a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
356e8f14785SLisandro Dalcin       PetscHashIter        iter;
357e8f14785SLisandro Dalcin       PetscBool            missing;
3589f074e33SMatthew G Knepley 
3595f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
360412e9a14SMatthew G. Knepley       key.i = face[0];
361412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
362412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
363412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
3649566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *) &key));
3659566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
366e9fa77a1SMatthew G. Knepley       if (missing) {
3679566063dSJacob Faibussowitsch         PetscCall(PetscHashIJKLIterSet(faceTable, iter, fEnd++));
368412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
369e9fa77a1SMatthew G. Knepley       }
3709a5b13a2SMatthew G Knepley     }
3719566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
37299836e0eSStefano Zampini   }
373412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
374412e9a14SMatthew G. Knepley   {
375412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
37699836e0eSStefano Zampini 
377412e9a14SMatthew G. Knepley     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {if (faceTypeNum[ct]) ++numFT; faceTypeStart[ct] = 0;}
378412e9a14SMatthew G. Knepley     if (numFT > 1) {
3799566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLClear(faceTable));
380412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
381412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct-1] + faceTypeNum[ct-1];
382412e9a14SMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
383412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
384412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
385ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
386412e9a14SMatthew G. Knepley         PetscInt              numFaces, cf, foff = 0;
38799836e0eSStefano Zampini 
3889566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
3899566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
3909566063dSJacob Faibussowitsch         PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
391412e9a14SMatthew G. Knepley         for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
392412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
393412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
394412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
39599836e0eSStefano Zampini           PetscHashIJKLKey     key;
39699836e0eSStefano Zampini           PetscHashIter        iter;
39799836e0eSStefano Zampini           PetscBool            missing;
39899836e0eSStefano Zampini 
3995f80ce2aSJacob Faibussowitsch           PetscCheck(faceSize <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
400412e9a14SMatthew G. Knepley           key.i = face[0];
401412e9a14SMatthew G. Knepley           key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
402412e9a14SMatthew G. Knepley           key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
403412e9a14SMatthew G. Knepley           key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
4049566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *) &key));
4059566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
4069566063dSJacob Faibussowitsch           if (missing) PetscCall(PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
40799836e0eSStefano Zampini         }
4089566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
40999836e0eSStefano Zampini       }
410412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
4111dca8a05SBarry Smith         PetscCheck(faceTypeStart[ct] == faceTypeStart[ct-1] + faceTypeNum[ct],PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent numbering for cell type %s, %" PetscInt_FMT " != %" PetscInt_FMT " + %" PetscInt_FMT, DMPolytopeTypes[ct], faceTypeStart[ct], faceTypeStart[ct-1], faceTypeNum[ct]);
4129a5b13a2SMatthew G Knepley       }
4139a5b13a2SMatthew G Knepley     }
414412e9a14SMatthew G. Knepley   }
415412e9a14SMatthew G. Knepley   /* Add new points, always at the end of the numbering */
4169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
4179566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
4189a5b13a2SMatthew G Knepley   /* Set cone sizes */
419412e9a14SMatthew G. Knepley   /*   Must create the celltype label here so that we do not automatically try to compute the types */
4209566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
4219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
4229a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
423412e9a14SMatthew G. Knepley     DMPolytopeType ct;
424412e9a14SMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, p;
4259f074e33SMatthew G Knepley 
426412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
4279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
428412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
4299566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4309566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, p, coneSize));
4319566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
4329566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, p, ct));
4339f074e33SMatthew G Knepley     }
4349f074e33SMatthew G Knepley   }
435412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
436412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
437412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
438412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
439412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
440412e9a14SMatthew G. Knepley 
4419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
4429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
4439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
4449566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(idm, c, ct));
4459566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(idm, c, numFaces));
446412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
447412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
448412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
449412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
450412e9a14SMatthew G. Knepley       PetscHashIJKLKey     key;
451412e9a14SMatthew G. Knepley       PetscHashIter        iter;
452412e9a14SMatthew G. Knepley       PetscBool            missing;
453412e9a14SMatthew G. Knepley       PetscInt             f;
454412e9a14SMatthew G. Knepley 
45563a3b9bcSJacob Faibussowitsch       PetscCheck(faceSize <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
456412e9a14SMatthew G. Knepley       key.i = face[0];
457412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
458412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
459412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
4609566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *) &key));
4619566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
46263a3b9bcSJacob Faibussowitsch       PetscCheck(!missing,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %" PetscInt_FMT ", lf %" PetscInt_FMT ")", c, cf);
4639566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f));
4649566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, f, faceSize));
4659566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, f, faceType));
466412e9a14SMatthew G. Knepley     }
4679566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
4689f074e33SMatthew G Knepley   }
4699566063dSJacob Faibussowitsch   PetscCall(DMSetUp(idm));
470412e9a14SMatthew G. Knepley   /* Initialize cones so we do not need the bash table to tell us that a cone has been set */
471412e9a14SMatthew G. Knepley   {
472412e9a14SMatthew G. Knepley     PetscSection cs;
473412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
4749a5b13a2SMatthew G Knepley 
4759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSection(idm, &cs));
4769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCones(idm, &cones));
4779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(cs, &csize));
478412e9a14SMatthew G. Knepley     for (c = 0; c < csize; ++c) cones[c] = -1;
479412e9a14SMatthew G. Knepley   }
480412e9a14SMatthew G. Knepley   /* Set cones */
481412e9a14SMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
482412e9a14SMatthew G. Knepley     const PetscInt *cone;
483412e9a14SMatthew G. Knepley     PetscInt        pStart, pEnd, p;
484412e9a14SMatthew G. Knepley 
485412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
4869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
487412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
4889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, p, &cone));
4899566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(idm, p, cone));
4909566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
4919566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeOrientation(idm, p, cone));
4929f074e33SMatthew G Knepley     }
4939a5b13a2SMatthew G Knepley   }
494412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
495412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
496412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
497ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
498412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
49999836e0eSStefano Zampini 
5009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
503412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
504412e9a14SMatthew G. Knepley       DMPolytopeType   faceType = faceTypes[cf];
505412e9a14SMatthew G. Knepley       const PetscInt   faceSize = faceSizes[cf];
506412e9a14SMatthew G. Knepley       const PetscInt  *face     = &faces[foff];
507412e9a14SMatthew G. Knepley       const PetscInt  *fcone;
5089a5b13a2SMatthew G Knepley       PetscHashIJKLKey key;
509e8f14785SLisandro Dalcin       PetscHashIter    iter;
510e8f14785SLisandro Dalcin       PetscBool        missing;
511412e9a14SMatthew G. Knepley       PetscInt         f;
5129f074e33SMatthew G Knepley 
51363a3b9bcSJacob Faibussowitsch       PetscCheck(faceSize <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
514412e9a14SMatthew G. Knepley       key.i = face[0];
515412e9a14SMatthew G. Knepley       key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT;
516412e9a14SMatthew G. Knepley       key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT;
517412e9a14SMatthew G. Knepley       key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT;
5189566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *) &key));
5199566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing));
5209566063dSJacob Faibussowitsch       PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f));
5219566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertCone(idm, c, cf, f));
5229566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(idm, f, &fcone));
5239566063dSJacob Faibussowitsch       if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
524412e9a14SMatthew G. Knepley       {
525412e9a14SMatthew G. Knepley         const PetscInt *cone;
526412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
527a74221b0SStefano Zampini 
5289566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
5299566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &cone));
53063a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == faceSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %" PetscInt_FMT " for face %" PetscInt_FMT " should be %" PetscInt_FMT, coneSize, f, faceSize);
531d89e6e46SMatthew G. Knepley         /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
5329566063dSJacob Faibussowitsch         PetscCall(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt));
5339566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertConeOrientation(idm, c, cf, ornt));
53499836e0eSStefano Zampini       }
53599836e0eSStefano Zampini     }
5369566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
53799836e0eSStefano Zampini   }
5389566063dSJacob Faibussowitsch   PetscCall(PetscHashIJKLDestroy(&faceTable));
5399566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
5409566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
5419f074e33SMatthew G Knepley   PetscFunctionReturn(0);
5429f074e33SMatthew G Knepley }
5439f074e33SMatthew G Knepley 
544f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
545f80536cbSVaclav Hapla {
546f80536cbSVaclav Hapla   PetscInt            nleaves;
547f80536cbSVaclav Hapla   PetscInt            nranks;
548a0d42dbcSVaclav Hapla   const PetscMPIInt  *ranks=NULL;
549a0d42dbcSVaclav Hapla   const PetscInt     *roffset=NULL, *rmine=NULL, *rremote=NULL;
550f80536cbSVaclav Hapla   PetscInt            n, o, r;
551f80536cbSVaclav Hapla 
552f80536cbSVaclav Hapla   PetscFunctionBegin;
5539566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
554f80536cbSVaclav Hapla   nleaves = roffset[nranks];
5559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
556f80536cbSVaclav Hapla   for (r=0; r<nranks; r++) {
557f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
558f80536cbSVaclav Hapla        - to unify order with the other side */
559f80536cbSVaclav Hapla     o = roffset[r];
560f80536cbSVaclav Hapla     n = roffset[r+1] - o;
5619566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
5629566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
5639566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
564f80536cbSVaclav Hapla   }
565f80536cbSVaclav Hapla   PetscFunctionReturn(0);
566f80536cbSVaclav Hapla }
567f80536cbSVaclav Hapla 
56827d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
5692e745bdaSMatthew G. Knepley {
570d89e6e46SMatthew G. Knepley   PetscSF            sf;
571d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
572d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
573d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
574d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
575d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
576d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
577d89e6e46SMatthew G. Knepley   PetscInt         (*roots)[4],      (*leaves)[4], mainCone[4];
578d89e6e46SMatthew G. Knepley   PetscMPIInt      (*rootsRanks)[4], (*leavesRanks)[4];
5792e745bdaSMatthew G. Knepley   MPI_Comm           comm;
58027d0e99aSVaclav Hapla   PetscMPIInt        rank, size;
5812e745bdaSMatthew G. Knepley   PetscInt           debug = 0;
5822e745bdaSMatthew G. Knepley 
5832e745bdaSMatthew G. Knepley   PetscFunctionBegin;
5849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
5859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
5879566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
5889566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
5899566063dSJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm));
5909566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
591d89e6e46SMatthew G. Knepley   if (nroots < 0) PetscFunctionReturn(0);
5929566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
5939566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
594d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
595d89e6e46SMatthew G. Knepley     PetscInt coneSize;
5969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
597d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
598d89e6e46SMatthew G. Knepley   }
59963a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4,comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
6009566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
6019e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
602d89e6e46SMatthew G. Knepley     const PetscInt *cone;
603d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
604d89e6e46SMatthew G. Knepley 
6059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
6069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
607d89e6e46SMatthew G. Knepley     /* Ignore vertices */
60827d0e99aSVaclav Hapla     if (coneSize < 2) {
609d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
61027d0e99aSVaclav Hapla         roots[p][c]      = -1;
61127d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
61227d0e99aSVaclav Hapla       }
61327d0e99aSVaclav Hapla       continue;
61427d0e99aSVaclav Hapla     }
6152e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
616d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
6179566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
6188a650c75SVaclav Hapla       if (ind0 < 0) {
6198a650c75SVaclav Hapla         roots[p][c]      = cone[c];
6208a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
621c8148b97SVaclav Hapla       } else {
6228a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
6238a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
6248a650c75SVaclav Hapla       }
6252e745bdaSMatthew G. Knepley     }
626d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
627d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
628d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
629d89e6e46SMatthew G. Knepley     }
6302e745bdaSMatthew G. Knepley   }
6319e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
632d89e6e46SMatthew G. Knepley     PetscInt c;
633d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
6348ccb905dSVaclav Hapla       leaves[p][c]      = -2;
6358ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
6368ccb905dSVaclav Hapla     }
637c8148b97SVaclav Hapla   }
6389566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
6399566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
6409566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
6419566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
642d89e6e46SMatthew G. Knepley   if (debug) {
6439566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
6449566063dSJacob Faibussowitsch     if (!rank) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
645d89e6e46SMatthew G. Knepley   }
6469566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
6479e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
648d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
649d89e6e46SMatthew G. Knepley     const PetscInt *cone;
650d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
651d89e6e46SMatthew G. Knepley 
652d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
6539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
6549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
6559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
656d89e6e46SMatthew G. Knepley     if (debug) {
65763a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]  %4" PetscInt_FMT ": cone=[%4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT "] roots=[(%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ")] leaves=[(%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ")]",
658d89e6e46SMatthew G. Knepley                                       rank, p, cone[0], cone[1], cone[2], cone[3],
659d89e6e46SMatthew G. Knepley                                       rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], rootsRanks[p][2], roots[p][2], rootsRanks[p][3], roots[p][3],
6605f80ce2aSJacob Faibussowitsch                                       leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1], leavesRanks[p][2], leaves[p][2], leavesRanks[p][3], leaves[p][3]));
661d89e6e46SMatthew G. Knepley     }
662d89e6e46SMatthew G. Knepley     if (leavesRanks[p][0] != rootsRanks[p][0] || leaves[p][0] != roots[p][0] ||
663d89e6e46SMatthew G. Knepley         leavesRanks[p][1] != rootsRanks[p][1] || leaves[p][1] != roots[p][1] ||
664d89e6e46SMatthew G. Knepley         leavesRanks[p][2] != rootsRanks[p][2] || leaves[p][2] != roots[p][2] ||
665d89e6e46SMatthew G. Knepley         leavesRanks[p][3] != rootsRanks[p][3] || leaves[p][3] != roots[p][3]) {
666d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
667d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
668d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
669d89e6e46SMatthew G. Knepley 
67027d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
671d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
6729dddd249SSatish Balay           mainCone[c] = leaves[p][c];
67327d0e99aSVaclav Hapla           continue;
67427d0e99aSVaclav Hapla         }
675f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
676f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
6779566063dSJacob Faibussowitsch         PetscCall(PetscFindMPIInt((PetscMPIInt) leavesRanks[p][c], nranks, ranks, &r));
67863a3b9bcSJacob Faibussowitsch         PetscCheck(r >= 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " cone[%" PetscInt_FMT "]=%" PetscInt_FMT " root (%d,%" PetscInt_FMT ") leaf (%d,%" PetscInt_FMT "): leaf rank not found among remote ranks", p, c, cone[c], rootsRanks[p][c], roots[p][c], leavesRanks[p][c], leaves[p][c]);
6791dca8a05SBarry Smith         PetscCheck(ranks[r] >= 0 && ranks[r] < size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%" PetscInt_FMT " c=%" PetscInt_FMT " commsize=%d: ranks[%" PetscInt_FMT "] = %d makes no sense", p, c, size, r, ranks[r]);
680f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
681d89e6e46SMatthew G. Knepley         rS = roffset[r];
682d89e6e46SMatthew G. Knepley         rN = roffset[r+1] - rS;
6839566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
68463a3b9bcSJacob Faibussowitsch         PetscCheck(ind0 >= 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " cone[%" PetscInt_FMT "]=%" PetscInt_FMT " root (%d,%" PetscInt_FMT ") leave (%d,%" PetscInt_FMT "): corresponding remote point not found - it seems there is missing connection in point SF!", p, c, cone[c], rootsRanks[p][c], roots[p][c], leavesRanks[p][c], leaves[p][c]);
685f80536cbSVaclav Hapla         /* Get the corresponding local point */
6865f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
687f80536cbSVaclav Hapla       }
68863a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, " mainCone=[%4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT "]\n", mainCone[0], mainCone[1], mainCone[2], mainCone[3]));
68927d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
6909566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
6919566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
6929566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
69323aaf07bSVaclav Hapla   }
69427d0e99aSVaclav Hapla   if (debug) {
6959566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
6969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
6972e745bdaSMatthew G. Knepley   }
6989566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
6999566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
7009566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
7012e745bdaSMatthew G. Knepley   PetscFunctionReturn(0);
7022e745bdaSMatthew G. Knepley }
7032e745bdaSMatthew G. Knepley 
7042e72742cSMatthew G. Knepley static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
7057bffde78SMichael Lange {
7062e72742cSMatthew G. Knepley   PetscInt       idx;
7072e72742cSMatthew G. Knepley   PetscMPIInt    rank;
7082e72742cSMatthew G. Knepley   PetscBool      flg;
7097bffde78SMichael Lange 
7107bffde78SMichael Lange   PetscFunctionBegin;
7119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
7122e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
7139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7149566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
71563a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
7169566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
7172e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7182e72742cSMatthew G. Knepley }
7192e72742cSMatthew G. Knepley 
7202e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
7212e72742cSMatthew G. Knepley {
7222e72742cSMatthew G. Knepley   PetscInt       idx;
7232e72742cSMatthew G. Knepley   PetscMPIInt    rank;
7242e72742cSMatthew G. Knepley   PetscBool      flg;
7252e72742cSMatthew G. Knepley 
7262e72742cSMatthew G. Knepley   PetscFunctionBegin;
7279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
7282e72742cSMatthew G. Knepley   if (!flg) PetscFunctionReturn(0);
7299566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7309566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
7312e72742cSMatthew G. Knepley   if (idxname) {
73263a3b9bcSJacob Faibussowitsch     for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " rank %" PetscInt_FMT " index %" PetscInt_FMT "\n", rank, idxname, idx, a[idx].rank, a[idx].index));
7332e72742cSMatthew G. Knepley   } else {
73463a3b9bcSJacob Faibussowitsch     for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]rank %" PetscInt_FMT " index %" PetscInt_FMT "\n", rank, a[idx].rank, a[idx].index));
7352e72742cSMatthew G. Knepley   }
7369566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
7372e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7382e72742cSMatthew G. Knepley }
7392e72742cSMatthew G. Knepley 
7405f80ce2aSJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
7412e72742cSMatthew G. Knepley {
7423be36e83SMatthew G. Knepley   PetscSF         sf;
7433be36e83SMatthew G. Knepley   const PetscInt *locals;
7443be36e83SMatthew G. Knepley   PetscMPIInt     rank;
7452e72742cSMatthew G. Knepley 
7462e72742cSMatthew G. Knepley   PetscFunctionBegin;
7479566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
7489566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
7499566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
7505f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
7512e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
7522e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
7532e72742cSMatthew G. Knepley   } else {
7542e72742cSMatthew G. Knepley     PetscHashIJKey key;
7553be36e83SMatthew G. Knepley     PetscInt       l;
7562e72742cSMatthew G. Knepley 
7572e72742cSMatthew G. Knepley     key.i = remotePoint.index;
7582e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
7599566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
7603be36e83SMatthew G. Knepley     if (l >= 0) {
7613be36e83SMatthew G. Knepley       *localPoint = locals[l];
7625f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
7632e72742cSMatthew G. Knepley   }
7642e72742cSMatthew G. Knepley   PetscFunctionReturn(0);
7652e72742cSMatthew G. Knepley }
7662e72742cSMatthew G. Knepley 
7675f80ce2aSJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
7683be36e83SMatthew G. Knepley {
7693be36e83SMatthew G. Knepley   PetscSF            sf;
7703be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
7713be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
7723be36e83SMatthew G. Knepley   PetscInt           Nl, l;
7733be36e83SMatthew G. Knepley   PetscMPIInt        rank;
7743be36e83SMatthew G. Knepley 
7753be36e83SMatthew G. Knepley   PetscFunctionBegin;
7765f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
7779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
7789566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
7799566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
7803be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
7819566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
7829566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
7833be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
7849566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
7855f80ce2aSJacob Faibussowitsch   if (l < 0) {if (mapFailed) *mapFailed = PETSC_TRUE;}
7865f80ce2aSJacob Faibussowitsch   else *remotePoint = remotes[l];
7873be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
7883be36e83SMatthew G. Knepley   owned:
7893be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
7903be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
7913be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
7923be36e83SMatthew G. Knepley }
7933be36e83SMatthew G. Knepley 
7943be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
7953be36e83SMatthew G. Knepley {
7963be36e83SMatthew G. Knepley   PetscSF         sf;
7973be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
7983be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
7993be36e83SMatthew G. Knepley 
8003be36e83SMatthew G. Knepley   PetscFunctionBegin;
8013be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
8029566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
8039566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
8043be36e83SMatthew G. Knepley   if (Nl < 0) PetscFunctionReturn(0);
8059566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
8063be36e83SMatthew G. Knepley   if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);}
8079566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
8089566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
8093be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
8103be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8113be36e83SMatthew G. Knepley }
8123be36e83SMatthew G. Knepley 
8133be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
8143be36e83SMatthew G. Knepley {
8153be36e83SMatthew G. Knepley   const PetscInt *cone;
8163be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
8173be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
8183be36e83SMatthew G. Knepley 
8193be36e83SMatthew G. Knepley   PetscFunctionBegin;
8209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
8223be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
8233be36e83SMatthew G. Knepley     PetscBool pointShared;
8243be36e83SMatthew G. Knepley 
8259566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
8263be36e83SMatthew G. Knepley     cShared = (PetscBool) (cShared && pointShared);
8273be36e83SMatthew G. Knepley   }
8283be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
8293be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8303be36e83SMatthew G. Knepley }
8313be36e83SMatthew G. Knepley 
8323be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
8333be36e83SMatthew G. Knepley {
8343be36e83SMatthew G. Knepley   const PetscInt *cone;
8353be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
8363be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
8373be36e83SMatthew G. Knepley 
8383be36e83SMatthew G. Knepley   PetscFunctionBegin;
8399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
8413be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
8423be36e83SMatthew G. Knepley     PetscSFNode rcp;
8435f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
8443be36e83SMatthew G. Knepley 
8459566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
8465f80ce2aSJacob Faibussowitsch     if (mapFailed) {
8473be36e83SMatthew G. Knepley       cmin = missing;
8483be36e83SMatthew G. Knepley     } else {
8493be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
8503be36e83SMatthew G. Knepley     }
8513be36e83SMatthew G. Knepley   }
8523be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
8533be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
8543be36e83SMatthew G. Knepley }
8553be36e83SMatthew G. Knepley 
8563be36e83SMatthew G. Knepley /*
8573be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
8583be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
8593be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
8603be36e83SMatthew G. Knepley */
8613be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
8623be36e83SMatthew G. Knepley {
8633be36e83SMatthew G. Knepley   MPI_Comm        comm;
8643be36e83SMatthew G. Knepley   const PetscInt *support;
865cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
8663be36e83SMatthew G. Knepley   PetscMPIInt     rank;
8673be36e83SMatthew G. Knepley 
8683be36e83SMatthew G. Knepley   PetscFunctionBegin;
8699566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
8709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
8729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
8739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
874cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight+1) {
875cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
87663a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Skipping face %" PetscInt_FMT " to avoid adding cell to hashmap since this is nonoverlapping mesh\n", rank, p));
877cf4dc471SVaclav Hapla     PetscFunctionReturn(0);
878cf4dc471SVaclav Hapla   }
8799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
8809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
8819566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
8823be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
8833be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
8843be36e83SMatthew G. Knepley     const PetscInt *cone;
8853be36e83SMatthew G. Knepley     PetscSFNode     cpmin={-1,-1}, rp={-1,-1};
8863be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
8873be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
8883be36e83SMatthew G. Knepley     PetscHashIJKey  key;
8893be36e83SMatthew G. Knepley 
8903be36e83SMatthew G. Knepley     /* Only add point once */
89163a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
8923be36e83SMatthew G. Knepley     key.i = p;
8933be36e83SMatthew G. Knepley     key.j = face;
8949566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
8953be36e83SMatthew G. Knepley     if (f >= 0) continue;
8969566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
8979566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
8989566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
8993be36e83SMatthew G. Knepley     if (debug) {
90063a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int) isShared));
90163a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Global point (%" PetscInt_FMT ", %" PetscInt_FMT ") Min Cone Point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index));
9023be36e83SMatthew G. Knepley     }
9033be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
9049566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
9053be36e83SMatthew G. Knepley       if (candidates) {
90663a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
9079566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
9089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
9093be36e83SMatthew G. Knepley         candidates[off+idx].rank    = -1;
9103be36e83SMatthew G. Knepley         candidates[off+idx++].index = coneSize-1;
9113be36e83SMatthew G. Knepley         candidates[off+idx].rank    = rank;
9123be36e83SMatthew G. Knepley         candidates[off+idx++].index = face;
9133be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
9143be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
9153be36e83SMatthew G. Knepley 
9163be36e83SMatthew G. Knepley           if (cp == p) continue;
9179566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx], NULL));
91863a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off+idx].rank, candidates[off+idx].index));
9193be36e83SMatthew G. Knepley           ++idx;
9203be36e83SMatthew G. Knepley         }
9219566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
9223be36e83SMatthew G. Knepley       } else {
9233be36e83SMatthew G. Knepley         /* Add cone size to section */
92463a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
9259566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
9269566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
9279566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize+1));
9283be36e83SMatthew G. Knepley       }
9293be36e83SMatthew G. Knepley     }
9303be36e83SMatthew G. Knepley   }
9313be36e83SMatthew G. Knepley   PetscFunctionReturn(0);
9323be36e83SMatthew G. Knepley }
9333be36e83SMatthew G. Knepley 
9342e72742cSMatthew G. Knepley /*@
9352e72742cSMatthew G. Knepley   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation
9362e72742cSMatthew G. Knepley 
937d083f849SBarry Smith   Collective on dm
9382e72742cSMatthew G. Knepley 
9392e72742cSMatthew G. Knepley   Input Parameters:
9402e72742cSMatthew G. Knepley + dm      - The interpolated DM
9412e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points
9422e72742cSMatthew G. Knepley 
9432e72742cSMatthew G. Knepley   Output Parameter:
9442e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points
9452e72742cSMatthew G. Knepley 
946f0cfc026SVaclav Hapla   Level: developer
9472e72742cSMatthew G. Knepley 
9482e72742cSMatthew G. Knepley    Note: All debugging for this process can be turned on with the options: -dm_interp_pre_view -petscsf_interp_pre_view -petscsection_interp_candidate_view -petscsection_interp_candidate_remote_view -petscsection_interp_claim_view -petscsf_interp_pre_view -dmplex_interp_debug
9492e72742cSMatthew G. Knepley 
950db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexUninterpolate()`
9512e72742cSMatthew G. Knepley @*/
952e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
9532e72742cSMatthew G. Knepley {
9543be36e83SMatthew G. Knepley   MPI_Comm           comm;
9553be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
9563be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
9573be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
9583be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
9592e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
9602e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
9613be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
9623be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
9633be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
964f0cfc026SVaclav Hapla   PetscMPIInt        rank;
9652e72742cSMatthew G. Knepley 
9662e72742cSMatthew G. Knepley   PetscFunctionBegin;
967f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
968064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
9699566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
970f0cfc026SVaclav Hapla   if (!flg) PetscFunctionReturn(0);
9713be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
9729566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
9739566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
9749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
97628b400f6SJacob Faibussowitsch   PetscCheck(!ov,comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
9779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug));
9789566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view"));
9799566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view"));
9809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0));
9813be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
9829566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
98308401ef6SPierre Jolivet   PetscCheck(Nr >= 0,comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
9849566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
9853be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
9863be36e83SMatthew G. Knepley     PetscHashIJKey key;
9872e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
9882e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
9899566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
9907bffde78SMichael Lange   }
99166aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
9929566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
9939566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9949566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
9953be36e83SMatthew G. Knepley   /*
9963be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
9973be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
9983be36e83SMatthew G. Knepley   \begin{itemize}
9993be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
10003be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
10013be36e83SMatthew G. Knepley   \end{itemize}
10023be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
10033be36e83SMatthew G. Knepley   \item At the root, if at least two faces with a given cone are present, including a local face, mark the face as shared \label{alg:rootStep} and choose the root face
10043be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
10053be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
10063be36e83SMatthew G. Knepley   */
10073be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
10083be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
10093be36e83SMatthew G. Knepley        The array holds candidate shared faces, each face is refered to by the leaf point */
10109566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
10119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
10127bffde78SMichael Lange   {
10133be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
10142e72742cSMatthew G. Knepley 
10159566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
10163be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
10173be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
10182e72742cSMatthew G. Knepley 
101963a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
10209566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
10212e72742cSMatthew G. Knepley     }
10229566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
10239566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
10249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
10259566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
10263be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
10273be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
10282e72742cSMatthew G. Knepley 
102963a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
10309566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
10312e72742cSMatthew G. Knepley     }
10329566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
10339566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
10347bffde78SMichael Lange   }
10359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) candidateSection, "Candidate Section"));
10369566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view"));
10379566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
10383be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
10392e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
10407bffde78SMichael Lange   {
10417bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
10427bffde78SMichael Lange     PetscInt *remoteOffsets;
10432e72742cSMatthew G. Knepley 
10449566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
10459566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
10469566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
10479566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
10489566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
10499566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
10509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
10519566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE));
10529566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE));
10539566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
10549566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
10559566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
10562e72742cSMatthew G. Knepley 
10579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section"));
10589566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
10599566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
10607bffde78SMichael Lange   }
10613be36e83SMatthew G. Knepley   /* Step 3: At the root, if at least two faces with a given cone are present, including a local face, mark the face as shared and choose the root face */
10627bffde78SMichael Lange   {
10633be36e83SMatthew G. Knepley     PetscHashIJKLRemote faceTable;
10643be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
10653be36e83SMatthew G. Knepley 
10669566063dSJacob Faibussowitsch     PetscCall(PetscHashIJKLRemoteCreate(&faceTable));
10672e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
10683be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
10692e72742cSMatthew G. Knepley       PetscInt deg;
10703be36e83SMatthew G. Knepley 
10712e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
10722e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
10732e72742cSMatthew G. Knepley 
10749566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
10759566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
10763be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
10772e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
10783be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
10793be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
10803be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx+1];
10813be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
10823be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
10833be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
10842e72742cSMatthew G. Knepley           const PetscInt        *join  = NULL;
10853be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
10863be36e83SMatthew G. Knepley           PetscHashIter          iter;
10875f80ce2aSJacob Faibussowitsch           PetscBool              missing,mapToLocalPointFailed = PETSC_FALSE;
10882e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
10892e72742cSMatthew G. Knepley 
109063a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Checking face (%" PetscInt_FMT ", %" PetscInt_FMT ") at (%" PetscInt_FMT ", %" PetscInt_FMT ", %" PetscInt_FMT ") with cone size %" PetscInt_FMT "\n", rank, rface.rank, rface.index, r, idx, d, Np));
109163a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle face (%" PetscInt_FMT ", %" PetscInt_FMT ") at (%" PetscInt_FMT ", %" PetscInt_FMT ", %" PetscInt_FMT ") with %" PetscInt_FMT " cone points", rface.rank, rface.index, r, idx, d, Np);
10923be36e83SMatthew G. Knepley           fcp0.rank  = rank;
10933be36e83SMatthew G. Knepley           fcp0.index = r;
10943be36e83SMatthew G. Knepley           d += Np;
10953be36e83SMatthew G. Knepley           /* Put remote face in hash table */
10963be36e83SMatthew G. Knepley           key.i = fcp0;
10973be36e83SMatthew G. Knepley           key.j = fcone[0];
10983be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
10993be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
11009566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *) &key));
11019566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing));
11023be36e83SMatthew G. Knepley           if (missing) {
110363a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
11049566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface));
11053be36e83SMatthew G. Knepley           } else {
11063be36e83SMatthew G. Knepley             PetscSFNode oface;
11073be36e83SMatthew G. Knepley 
11089566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface));
11093be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
111063a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
11119566063dSJacob Faibussowitsch               PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface));
11123be36e83SMatthew G. Knepley             }
11133be36e83SMatthew G. Knepley           }
11143be36e83SMatthew G. Knepley           /* Check for local face */
11152e72742cSMatthew G. Knepley           points[0] = r;
11163be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
11179566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p], &mapToLocalPointFailed));
11185f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
111963a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
11207bffde78SMichael Lange           }
11215f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
11229566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
11237bffde78SMichael Lange           if (joinSize == 1) {
11243be36e83SMatthew G. Knepley             PetscSFNode lface;
11253be36e83SMatthew G. Knepley             PetscSFNode oface;
11263be36e83SMatthew G. Knepley 
11273be36e83SMatthew G. Knepley             /* Always replace with local face */
11283be36e83SMatthew G. Knepley             lface.rank  = rank;
11293be36e83SMatthew G. Knepley             lface.index = join[0];
11309566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface));
113163a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Replacing (%" PetscInt_FMT ", %" PetscInt_FMT ") with local face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, oface.index, oface.rank, lface.index, lface.rank));
11329566063dSJacob Faibussowitsch             PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, lface));
11337bffde78SMichael Lange           }
11349566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
11353be36e83SMatthew G. Knepley         }
11363be36e83SMatthew G. Knepley       }
11373be36e83SMatthew G. Knepley       /* Put back faces for this root */
11383be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
11393be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
11403be36e83SMatthew G. Knepley 
11419566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
11429566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
11433be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
11443be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11453be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset+d;
11463be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index+1;
11473be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx+2];
11483be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
11493be36e83SMatthew G. Knepley           const PetscSFNode      pmax  = {PETSC_MAX_INT, PETSC_MAX_INT};
11503be36e83SMatthew G. Knepley           PetscHashIJKLRemoteKey key;
11513be36e83SMatthew G. Knepley           PetscHashIter          iter;
11523be36e83SMatthew G. Knepley           PetscBool              missing;
11533be36e83SMatthew G. Knepley 
115463a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
115563a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
11563be36e83SMatthew G. Knepley           fcp0.rank  = rank;
11573be36e83SMatthew G. Knepley           fcp0.index = r;
11583be36e83SMatthew G. Knepley           d += Np;
11593be36e83SMatthew G. Knepley           /* Find remote face in hash table */
11603be36e83SMatthew G. Knepley           key.i = fcp0;
11613be36e83SMatthew G. Knepley           key.j = fcone[0];
11623be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
11633be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
11649566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *) &key));
116563a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d]    key (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index));
11669566063dSJacob Faibussowitsch           PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing));
116763a3b9bcSJacob Faibussowitsch           PetscCheck(!missing,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
11689566063dSJacob Faibussowitsch           else        PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
11697bffde78SMichael Lange         }
11707bffde78SMichael Lange       }
11717bffde78SMichael Lange     }
11729566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL));
11739566063dSJacob Faibussowitsch     PetscCall(PetscHashIJKLRemoteDestroy(&faceTable));
11747bffde78SMichael Lange   }
11753be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
11767bffde78SMichael Lange   {
11777bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
11787bffde78SMichael Lange     PetscSFNode *remotePointsNew;
11792e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
11803be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
11812e72742cSMatthew G. Knepley 
11823be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
11839566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
11849566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
11859566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
11869566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
11879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
11889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
11893be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
11909566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE));
11919566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE));
11929566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
11939566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
11949566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) claimSection, "Claim Section"));
11959566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view"));
11969566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
11973be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
11983be36e83SMatthew G. Knepley     /* TODO I should not have to do a join here since I already put the face and its cone in the candidate section */
11999566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
12003be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
12013be36e83SMatthew G. Knepley       PetscInt dof, off, d;
12022e72742cSMatthew G. Knepley 
120363a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
12049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
12059566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
12062e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
12073be36e83SMatthew G. Knepley         if (claims[off+d].rank >= 0) {
12083be36e83SMatthew G. Knepley           const PetscInt  faceInd = off+d;
12093be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off+d].index;
12102e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
12112e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
12122e72742cSMatthew G. Knepley 
121363a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
12143be36e83SMatthew G. Knepley           points[0] = r;
121563a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
12163be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
12179566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1], NULL));
121863a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c+1]));
12192e72742cSMatthew G. Knepley           }
12209566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np+1, points, &joinSize, &join));
12212e72742cSMatthew G. Knepley           if (joinSize == 1) {
12223be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
122363a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
12243be36e83SMatthew G. Knepley             } else {
122563a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
12269566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
12272e72742cSMatthew G. Knepley             }
12283be36e83SMatthew G. Knepley           } else {
12299566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
12303be36e83SMatthew G. Knepley           }
12319566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join));
12323be36e83SMatthew G. Knepley         } else {
123363a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
12343be36e83SMatthew G. Knepley           d += claims[off+d].index+1;
12357bffde78SMichael Lange         }
12367bffde78SMichael Lange       }
12373be36e83SMatthew G. Knepley     }
12389566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
12393be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
12409566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
12419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
12429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
12439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
12443be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
12453be36e83SMatthew G. Knepley       localPointsNew[l] = localPoints[l];
12463be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
12473be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
12487bffde78SMichael Lange     }
12493be36e83SMatthew G. Knepley     p = Nl;
12509566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
12513be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
12529566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(NlNew, &localPointsNew[Nl]));
12533be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
12543be36e83SMatthew G. Knepley       PetscInt off;
12559566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
12561dca8a05SBarry Smith       PetscCheck(claims[off].rank >= 0 && claims[off].index >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %" PetscInt_FMT ", (%" PetscInt_FMT ", %" PetscInt_FMT ")", localPointsNew[p], claims[off].rank, claims[off].index);
12573be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
12587bffde78SMichael Lange     }
12599566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
12609566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
12619566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
12629566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
12639566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view"));
12649566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
12659566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
12667bffde78SMichael Lange   }
12679566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
12689566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
12699566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
12709566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
12719566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
12729566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
12739566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
12749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0));
12757bffde78SMichael Lange   PetscFunctionReturn(0);
12767bffde78SMichael Lange }
12777bffde78SMichael Lange 
1278248eb259SVaclav Hapla /*@
127980330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
128080330477SMatthew G. Knepley 
1281d083f849SBarry Smith   Collective on dm
128280330477SMatthew G. Knepley 
1283e56d480eSMatthew G. Knepley   Input Parameters:
1284e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices
128510a67516SMatthew G. Knepley - dmInt - The interpolated DM
128680330477SMatthew G. Knepley 
128780330477SMatthew G. Knepley   Output Parameter:
12884e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object
128980330477SMatthew G. Knepley 
129080330477SMatthew G. Knepley   Level: intermediate
129180330477SMatthew G. Knepley 
129295452b02SPatrick Sanan   Notes:
12937fb59074SVaclav Hapla     Labels and coordinates are copied.
129443eeeb2dSStefano Zampini 
12959ade3219SVaclav Hapla   Developer Notes:
12969ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL.
12979ade3219SVaclav Hapla 
1298db781477SPatrick Sanan .seealso: `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
129980330477SMatthew G. Knepley @*/
13009f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
13019f074e33SMatthew G Knepley {
1302a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
13039a5b13a2SMatthew G Knepley   DM             idm, odm = dm;
13047bffde78SMichael Lange   PetscSF        sfPoint;
13052e1b13c2SMatthew G. Knepley   PetscInt       depth, dim, d;
130610a67516SMatthew G. Knepley   const char    *name;
1307b325530aSVaclav Hapla   PetscBool      flg=PETSC_TRUE;
13089f074e33SMatthew G Knepley 
13099f074e33SMatthew G Knepley   PetscFunctionBegin;
131010a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
131110a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
13129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0));
13139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
13149566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
13159566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
131608401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1317827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
13189566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) dm));
131976b791aaSMatthew G. Knepley     idm  = dm;
1320b21b8912SMatthew G. Knepley   } else {
13219a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
13229a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
13239566063dSJacob Faibussowitsch       PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
13249566063dSJacob Faibussowitsch       PetscCall(DMSetType(idm, DMPLEX));
13259566063dSJacob Faibussowitsch       PetscCall(DMSetDimension(idm, dim));
13267bffde78SMichael Lange       if (depth > 0) {
13279566063dSJacob Faibussowitsch         PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
13289566063dSJacob Faibussowitsch         PetscCall(DMGetPointSF(odm, &sfPoint));
132994488200SVaclav Hapla         {
13303be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
133194488200SVaclav Hapla           PetscInt nroots;
13329566063dSJacob Faibussowitsch           PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
13339566063dSJacob Faibussowitsch           if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
133494488200SVaclav Hapla         }
13357bffde78SMichael Lange       }
13369566063dSJacob Faibussowitsch       if (odm != dm) PetscCall(DMDestroy(&odm));
13379a5b13a2SMatthew G Knepley       odm = idm;
13389f074e33SMatthew G Knepley     }
13399566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm,  &name));
13409566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) idm,  name));
13419566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
13429566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
13439566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
13449566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
134584699f70SSatish Balay   }
1346827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1347827c4036SVaclav Hapla   {
1348d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) idm->data;
1349827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1350827c4036SVaclav Hapla   }
1351*5de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
13529a5b13a2SMatthew G Knepley   *dmInt = idm;
13539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0));
13549f074e33SMatthew G Knepley   PetscFunctionReturn(0);
13559f074e33SMatthew G Knepley }
135607b0a1fcSMatthew G Knepley 
135780330477SMatthew G. Knepley /*@
135880330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
135980330477SMatthew G. Knepley 
1360d083f849SBarry Smith   Collective on dmA
136180330477SMatthew G. Knepley 
136280330477SMatthew G. Knepley   Input Parameter:
136380330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates
136480330477SMatthew G. Knepley 
136580330477SMatthew G. Knepley   Output Parameter:
136680330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates
136780330477SMatthew G. Knepley 
136880330477SMatthew G. Knepley   Level: intermediate
136980330477SMatthew G. Knepley 
137080330477SMatthew G. Knepley   Note: This is typically used when adding pieces other than vertices to a mesh
137180330477SMatthew G. Knepley 
1372db781477SPatrick Sanan .seealso: `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
137380330477SMatthew G. Knepley @*/
137407b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
137507b0a1fcSMatthew G Knepley {
137607b0a1fcSMatthew G Knepley   Vec            coordinatesA, coordinatesB;
137743eeeb2dSStefano Zampini   VecType        vtype;
137807b0a1fcSMatthew G Knepley   PetscSection   coordSectionA, coordSectionB;
137907b0a1fcSMatthew G Knepley   PetscScalar   *coordsA, *coordsB;
13800bedd6beSMatthew G. Knepley   PetscInt       spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
138190a8aa44SJed Brown   PetscInt       cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
138243eeeb2dSStefano Zampini   PetscBool      lc = PETSC_FALSE;
138307b0a1fcSMatthew G Knepley 
138407b0a1fcSMatthew G Knepley   PetscFunctionBegin;
138543eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
138643eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
138776b791aaSMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
13889566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
13899566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
13909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
13919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
139263a3b9bcSJacob Faibussowitsch   PetscCheck((vEndA-vStartA) == (vEndB-vStartB),PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %" PetscInt_FMT " != %" PetscInt_FMT " in the second DM", vEndA-vStartA, vEndB-vStartB);
139361a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
139461a622f3SMatthew G. Knepley   {
139561a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
139661a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
139761a622f3SMatthew G. Knepley     PetscObject        objA, objB;
139861a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
139961a622f3SMatthew G. Knepley     const PetscScalar *constants;
140061a622f3SMatthew G. Knepley     PetscInt            cdim, Nc;
140161a622f3SMatthew G. Knepley 
14029566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
14039566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
14049566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
14059566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
14069566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
14079566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
140861a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
14099566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
14109566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
14119566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
14129566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
14139566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
14149566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
14159566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
14169566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *) constants));
141761a622f3SMatthew G. Knepley     }
141861a622f3SMatthew G. Knepley   }
14199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
14209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
14219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
14229566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
1423972bc18aSToby Isaac   if (coordSectionA == coordSectionB) PetscFunctionReturn(0);
14249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
14250bedd6beSMatthew G. Knepley   if (!Nf) PetscFunctionReturn(0);
142663a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1427df26b574SMatthew G. Knepley   if (!coordSectionB) {
1428df26b574SMatthew G. Knepley     PetscInt dim;
1429df26b574SMatthew G. Knepley 
14309566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB));
14319566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
14329566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
14339566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject) coordSectionB));
1434df26b574SMatthew G. Knepley   }
14359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
14369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
14379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
14389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
143943eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
144063a3b9bcSJacob Faibussowitsch     PetscCheck((cEndA-cStartA) == (cEndB-cStartB),PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %" PetscInt_FMT " != %" PetscInt_FMT " in the second DM", cEndA-cStartA, cEndB-cStartB);
144143eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
144243eeeb2dSStefano Zampini     cE = vEndB;
144343eeeb2dSStefano Zampini     lc = PETSC_TRUE;
144443eeeb2dSStefano Zampini   } else {
144543eeeb2dSStefano Zampini     cS = vStartB;
144643eeeb2dSStefano Zampini     cE = vEndB;
144743eeeb2dSStefano Zampini   }
14489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
144907b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
14509566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
14519566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
145207b0a1fcSMatthew G Knepley   }
145343eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
145443eeeb2dSStefano Zampini     PetscInt c;
145543eeeb2dSStefano Zampini 
145643eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
145743eeeb2dSStefano Zampini       PetscInt dof;
145843eeeb2dSStefano Zampini 
14599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
14609566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSectionB, c + cStartB, dof));
14619566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof));
146243eeeb2dSStefano Zampini     }
146343eeeb2dSStefano Zampini   }
14649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
14659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
14669566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
14679566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
14689566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) coordinatesB, "coordinates"));
14699566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
14709566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
14719566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
14729566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
14739566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
14749566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
14759566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
147607b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB-vStartB; ++v) {
147743eeeb2dSStefano Zampini     PetscInt offA, offB;
147843eeeb2dSStefano Zampini 
14799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
14809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
148107b0a1fcSMatthew G Knepley     for (d = 0; d < spaceDim; ++d) {
148243eeeb2dSStefano Zampini       coordsB[offB+d] = coordsA[offA+d];
148343eeeb2dSStefano Zampini     }
148443eeeb2dSStefano Zampini   }
148543eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
148643eeeb2dSStefano Zampini     PetscInt c;
148743eeeb2dSStefano Zampini 
148843eeeb2dSStefano Zampini     for (c = cS-cStartB; c < cEndB-cStartB; c++) {
148943eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
149043eeeb2dSStefano Zampini 
14919566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA));
14929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB));
14939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
14949566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(coordsB + offB,coordsA + offA,dof));
149507b0a1fcSMatthew G Knepley     }
149607b0a1fcSMatthew G Knepley   }
14979566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
14989566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
14999566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
15009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
150107b0a1fcSMatthew G Knepley   PetscFunctionReturn(0);
150207b0a1fcSMatthew G Knepley }
15035c386225SMatthew G. Knepley 
15044e3744c5SMatthew G. Knepley /*@
15054e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
15064e3744c5SMatthew G. Knepley 
1507d083f849SBarry Smith   Collective on dm
15084e3744c5SMatthew G. Knepley 
15094e3744c5SMatthew G. Knepley   Input Parameter:
15104e3744c5SMatthew G. Knepley . dm - The complete DMPlex object
15114e3744c5SMatthew G. Knepley 
15124e3744c5SMatthew G. Knepley   Output Parameter:
15134e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices
15144e3744c5SMatthew G. Knepley 
15154e3744c5SMatthew G. Knepley   Level: intermediate
15164e3744c5SMatthew G. Knepley 
151795452b02SPatrick Sanan   Notes:
151895452b02SPatrick Sanan     It does not copy over the coordinates.
151943eeeb2dSStefano Zampini 
15209ade3219SVaclav Hapla   Developer Notes:
15219ade3219SVaclav Hapla     It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
15229ade3219SVaclav Hapla 
1523db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
15244e3744c5SMatthew G. Knepley @*/
15254e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
15264e3744c5SMatthew G. Knepley {
1527827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
15284e3744c5SMatthew G. Knepley   DM             udm;
1529412e9a14SMatthew G. Knepley   PetscInt       dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
15304e3744c5SMatthew G. Knepley 
15314e3744c5SMatthew G. Knepley   PetscFunctionBegin;
153243eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
153343eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
15349566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
15359566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
153608401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1537827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1538827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
15399566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) dm));
1540595d4abbSMatthew G. Knepley     *dmUnint = dm;
1541595d4abbSMatthew G. Knepley     PetscFunctionReturn(0);
15424e3744c5SMatthew G. Knepley   }
15439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
15449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
15459566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject) dm), &udm));
15469566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
15479566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
15489566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
15494e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1550595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
15514e3744c5SMatthew G. Knepley 
15529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
15534e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
15544e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
15554e3744c5SMatthew G. Knepley 
15564e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
15574e3744c5SMatthew G. Knepley     }
15589566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
15599566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1560595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
15614e3744c5SMatthew G. Knepley   }
15629566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
15639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
15644e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1565595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
15664e3744c5SMatthew G. Knepley 
15679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
15684e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
15694e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
15704e3744c5SMatthew G. Knepley 
15714e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
15724e3744c5SMatthew G. Knepley     }
15739566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
15749566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
15754e3744c5SMatthew G. Knepley   }
15769566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
15779566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
15789566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
15795c7de58aSMatthew G. Knepley   /* Reduce SF */
15805c7de58aSMatthew G. Knepley   {
15815c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
15825c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
15835c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
15845c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
15855c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
15865c7de58aSMatthew G. Knepley     PetscInt           vEnd, numRoots, numLeaves, l;
15875c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
15885c7de58aSMatthew G. Knepley 
15895c7de58aSMatthew G. Knepley     /* Get original SF information */
15909566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
15919566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
15929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, NULL, &vEnd));
15939566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
15945c7de58aSMatthew G. Knepley     /* Allocate space for cells and vertices */
15955c7de58aSMatthew G. Knepley     for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++;
15965c7de58aSMatthew G. Knepley     /* Fill in leaves */
15975c7de58aSMatthew G. Knepley     if (vEnd >= 0) {
15989566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
15999566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
16005c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
16015c7de58aSMatthew G. Knepley         if (localPoints[l] < vEnd) {
16025c7de58aSMatthew G. Knepley           localPointsUn[n]        = localPoints[l];
16035c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
16045c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
16055c7de58aSMatthew G. Knepley           ++n;
16065c7de58aSMatthew G. Knepley         }
16075c7de58aSMatthew G. Knepley       }
160863a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
16099566063dSJacob Faibussowitsch       PetscCall(PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
16105c7de58aSMatthew G. Knepley     }
16115c7de58aSMatthew G. Knepley   }
1612827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1613827c4036SVaclav Hapla   {
1614d6e9e4f7SVaclav Hapla     DM_Plex *plex = (DM_Plex *) udm->data;
1615827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1616827c4036SVaclav Hapla   }
1617*5de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
16184e3744c5SMatthew G. Knepley   *dmUnint = udm;
16194e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
16204e3744c5SMatthew G. Knepley }
1621a7748839SVaclav Hapla 
1622a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1623a7748839SVaclav Hapla {
1624a7748839SVaclav Hapla   PetscInt       coneSize, depth, dim, h, p, pStart, pEnd;
1625a7748839SVaclav Hapla   MPI_Comm       comm;
1626a7748839SVaclav Hapla 
1627a7748839SVaclav Hapla   PetscFunctionBegin;
16289566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
16299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
16309566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1631a7748839SVaclav Hapla 
1632a7748839SVaclav Hapla   if (depth == dim) {
1633a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1634a7748839SVaclav Hapla     if (!dim) goto finish;
1635a7748839SVaclav Hapla 
1636a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
16379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1638a7748839SVaclav Hapla     for (p=pStart; p<pEnd; p++) {
16399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1640a7748839SVaclav Hapla       if (coneSize) {
1641a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1642a7748839SVaclav Hapla         goto finish;
1643a7748839SVaclav Hapla       }
1644a7748839SVaclav Hapla     }
1645a7748839SVaclav Hapla 
1646a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1647a7748839SVaclav Hapla     for (h=0; h<dim; h++) {
16489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1649a7748839SVaclav Hapla       for (p=pStart; p<pEnd; p++) {
16509566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1651a7748839SVaclav Hapla         if (!coneSize) {
1652a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1653a7748839SVaclav Hapla           goto finish;
1654a7748839SVaclav Hapla         }
1655a7748839SVaclav Hapla       }
1656a7748839SVaclav Hapla     }
1657a7748839SVaclav Hapla   } else if (depth == 1) {
1658a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1659a7748839SVaclav Hapla   } else {
1660a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1661a7748839SVaclav Hapla   }
1662a7748839SVaclav Hapla finish:
1663a7748839SVaclav Hapla   PetscFunctionReturn(0);
1664a7748839SVaclav Hapla }
1665a7748839SVaclav Hapla 
1666a7748839SVaclav Hapla /*@
16679ade3219SVaclav Hapla   DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated.
1668a7748839SVaclav Hapla 
1669a7748839SVaclav Hapla   Not Collective
1670a7748839SVaclav Hapla 
1671a7748839SVaclav Hapla   Input Parameter:
1672a7748839SVaclav Hapla . dm      - The DM object
1673a7748839SVaclav Hapla 
1674a7748839SVaclav Hapla   Output Parameter:
1675a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1676a7748839SVaclav Hapla 
1677a7748839SVaclav Hapla   Level: intermediate
1678a7748839SVaclav Hapla 
1679a7748839SVaclav Hapla   Notes:
16809ade3219SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this is NOT collective
16819ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
1682a7748839SVaclav Hapla   However, DMPlexInterpolate() guarantees the result is the same on all.
16839ade3219SVaclav Hapla 
1684a7748839SVaclav Hapla   Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED.
1685a7748839SVaclav Hapla 
16869ade3219SVaclav Hapla   Developer Notes:
16879ade3219SVaclav Hapla   Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID.
16889ade3219SVaclav Hapla 
16899ade3219SVaclav Hapla   If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called.
16909ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
16919ade3219SVaclav Hapla   DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL.
16929ade3219SVaclav Hapla 
16939ade3219SVaclav Hapla   If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated.
16949ade3219SVaclav Hapla 
16959ade3219SVaclav Hapla   DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL,
16969ade3219SVaclav Hapla   and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE.
16979ade3219SVaclav Hapla 
1698db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1699a7748839SVaclav Hapla @*/
1700a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1701a7748839SVaclav Hapla {
1702a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1703a7748839SVaclav Hapla 
1704a7748839SVaclav Hapla   PetscFunctionBegin;
1705a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1706a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
1707a7748839SVaclav Hapla   if (plex->interpolated < 0) {
17089566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
170976bd3646SJed Brown   } else if (PetscDefined (USE_DEBUG)) {
1710a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1711a7748839SVaclav Hapla 
17129566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
171308401ef6SPierre Jolivet     PetscCheck(flg == plex->interpolated,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1714a7748839SVaclav Hapla   }
1715a7748839SVaclav Hapla   *interpolated = plex->interpolated;
1716a7748839SVaclav Hapla   PetscFunctionReturn(0);
1717a7748839SVaclav Hapla }
1718a7748839SVaclav Hapla 
1719a7748839SVaclav Hapla /*@
17209ade3219SVaclav Hapla   DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner).
1721a7748839SVaclav Hapla 
17222666ff3cSVaclav Hapla   Collective
1723a7748839SVaclav Hapla 
1724a7748839SVaclav Hapla   Input Parameter:
1725a7748839SVaclav Hapla . dm      - The DM object
1726a7748839SVaclav Hapla 
1727a7748839SVaclav Hapla   Output Parameter:
1728a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated
1729a7748839SVaclav Hapla 
1730a7748839SVaclav Hapla   Level: intermediate
1731a7748839SVaclav Hapla 
1732a7748839SVaclav Hapla   Notes:
17339ade3219SVaclav Hapla   Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks.
17349ade3219SVaclav Hapla 
17359ade3219SVaclav Hapla   This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks.
17369ade3219SVaclav Hapla 
17379ade3219SVaclav Hapla   Developer Notes:
17389ade3219SVaclav Hapla   Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID.
17399ade3219SVaclav Hapla 
17409ade3219SVaclav Hapla   If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated.
17419ade3219SVaclav Hapla   MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
17429ade3219SVaclav Hapla   if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED,
17439ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
17449ade3219SVaclav Hapla 
17459ade3219SVaclav Hapla   If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective.
1746a7748839SVaclav Hapla 
1747db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
1748a7748839SVaclav Hapla @*/
1749a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1750a7748839SVaclav Hapla {
1751a7748839SVaclav Hapla   DM_Plex        *plex = (DM_Plex *) dm->data;
1752a7748839SVaclav Hapla   PetscBool       debug=PETSC_FALSE;
1753a7748839SVaclav Hapla 
1754a7748839SVaclav Hapla   PetscFunctionBegin;
1755a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1756a7748839SVaclav Hapla   PetscValidPointer(interpolated,2);
17579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
1758a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1759a7748839SVaclav Hapla     DMPlexInterpolatedFlag  min, max;
1760a7748839SVaclav Hapla     MPI_Comm                comm;
1761a7748839SVaclav Hapla 
17629566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
17639566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
17649566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
17659566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
1766a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1767a7748839SVaclav Hapla     if (debug) {
1768a7748839SVaclav Hapla       PetscMPIInt rank;
1769a7748839SVaclav Hapla 
17709566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
17719566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
17729566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
1773a7748839SVaclav Hapla     }
1774a7748839SVaclav Hapla   }
1775a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
1776a7748839SVaclav Hapla   PetscFunctionReturn(0);
1777a7748839SVaclav Hapla }
1778