xref: /petsc/src/dm/impls/plex/plexinterpolate.c (revision 172ee2662f600bbadcf24cd1159ee4392d8f8483)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I      "petscdmplex.h"   I*/
2e8f14785SLisandro Dalcin #include <petsc/private/hashmapi.h>
3e8f14785SLisandro Dalcin #include <petsc/private/hashmapij.h>
4e8f14785SLisandro Dalcin 
5ea78f98cSLisandro Dalcin const char *const DMPlexInterpolatedFlags[] = {"none", "partial", "mixed", "full", "DMPlexInterpolatedFlag", "DMPLEX_INTERPOLATED_", NULL};
6a7748839SVaclav Hapla 
7a03d55ffSStefano Zampini /* HMapIJKL */
8e8f14785SLisandro Dalcin 
9a03d55ffSStefano Zampini #include <petsc/private/hashmapijkl.h>
10e8f14785SLisandro Dalcin 
113be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1};
123be36e83SMatthew G. Knepley 
13a03d55ffSStefano Zampini typedef struct _PetscHMapIJKLRemoteKey {
149371c9d4SSatish Balay   PetscSFNode i, j, k, l;
15a03d55ffSStefano Zampini } PetscHMapIJKLRemoteKey;
163be36e83SMatthew G. Knepley 
17a03d55ffSStefano Zampini #define PetscHMapIJKLRemoteKeyHash(key) \
189371c9d4SSatish Balay   PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index), PetscHashInt((key).j.rank + (key).j.index)), PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index), PetscHashInt((key).l.rank + (key).l.index)))
193be36e83SMatthew G. Knepley 
20a03d55ffSStefano Zampini #define PetscHMapIJKLRemoteKeyEqual(k1, k2) \
213be36e83SMatthew G. Knepley   (((k1).i.rank == (k2).i.rank) ? ((k1).i.index == (k2).i.index) ? ((k1).j.rank == (k2).j.rank) ? ((k1).j.index == (k2).j.index) ? ((k1).k.rank == (k2).k.rank) ? ((k1).k.index == (k2).k.index) ? ((k1).l.rank == (k2).l.rank) ? ((k1).l.index == (k2).l.index) : 0 : 0 : 0 : 0 : 0 : 0 : 0)
223be36e83SMatthew G. Knepley 
23a03d55ffSStefano Zampini PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HMapIJKLRemote, PetscHMapIJKLRemoteKey, PetscSFNode, PetscHMapIJKLRemoteKeyHash, PetscHMapIJKLRemoteKeyEqual, _PetscInvalidSFNode))
243be36e83SMatthew G. Knepley 
25d71ae5a4SJacob Faibussowitsch   static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[])
26d71ae5a4SJacob Faibussowitsch {
273be36e83SMatthew G. Knepley   PetscInt i;
283be36e83SMatthew G. Knepley 
293be36e83SMatthew G. Knepley   PetscFunctionBegin;
303be36e83SMatthew G. Knepley   for (i = 1; i < n; ++i) {
313be36e83SMatthew G. Knepley     PetscSFNode x = A[i];
323be36e83SMatthew G. Knepley     PetscInt    j;
333be36e83SMatthew G. Knepley 
343be36e83SMatthew G. Knepley     for (j = i - 1; j >= 0; --j) {
353be36e83SMatthew G. Knepley       if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break;
363be36e83SMatthew G. Knepley       A[j + 1] = A[j];
373be36e83SMatthew G. Knepley     }
383be36e83SMatthew G. Knepley     A[j + 1] = x;
393be36e83SMatthew G. Knepley   }
403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
413be36e83SMatthew G. Knepley }
429f074e33SMatthew G Knepley 
439f074e33SMatthew G Knepley /*
44439ece16SMatthew G. Knepley   DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone
45439ece16SMatthew G. Knepley */
46d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
47d71ae5a4SJacob Faibussowitsch {
48412e9a14SMatthew G. Knepley   DMPolytopeType *typesTmp;
49412e9a14SMatthew G. Knepley   PetscInt       *sizesTmp, *facesTmp;
50439ece16SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize;
51439ece16SMatthew G. Knepley 
52439ece16SMatthew G. Knepley   PetscFunctionBegin;
53439ece16SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54ba2698f1SMatthew G. Knepley   if (cone) PetscValidIntPointer(cone, 3);
559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
569566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &typesTmp));
579566063dSJacob Faibussowitsch   if (faceSizes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &sizesTmp));
589566063dSJacob Faibussowitsch   if (faces) PetscCall(DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp));
59ba2698f1SMatthew G. Knepley   switch (ct) {
60ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_POINT:
61ba2698f1SMatthew G. Knepley     if (numFaces) *numFaces = 0;
62ba2698f1SMatthew G. Knepley     break;
63ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
64412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 2;
65412e9a14SMatthew G. Knepley     if (faceTypes) {
669371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
679371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
68412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
69412e9a14SMatthew G. Knepley     }
70412e9a14SMatthew G. Knepley     if (faceSizes) {
719371c9d4SSatish Balay       sizesTmp[0] = 1;
729371c9d4SSatish Balay       sizesTmp[1] = 1;
73412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
74412e9a14SMatthew G. Knepley     }
75c49d9212SMatthew G. Knepley     if (faces) {
769371c9d4SSatish Balay       facesTmp[0] = cone[0];
779371c9d4SSatish Balay       facesTmp[1] = cone[1];
78c49d9212SMatthew G. Knepley       *faces      = facesTmp;
79c49d9212SMatthew G. Knepley     }
80412e9a14SMatthew G. Knepley     break;
81412e9a14SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
82c49d9212SMatthew G. Knepley     if (numFaces) *numFaces = 2;
83412e9a14SMatthew G. Knepley     if (faceTypes) {
849371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_POINT;
859371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_POINT;
86412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
87412e9a14SMatthew G. Knepley     }
88412e9a14SMatthew G. Knepley     if (faceSizes) {
899371c9d4SSatish Balay       sizesTmp[0] = 1;
909371c9d4SSatish Balay       sizesTmp[1] = 1;
91412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
92412e9a14SMatthew G. Knepley     }
93412e9a14SMatthew G. Knepley     if (faces) {
949371c9d4SSatish Balay       facesTmp[0] = cone[0];
959371c9d4SSatish Balay       facesTmp[1] = cone[1];
96412e9a14SMatthew G. Knepley       *faces      = facesTmp;
97412e9a14SMatthew G. Knepley     }
98c49d9212SMatthew G. Knepley     break;
99ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
100412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 3;
101412e9a14SMatthew G. Knepley     if (faceTypes) {
1029371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1039371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1049371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
105412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
106412e9a14SMatthew G. Knepley     }
107412e9a14SMatthew G. Knepley     if (faceSizes) {
1089371c9d4SSatish Balay       sizesTmp[0] = 2;
1099371c9d4SSatish Balay       sizesTmp[1] = 2;
1109371c9d4SSatish Balay       sizesTmp[2] = 2;
111412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
112412e9a14SMatthew G. Knepley     }
1139a5b13a2SMatthew G Knepley     if (faces) {
1149371c9d4SSatish Balay       facesTmp[0] = cone[0];
1159371c9d4SSatish Balay       facesTmp[1] = cone[1];
1169371c9d4SSatish Balay       facesTmp[2] = cone[1];
1179371c9d4SSatish Balay       facesTmp[3] = cone[2];
1189371c9d4SSatish Balay       facesTmp[4] = cone[2];
1199371c9d4SSatish Balay       facesTmp[5] = cone[0];
1209a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1219a5b13a2SMatthew G Knepley     }
1229f074e33SMatthew G Knepley     break;
123ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
1249a5b13a2SMatthew G Knepley     /* Vertices follow right hand rule */
125412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
126412e9a14SMatthew G. Knepley     if (faceTypes) {
1279371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1289371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1299371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEGMENT;
1309371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEGMENT;
131412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
132412e9a14SMatthew G. Knepley     }
133412e9a14SMatthew G. Knepley     if (faceSizes) {
1349371c9d4SSatish Balay       sizesTmp[0] = 2;
1359371c9d4SSatish Balay       sizesTmp[1] = 2;
1369371c9d4SSatish Balay       sizesTmp[2] = 2;
1379371c9d4SSatish Balay       sizesTmp[3] = 2;
138412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
139412e9a14SMatthew G. Knepley     }
1409a5b13a2SMatthew G Knepley     if (faces) {
1419371c9d4SSatish Balay       facesTmp[0] = cone[0];
1429371c9d4SSatish Balay       facesTmp[1] = cone[1];
1439371c9d4SSatish Balay       facesTmp[2] = cone[1];
1449371c9d4SSatish Balay       facesTmp[3] = cone[2];
1459371c9d4SSatish Balay       facesTmp[4] = cone[2];
1469371c9d4SSatish Balay       facesTmp[5] = cone[3];
1479371c9d4SSatish Balay       facesTmp[6] = cone[3];
1489371c9d4SSatish Balay       facesTmp[7] = cone[0];
1499a5b13a2SMatthew G Knepley       *faces      = facesTmp;
1509a5b13a2SMatthew G Knepley     }
151412e9a14SMatthew G. Knepley     break;
152412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
1539a5b13a2SMatthew G Knepley     if (numFaces) *numFaces = 4;
154412e9a14SMatthew G. Knepley     if (faceTypes) {
1559371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_SEGMENT;
1569371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_SEGMENT;
1579371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1589371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
159412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
160412e9a14SMatthew G. Knepley     }
161412e9a14SMatthew G. Knepley     if (faceSizes) {
1629371c9d4SSatish Balay       sizesTmp[0] = 2;
1639371c9d4SSatish Balay       sizesTmp[1] = 2;
1649371c9d4SSatish Balay       sizesTmp[2] = 2;
1659371c9d4SSatish Balay       sizesTmp[3] = 2;
166412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
167412e9a14SMatthew G. Knepley     }
168412e9a14SMatthew G. Knepley     if (faces) {
1699371c9d4SSatish Balay       facesTmp[0] = cone[0];
1709371c9d4SSatish Balay       facesTmp[1] = cone[1];
1719371c9d4SSatish Balay       facesTmp[2] = cone[2];
1729371c9d4SSatish Balay       facesTmp[3] = cone[3];
1739371c9d4SSatish Balay       facesTmp[4] = cone[0];
1749371c9d4SSatish Balay       facesTmp[5] = cone[2];
1759371c9d4SSatish Balay       facesTmp[6] = cone[1];
1769371c9d4SSatish Balay       facesTmp[7] = cone[3];
177412e9a14SMatthew G. Knepley       *faces      = facesTmp;
178412e9a14SMatthew G. Knepley     }
1799f074e33SMatthew G Knepley     break;
180ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
1812e1b13c2SMatthew G. Knepley     /* Vertices of first face follow right hand rule and normal points away from last vertex */
182412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 4;
183412e9a14SMatthew G. Knepley     if (faceTypes) {
1849371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
1859371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
1869371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
1879371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
188412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
189412e9a14SMatthew G. Knepley     }
190412e9a14SMatthew G. Knepley     if (faceSizes) {
1919371c9d4SSatish Balay       sizesTmp[0] = 3;
1929371c9d4SSatish Balay       sizesTmp[1] = 3;
1939371c9d4SSatish Balay       sizesTmp[2] = 3;
1949371c9d4SSatish Balay       sizesTmp[3] = 3;
195412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
196412e9a14SMatthew G. Knepley     }
1979a5b13a2SMatthew G Knepley     if (faces) {
1989371c9d4SSatish Balay       facesTmp[0]  = cone[0];
1999371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2009371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2019371c9d4SSatish Balay       facesTmp[3]  = cone[0];
2029371c9d4SSatish Balay       facesTmp[4]  = cone[3];
2039371c9d4SSatish Balay       facesTmp[5]  = cone[1];
2049371c9d4SSatish Balay       facesTmp[6]  = cone[0];
2059371c9d4SSatish Balay       facesTmp[7]  = cone[2];
2069371c9d4SSatish Balay       facesTmp[8]  = cone[3];
2079371c9d4SSatish Balay       facesTmp[9]  = cone[2];
2089371c9d4SSatish Balay       facesTmp[10] = cone[1];
2099371c9d4SSatish Balay       facesTmp[11] = cone[3];
2109a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2119a5b13a2SMatthew G Knepley     }
2129a5b13a2SMatthew G Knepley     break;
213ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
214e368ef20SMatthew G. Knepley     /*  7--------6
215e368ef20SMatthew G. Knepley          /|       /|
216e368ef20SMatthew G. Knepley         / |      / |
217e368ef20SMatthew G. Knepley        4--------5  |
218e368ef20SMatthew G. Knepley        |  |     |  |
219e368ef20SMatthew G. Knepley        |  |     |  |
220e368ef20SMatthew G. Knepley        |  1--------2
221e368ef20SMatthew G. Knepley        | /      | /
222e368ef20SMatthew G. Knepley        |/       |/
223e368ef20SMatthew G. Knepley        0--------3
224e368ef20SMatthew G. Knepley        */
225412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
226412e9a14SMatthew G. Knepley     if (faceTypes) {
2279371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
2289371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
2299371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2309371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2319371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
2329371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
233412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
234412e9a14SMatthew G. Knepley     }
235412e9a14SMatthew G. Knepley     if (faceSizes) {
2369371c9d4SSatish Balay       sizesTmp[0] = 4;
2379371c9d4SSatish Balay       sizesTmp[1] = 4;
2389371c9d4SSatish Balay       sizesTmp[2] = 4;
2399371c9d4SSatish Balay       sizesTmp[3] = 4;
2409371c9d4SSatish Balay       sizesTmp[4] = 4;
2419371c9d4SSatish Balay       sizesTmp[5] = 4;
242412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
243412e9a14SMatthew G. Knepley     }
2449a5b13a2SMatthew G Knepley     if (faces) {
2459371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2469371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2479371c9d4SSatish Balay       facesTmp[2]  = cone[2];
2489371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
2499371c9d4SSatish Balay       facesTmp[4]  = cone[4];
2509371c9d4SSatish Balay       facesTmp[5]  = cone[5];
2519371c9d4SSatish Balay       facesTmp[6]  = cone[6];
2529371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
2539371c9d4SSatish Balay       facesTmp[8]  = cone[0];
2549371c9d4SSatish Balay       facesTmp[9]  = cone[3];
2559371c9d4SSatish Balay       facesTmp[10] = cone[5];
2569371c9d4SSatish Balay       facesTmp[11] = cone[4]; /* Front */
2579371c9d4SSatish Balay       facesTmp[12] = cone[2];
2589371c9d4SSatish Balay       facesTmp[13] = cone[1];
2599371c9d4SSatish Balay       facesTmp[14] = cone[7];
2609371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Back */
2619371c9d4SSatish Balay       facesTmp[16] = cone[3];
2629371c9d4SSatish Balay       facesTmp[17] = cone[2];
2639371c9d4SSatish Balay       facesTmp[18] = cone[6];
2649371c9d4SSatish Balay       facesTmp[19] = cone[5]; /* Right */
2659371c9d4SSatish Balay       facesTmp[20] = cone[0];
2669371c9d4SSatish Balay       facesTmp[21] = cone[4];
2679371c9d4SSatish Balay       facesTmp[22] = cone[7];
2689371c9d4SSatish Balay       facesTmp[23] = cone[1]; /* Left */
2699a5b13a2SMatthew G Knepley       *faces       = facesTmp;
2709a5b13a2SMatthew G Knepley     }
27199836e0eSStefano Zampini     break;
272ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM:
273412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
274412e9a14SMatthew G. Knepley     if (faceTypes) {
2759371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2769371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2779371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2789371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2799371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
280412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
281412e9a14SMatthew G. Knepley     }
282412e9a14SMatthew G. Knepley     if (faceSizes) {
2839371c9d4SSatish Balay       sizesTmp[0] = 3;
2849371c9d4SSatish Balay       sizesTmp[1] = 3;
2859371c9d4SSatish Balay       sizesTmp[2] = 4;
2869371c9d4SSatish Balay       sizesTmp[3] = 4;
2879371c9d4SSatish Balay       sizesTmp[4] = 4;
288412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
289412e9a14SMatthew G. Knepley     }
290ba2698f1SMatthew G. Knepley     if (faces) {
2919371c9d4SSatish Balay       facesTmp[0]  = cone[0];
2929371c9d4SSatish Balay       facesTmp[1]  = cone[1];
2939371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
2949371c9d4SSatish Balay       facesTmp[3]  = cone[3];
2959371c9d4SSatish Balay       facesTmp[4]  = cone[4];
2969371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
2979371c9d4SSatish Balay       facesTmp[6]  = cone[0];
2989371c9d4SSatish Balay       facesTmp[7]  = cone[2];
2999371c9d4SSatish Balay       facesTmp[8]  = cone[4];
3009371c9d4SSatish Balay       facesTmp[9]  = cone[3]; /* Back left */
3019371c9d4SSatish Balay       facesTmp[10] = cone[2];
3029371c9d4SSatish Balay       facesTmp[11] = cone[1];
3039371c9d4SSatish Balay       facesTmp[12] = cone[5];
3049371c9d4SSatish Balay       facesTmp[13] = cone[4]; /* Front */
3059371c9d4SSatish Balay       facesTmp[14] = cone[1];
3069371c9d4SSatish Balay       facesTmp[15] = cone[0];
3079371c9d4SSatish Balay       facesTmp[16] = cone[3];
3089371c9d4SSatish Balay       facesTmp[17] = cone[5]; /* Back right */
309ba2698f1SMatthew G. Knepley       *faces       = facesTmp;
31099836e0eSStefano Zampini     }
31199836e0eSStefano Zampini     break;
312ba2698f1SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
313412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 5;
314412e9a14SMatthew G. Knepley     if (faceTypes) {
3159371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_TRIANGLE;
3169371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
3179371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3189371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3199371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
320412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
321412e9a14SMatthew G. Knepley     }
322412e9a14SMatthew G. Knepley     if (faceSizes) {
3239371c9d4SSatish Balay       sizesTmp[0] = 3;
3249371c9d4SSatish Balay       sizesTmp[1] = 3;
3259371c9d4SSatish Balay       sizesTmp[2] = 4;
3269371c9d4SSatish Balay       sizesTmp[3] = 4;
3279371c9d4SSatish Balay       sizesTmp[4] = 4;
328412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
329412e9a14SMatthew G. Knepley     }
33099836e0eSStefano Zampini     if (faces) {
3319371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3329371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3339371c9d4SSatish Balay       facesTmp[2]  = cone[2]; /* Bottom */
3349371c9d4SSatish Balay       facesTmp[3]  = cone[3];
3359371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3369371c9d4SSatish Balay       facesTmp[5]  = cone[5]; /* Top */
3379371c9d4SSatish Balay       facesTmp[6]  = cone[0];
3389371c9d4SSatish Balay       facesTmp[7]  = cone[1];
3399371c9d4SSatish Balay       facesTmp[8]  = cone[3];
3409371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Back left */
3419371c9d4SSatish Balay       facesTmp[10] = cone[1];
3429371c9d4SSatish Balay       facesTmp[11] = cone[2];
3439371c9d4SSatish Balay       facesTmp[12] = cone[4];
3449371c9d4SSatish Balay       facesTmp[13] = cone[5]; /* Back right */
3459371c9d4SSatish Balay       facesTmp[14] = cone[2];
3469371c9d4SSatish Balay       facesTmp[15] = cone[0];
3479371c9d4SSatish Balay       facesTmp[16] = cone[5];
3489371c9d4SSatish Balay       facesTmp[17] = cone[3]; /* Front */
34999836e0eSStefano Zampini       *faces       = facesTmp;
35099836e0eSStefano Zampini     }
351412e9a14SMatthew G. Knepley     break;
352412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
353412e9a14SMatthew G. Knepley     /*  7--------6
354412e9a14SMatthew G. Knepley          /|       /|
355412e9a14SMatthew G. Knepley         / |      / |
356412e9a14SMatthew G. Knepley        4--------5  |
357412e9a14SMatthew G. Knepley        |  |     |  |
358412e9a14SMatthew G. Knepley        |  |     |  |
359412e9a14SMatthew G. Knepley        |  3--------2
360412e9a14SMatthew G. Knepley        | /      | /
361412e9a14SMatthew G. Knepley        |/       |/
362412e9a14SMatthew G. Knepley        0--------1
363412e9a14SMatthew G. Knepley        */
364412e9a14SMatthew G. Knepley     if (numFaces) *numFaces = 6;
365412e9a14SMatthew G. Knepley     if (faceTypes) {
3669371c9d4SSatish Balay       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
3679371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
3689371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3699371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3709371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3719371c9d4SSatish Balay       typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
372412e9a14SMatthew G. Knepley       *faceTypes  = typesTmp;
373412e9a14SMatthew G. Knepley     }
374412e9a14SMatthew G. Knepley     if (faceSizes) {
3759371c9d4SSatish Balay       sizesTmp[0] = 4;
3769371c9d4SSatish Balay       sizesTmp[1] = 4;
3779371c9d4SSatish Balay       sizesTmp[2] = 4;
3789371c9d4SSatish Balay       sizesTmp[3] = 4;
3799371c9d4SSatish Balay       sizesTmp[4] = 4;
3809371c9d4SSatish Balay       sizesTmp[5] = 4;
381412e9a14SMatthew G. Knepley       *faceSizes  = sizesTmp;
382412e9a14SMatthew G. Knepley     }
383412e9a14SMatthew G. Knepley     if (faces) {
3849371c9d4SSatish Balay       facesTmp[0]  = cone[0];
3859371c9d4SSatish Balay       facesTmp[1]  = cone[1];
3869371c9d4SSatish Balay       facesTmp[2]  = cone[2];
3879371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
3889371c9d4SSatish Balay       facesTmp[4]  = cone[4];
3899371c9d4SSatish Balay       facesTmp[5]  = cone[5];
3909371c9d4SSatish Balay       facesTmp[6]  = cone[6];
3919371c9d4SSatish Balay       facesTmp[7]  = cone[7]; /* Top */
3929371c9d4SSatish Balay       facesTmp[8]  = cone[0];
3939371c9d4SSatish Balay       facesTmp[9]  = cone[1];
3949371c9d4SSatish Balay       facesTmp[10] = cone[4];
3959371c9d4SSatish Balay       facesTmp[11] = cone[5]; /* Front */
3969371c9d4SSatish Balay       facesTmp[12] = cone[1];
3979371c9d4SSatish Balay       facesTmp[13] = cone[2];
3989371c9d4SSatish Balay       facesTmp[14] = cone[5];
3999371c9d4SSatish Balay       facesTmp[15] = cone[6]; /* Right */
4009371c9d4SSatish Balay       facesTmp[16] = cone[2];
4019371c9d4SSatish Balay       facesTmp[17] = cone[3];
4029371c9d4SSatish Balay       facesTmp[18] = cone[6];
4039371c9d4SSatish Balay       facesTmp[19] = cone[7]; /* Back */
4049371c9d4SSatish Balay       facesTmp[20] = cone[3];
4059371c9d4SSatish Balay       facesTmp[21] = cone[0];
4069371c9d4SSatish Balay       facesTmp[22] = cone[7];
4079371c9d4SSatish Balay       facesTmp[23] = cone[4]; /* Left */
408412e9a14SMatthew G. Knepley       *faces       = facesTmp;
409412e9a14SMatthew G. Knepley     }
41099836e0eSStefano Zampini     break;
411da9060c4SMatthew G. Knepley   case DM_POLYTOPE_PYRAMID:
412da9060c4SMatthew G. Knepley     /*
413da9060c4SMatthew G. Knepley        4----
414da9060c4SMatthew G. Knepley        |\-\ \-----
415da9060c4SMatthew G. Knepley        | \ -\     \
416da9060c4SMatthew G. Knepley        |  1--\-----2
417da9060c4SMatthew G. Knepley        | /    \   /
418da9060c4SMatthew G. Knepley        |/      \ /
419da9060c4SMatthew G. Knepley        0--------3
420da9060c4SMatthew G. Knepley        */
421da9060c4SMatthew G. Knepley     if (numFaces) *numFaces = 5;
422da9060c4SMatthew G. Knepley     if (faceTypes) {
423da9060c4SMatthew G. Knepley       typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
4249371c9d4SSatish Balay       typesTmp[1] = DM_POLYTOPE_TRIANGLE;
4259371c9d4SSatish Balay       typesTmp[2] = DM_POLYTOPE_TRIANGLE;
4269371c9d4SSatish Balay       typesTmp[3] = DM_POLYTOPE_TRIANGLE;
4279371c9d4SSatish Balay       typesTmp[4] = DM_POLYTOPE_TRIANGLE;
428da9060c4SMatthew G. Knepley       *faceTypes  = typesTmp;
429da9060c4SMatthew G. Knepley     }
430da9060c4SMatthew G. Knepley     if (faceSizes) {
431da9060c4SMatthew G. Knepley       sizesTmp[0] = 4;
4329371c9d4SSatish Balay       sizesTmp[1] = 3;
4339371c9d4SSatish Balay       sizesTmp[2] = 3;
4349371c9d4SSatish Balay       sizesTmp[3] = 3;
4359371c9d4SSatish Balay       sizesTmp[4] = 3;
436da9060c4SMatthew G. Knepley       *faceSizes  = sizesTmp;
437da9060c4SMatthew G. Knepley     }
438da9060c4SMatthew G. Knepley     if (faces) {
4399371c9d4SSatish Balay       facesTmp[0]  = cone[0];
4409371c9d4SSatish Balay       facesTmp[1]  = cone[1];
4419371c9d4SSatish Balay       facesTmp[2]  = cone[2];
4429371c9d4SSatish Balay       facesTmp[3]  = cone[3]; /* Bottom */
4439371c9d4SSatish Balay       facesTmp[4]  = cone[0];
4449371c9d4SSatish Balay       facesTmp[5]  = cone[3];
4459371c9d4SSatish Balay       facesTmp[6]  = cone[4]; /* Front */
4469371c9d4SSatish Balay       facesTmp[7]  = cone[3];
4479371c9d4SSatish Balay       facesTmp[8]  = cone[2];
4489371c9d4SSatish Balay       facesTmp[9]  = cone[4]; /* Right */
4499371c9d4SSatish Balay       facesTmp[10] = cone[2];
4509371c9d4SSatish Balay       facesTmp[11] = cone[1];
4519371c9d4SSatish Balay       facesTmp[12] = cone[4]; /* Back */
4529371c9d4SSatish Balay       facesTmp[13] = cone[1];
4539371c9d4SSatish Balay       facesTmp[14] = cone[0];
4549371c9d4SSatish Balay       facesTmp[15] = cone[4]; /* Left */
455da9060c4SMatthew G. Knepley       *faces       = facesTmp;
456da9060c4SMatthew G. Knepley     }
457da9060c4SMatthew G. Knepley     break;
458d71ae5a4SJacob Faibussowitsch   default:
459d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
46099836e0eSStefano Zampini   }
4613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46299836e0eSStefano Zampini }
46399836e0eSStefano Zampini 
464d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
465d71ae5a4SJacob Faibussowitsch {
46699836e0eSStefano Zampini   PetscFunctionBegin;
4679566063dSJacob Faibussowitsch   if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes));
4689566063dSJacob Faibussowitsch   if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes));
4699566063dSJacob Faibussowitsch   if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces));
4703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47199836e0eSStefano Zampini }
47299836e0eSStefano Zampini 
4739a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
474d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
475d71ae5a4SJacob Faibussowitsch {
476412e9a14SMatthew G. Knepley   DMLabel       ctLabel;
477a03d55ffSStefano Zampini   PetscHMapIJKL faceTable;
478412e9a14SMatthew G. Knepley   PetscInt      faceTypeNum[DM_NUM_POLYTOPES];
4799318fe57SMatthew G. Knepley   PetscInt      depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd;
480a03d55ffSStefano Zampini   PetscInt      cntFaces, *facesId, minCone;
4819f074e33SMatthew G Knepley 
4829f074e33SMatthew G Knepley   PetscFunctionBegin;
4839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
484a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLCreate(&faceTable));
4859566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
4869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
487412e9a14SMatthew G. Knepley   /* Number new faces and save face vertices in hash table */
4889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
489412e9a14SMatthew G. Knepley   fEnd = fStart;
490591a860aSStefano Zampini 
491a03d55ffSStefano Zampini   minCone = PETSC_MAX_INT;
492591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
493591a860aSStefano Zampini     const PetscInt *cone;
494591a860aSStefano Zampini     DMPolytopeType  ct;
495a03d55ffSStefano Zampini     PetscInt        numFaces, coneSize;
496591a860aSStefano Zampini 
497591a860aSStefano Zampini     PetscCall(DMPlexGetCellType(dm, c, &ct));
498591a860aSStefano Zampini     PetscCall(DMPlexGetCone(dm, c, &cone));
499a03d55ffSStefano Zampini     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
500a03d55ffSStefano Zampini     for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone);
501591a860aSStefano Zampini     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL));
502591a860aSStefano Zampini     cntFaces += numFaces;
503591a860aSStefano Zampini   }
504a03d55ffSStefano Zampini   // Encode so that we can use 0 as an excluded value, instead of PETSC_MAX_INT
505a03d55ffSStefano Zampini   minCone = -(minCone - 1);
506591a860aSStefano Zampini 
507591a860aSStefano Zampini   PetscCall(PetscMalloc1(cntFaces, &facesId));
508591a860aSStefano Zampini 
509591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
510412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
511412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
512ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
513412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
51499836e0eSStefano Zampini 
5159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
5169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
5179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
518412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
519412e9a14SMatthew G. Knepley       const PetscInt       faceSize = faceSizes[cf];
520412e9a14SMatthew G. Knepley       const DMPolytopeType faceType = faceTypes[cf];
521412e9a14SMatthew G. Knepley       const PetscInt      *face     = &faces[foff];
5229a5b13a2SMatthew G Knepley       PetscHashIJKLKey     key;
523e8f14785SLisandro Dalcin       PetscHashIter        iter;
524e8f14785SLisandro Dalcin       PetscBool            missing;
5259f074e33SMatthew G Knepley 
5265f80ce2aSJacob Faibussowitsch       PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
527a03d55ffSStefano Zampini       key.i = face[0] + minCone;
528a03d55ffSStefano Zampini       key.j = faceSize > 1 ? face[1] + minCone : 0;
529a03d55ffSStefano Zampini       key.k = faceSize > 2 ? face[2] + minCone : 0;
530a03d55ffSStefano Zampini       key.l = faceSize > 3 ? face[3] + minCone : 0;
5319566063dSJacob Faibussowitsch       PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
532a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
533e9fa77a1SMatthew G. Knepley       if (missing) {
534591a860aSStefano Zampini         facesId[cntFaces] = fEnd;
535a03d55ffSStefano Zampini         PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++));
536412e9a14SMatthew G. Knepley         ++faceTypeNum[faceType];
537a03d55ffSStefano Zampini       } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
538591a860aSStefano Zampini       cntFaces++;
5399a5b13a2SMatthew G Knepley     }
5409566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
54199836e0eSStefano Zampini   }
542412e9a14SMatthew G. Knepley   /* We need to number faces contiguously among types */
543412e9a14SMatthew G. Knepley   {
544412e9a14SMatthew G. Knepley     PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
54599836e0eSStefano Zampini 
5469371c9d4SSatish Balay     for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5479371c9d4SSatish Balay       if (faceTypeNum[ct]) ++numFT;
5489371c9d4SSatish Balay       faceTypeStart[ct] = 0;
5499371c9d4SSatish Balay     }
550412e9a14SMatthew G. Knepley     if (numFT > 1) {
551a03d55ffSStefano Zampini       PetscCall(PetscHMapIJKLClear(faceTable));
552412e9a14SMatthew G. Knepley       faceTypeStart[0] = fStart;
553412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
554591a860aSStefano Zampini       for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
555412e9a14SMatthew G. Knepley         const PetscInt       *cone, *faceSizes, *faces;
556412e9a14SMatthew G. Knepley         const DMPolytopeType *faceTypes;
557ba2698f1SMatthew G. Knepley         DMPolytopeType        ct;
558412e9a14SMatthew G. Knepley         PetscInt              numFaces, cf, foff = 0;
55999836e0eSStefano Zampini 
5609566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
5619566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, c, &cone));
5629566063dSJacob Faibussowitsch         PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
563412e9a14SMatthew G. Knepley         for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
564412e9a14SMatthew G. Knepley           const PetscInt       faceSize = faceSizes[cf];
565412e9a14SMatthew G. Knepley           const DMPolytopeType faceType = faceTypes[cf];
566412e9a14SMatthew G. Knepley           const PetscInt      *face     = &faces[foff];
56799836e0eSStefano Zampini           PetscHashIJKLKey     key;
56899836e0eSStefano Zampini           PetscHashIter        iter;
56999836e0eSStefano Zampini           PetscBool            missing;
57099836e0eSStefano Zampini 
571a03d55ffSStefano Zampini           key.i = face[0] + minCone;
572a03d55ffSStefano Zampini           key.j = faceSize > 1 ? face[1] + minCone : 0;
573a03d55ffSStefano Zampini           key.k = faceSize > 2 ? face[2] + minCone : 0;
574a03d55ffSStefano Zampini           key.l = faceSize > 3 ? face[3] + minCone : 0;
5759566063dSJacob Faibussowitsch           PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
576a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
577591a860aSStefano Zampini           if (missing) {
578591a860aSStefano Zampini             facesId[cntFaces] = faceTypeStart[faceType];
579a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
580a03d55ffSStefano Zampini           } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
581591a860aSStefano Zampini           cntFaces++;
58299836e0eSStefano Zampini         }
5839566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
58499836e0eSStefano Zampini       }
585412e9a14SMatthew G. Knepley       for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
5861dca8a05SBarry 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]);
5879a5b13a2SMatthew G Knepley       }
5889a5b13a2SMatthew G Knepley     }
589412e9a14SMatthew G. Knepley   }
590a03d55ffSStefano Zampini   PetscCall(PetscHMapIJKLDestroy(&faceTable));
591591a860aSStefano Zampini 
592412e9a14SMatthew G. Knepley   /* Add new points, always at the end of the numbering */
5939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &Np));
5949566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
5959a5b13a2SMatthew G Knepley   /* Set cone sizes */
596412e9a14SMatthew G. Knepley   /*   Must create the celltype label here so that we do not automatically try to compute the types */
5979566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(idm, "celltype"));
5989566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
5999a5b13a2SMatthew G Knepley   for (d = 0; d <= depth; ++d) {
600412e9a14SMatthew G. Knepley     DMPolytopeType ct;
601412e9a14SMatthew G. Knepley     PetscInt       coneSize, pStart, pEnd, p;
6029f074e33SMatthew G Knepley 
603412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
605412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
6069566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
6079566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, p, coneSize));
6089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, p, &ct));
6099566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, p, ct));
6109f074e33SMatthew G Knepley     }
6119f074e33SMatthew G Knepley   }
612591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
613591a860aSStefano Zampini     const PetscInt       *cone, *faceSizes;
614412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
615412e9a14SMatthew G. Knepley     DMPolytopeType        ct;
616591a860aSStefano Zampini     PetscInt              numFaces, cf;
617412e9a14SMatthew G. Knepley 
6189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6199566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
620591a860aSStefano Zampini     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6219566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(idm, c, ct));
6229566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(idm, c, numFaces));
623591a860aSStefano Zampini     for (cf = 0; cf < numFaces; ++cf) {
624591a860aSStefano Zampini       const PetscInt f        = facesId[cntFaces];
625591a860aSStefano Zampini       DMPolytopeType faceType = faceTypes[cf];
626412e9a14SMatthew G. Knepley       const PetscInt faceSize = faceSizes[cf];
6279566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeSize(idm, f, faceSize));
6289566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(idm, f, faceType));
629591a860aSStefano Zampini       cntFaces++;
630412e9a14SMatthew G. Knepley     }
631591a860aSStefano Zampini     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6329f074e33SMatthew G Knepley   }
6339566063dSJacob Faibussowitsch   PetscCall(DMSetUp(idm));
634412e9a14SMatthew G. Knepley   /* Initialize cones so we do not need the bash table to tell us that a cone has been set */
635412e9a14SMatthew G. Knepley   {
636412e9a14SMatthew G. Knepley     PetscSection cs;
637412e9a14SMatthew G. Knepley     PetscInt    *cones, csize;
6389a5b13a2SMatthew G Knepley 
6399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSection(idm, &cs));
6409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCones(idm, &cones));
6419566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(cs, &csize));
642412e9a14SMatthew G. Knepley     for (c = 0; c < csize; ++c) cones[c] = -1;
643412e9a14SMatthew G. Knepley   }
644412e9a14SMatthew G. Knepley   /* Set cones */
645412e9a14SMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
646412e9a14SMatthew G. Knepley     const PetscInt *cone;
647412e9a14SMatthew G. Knepley     PetscInt        pStart, pEnd, p;
648412e9a14SMatthew G. Knepley 
649412e9a14SMatthew G. Knepley     if (d == cellDepth) continue;
6509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
651412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
6529566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, p, &cone));
6539566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(idm, p, cone));
6549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
6559566063dSJacob Faibussowitsch       PetscCall(DMPlexSetConeOrientation(idm, p, cone));
6569f074e33SMatthew G Knepley     }
6579a5b13a2SMatthew G Knepley   }
658591a860aSStefano Zampini   for (c = cStart, cntFaces = 0; c < cEnd; ++c) {
659412e9a14SMatthew G. Knepley     const PetscInt       *cone, *faceSizes, *faces;
660412e9a14SMatthew G. Knepley     const DMPolytopeType *faceTypes;
661ba2698f1SMatthew G. Knepley     DMPolytopeType        ct;
662412e9a14SMatthew G. Knepley     PetscInt              numFaces, cf, foff = 0;
66399836e0eSStefano Zampini 
6649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
6659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
6669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
667412e9a14SMatthew G. Knepley     for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
668412e9a14SMatthew G. Knepley       DMPolytopeType  faceType = faceTypes[cf];
669412e9a14SMatthew G. Knepley       const PetscInt  faceSize = faceSizes[cf];
670591a860aSStefano Zampini       const PetscInt  f        = facesId[cntFaces];
671412e9a14SMatthew G. Knepley       const PetscInt *face     = &faces[foff];
672412e9a14SMatthew G. Knepley       const PetscInt *fcone;
6739f074e33SMatthew G Knepley 
6749566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertCone(idm, c, cf, f));
6759566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(idm, f, &fcone));
6769566063dSJacob Faibussowitsch       if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
677412e9a14SMatthew G. Knepley       {
678412e9a14SMatthew G. Knepley         const PetscInt *cone;
679412e9a14SMatthew G. Knepley         PetscInt        coneSize, ornt;
680a74221b0SStefano Zampini 
6819566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
6829566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(idm, f, &cone));
68363a3b9bcSJacob 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);
684d89e6e46SMatthew G. Knepley         /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
6859566063dSJacob Faibussowitsch         PetscCall(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt));
6869566063dSJacob Faibussowitsch         PetscCall(DMPlexInsertConeOrientation(idm, c, cf, ornt));
68799836e0eSStefano Zampini       }
688591a860aSStefano Zampini       cntFaces++;
68999836e0eSStefano Zampini     }
6909566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
69199836e0eSStefano Zampini   }
692591a860aSStefano Zampini   PetscCall(PetscFree(facesId));
6939566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(idm));
6949566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(idm));
6953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6969f074e33SMatthew G Knepley }
6979f074e33SMatthew G Knepley 
698d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
699d71ae5a4SJacob Faibussowitsch {
700f80536cbSVaclav Hapla   PetscInt           nleaves;
701f80536cbSVaclav Hapla   PetscInt           nranks;
702a0d42dbcSVaclav Hapla   const PetscMPIInt *ranks   = NULL;
703a0d42dbcSVaclav Hapla   const PetscInt    *roffset = NULL, *rmine = NULL, *rremote = NULL;
704f80536cbSVaclav Hapla   PetscInt           n, o, r;
705f80536cbSVaclav Hapla 
706f80536cbSVaclav Hapla   PetscFunctionBegin;
7079566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
708f80536cbSVaclav Hapla   nleaves = roffset[nranks];
7099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
710f80536cbSVaclav Hapla   for (r = 0; r < nranks; r++) {
711f80536cbSVaclav Hapla     /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
712f80536cbSVaclav Hapla        - to unify order with the other side */
713f80536cbSVaclav Hapla     o = roffset[r];
714f80536cbSVaclav Hapla     n = roffset[r + 1] - o;
7159566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7169566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7179566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
718f80536cbSVaclav Hapla   }
7193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
720f80536cbSVaclav Hapla }
721f80536cbSVaclav Hapla 
722d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
723d71ae5a4SJacob Faibussowitsch {
724d89e6e46SMatthew G. Knepley   PetscSF            sf;
725d89e6e46SMatthew G. Knepley   const PetscInt    *locals;
726d89e6e46SMatthew G. Knepley   const PetscSFNode *remotes;
727d89e6e46SMatthew G. Knepley   const PetscMPIInt *ranks;
728d89e6e46SMatthew G. Knepley   const PetscInt    *roffset;
729d89e6e46SMatthew G. Knepley   PetscInt          *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
730d89e6e46SMatthew G. Knepley   PetscInt           nroots, p, nleaves, nranks, r, maxConeSize = 0;
731d89e6e46SMatthew G. Knepley   PetscInt(*roots)[4], (*leaves)[4], mainCone[4];
732d89e6e46SMatthew G. Knepley   PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4];
7332e745bdaSMatthew G. Knepley   MPI_Comm    comm;
73427d0e99aSVaclav Hapla   PetscMPIInt rank, size;
7352e745bdaSMatthew G. Knepley   PetscInt    debug = 0;
7362e745bdaSMatthew G. Knepley 
7372e745bdaSMatthew G. Knepley   PetscFunctionBegin;
7389566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
7399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
7419566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
7429566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
743d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
7449566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
7453ba16761SJacob Faibussowitsch   if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS);
7469566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUp(sf));
7479566063dSJacob Faibussowitsch   PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
748d89e6e46SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
749d89e6e46SMatthew G. Knepley     PetscInt coneSize;
7509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
751d89e6e46SMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
752d89e6e46SMatthew G. Knepley   }
75363a3b9bcSJacob Faibussowitsch   PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
7549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
7559e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
756d89e6e46SMatthew G. Knepley     const PetscInt *cone;
757d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0;
758d89e6e46SMatthew G. Knepley 
7599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
7609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
761d89e6e46SMatthew G. Knepley     /* Ignore vertices */
76227d0e99aSVaclav Hapla     if (coneSize < 2) {
763d89e6e46SMatthew G. Knepley       for (c = 0; c < 4; c++) {
76427d0e99aSVaclav Hapla         roots[p][c]      = -1;
76527d0e99aSVaclav Hapla         rootsRanks[p][c] = -1;
76627d0e99aSVaclav Hapla       }
76727d0e99aSVaclav Hapla       continue;
76827d0e99aSVaclav Hapla     }
7692e745bdaSMatthew G. Knepley     /* Translate all points to root numbering */
770d89e6e46SMatthew G. Knepley     for (c = 0; c < PetscMin(coneSize, 4); c++) {
7719566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
7728a650c75SVaclav Hapla       if (ind0 < 0) {
7738a650c75SVaclav Hapla         roots[p][c]      = cone[c];
7748a650c75SVaclav Hapla         rootsRanks[p][c] = rank;
775c8148b97SVaclav Hapla       } else {
7768a650c75SVaclav Hapla         roots[p][c]      = remotes[ind0].index;
7778a650c75SVaclav Hapla         rootsRanks[p][c] = remotes[ind0].rank;
7788a650c75SVaclav Hapla       }
7792e745bdaSMatthew G. Knepley     }
780d89e6e46SMatthew G. Knepley     for (c = coneSize; c < 4; c++) {
781d89e6e46SMatthew G. Knepley       roots[p][c]      = -1;
782d89e6e46SMatthew G. Knepley       rootsRanks[p][c] = -1;
783d89e6e46SMatthew G. Knepley     }
7842e745bdaSMatthew G. Knepley   }
7859e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
786d89e6e46SMatthew G. Knepley     PetscInt c;
787d89e6e46SMatthew G. Knepley     for (c = 0; c < 4; c++) {
7888ccb905dSVaclav Hapla       leaves[p][c]      = -2;
7898ccb905dSVaclav Hapla       leavesRanks[p][c] = -2;
7908ccb905dSVaclav Hapla     }
791c8148b97SVaclav Hapla   }
7929566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
7939566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
7949566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
7959566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
796d89e6e46SMatthew G. Knepley   if (debug) {
7979566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
798c5853193SPierre Jolivet     if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
799d89e6e46SMatthew G. Knepley   }
8009566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8019e24d8a0SVaclav Hapla   for (p = 0; p < nroots; ++p) {
802d89e6e46SMatthew G. Knepley     DMPolytopeType  ct;
803d89e6e46SMatthew G. Knepley     const PetscInt *cone;
804d89e6e46SMatthew G. Knepley     PetscInt        coneSize, c, ind0, o;
805d89e6e46SMatthew G. Knepley 
806d89e6e46SMatthew G. Knepley     if (leaves[p][0] < 0) continue; /* Ignore vertices */
8079566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
8089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
810d89e6e46SMatthew G. Knepley     if (debug) {
8119371c9d4SSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "[%d]  %4" PetscInt_FMT ": cone=[%4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT " %4" PetscInt_FMT "] roots=[(%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ")] leaves=[(%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ") (%d,%4" PetscInt_FMT ")]", rank, p, cone[0], cone[1], cone[2], cone[3], rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], rootsRanks[p][2], roots[p][2], rootsRanks[p][3], roots[p][3], leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1], leavesRanks[p][2], leaves[p][2], leavesRanks[p][3], leaves[p][3]));
812d89e6e46SMatthew G. Knepley     }
8139371c9d4SSatish Balay     if (leavesRanks[p][0] != rootsRanks[p][0] || leaves[p][0] != roots[p][0] || leavesRanks[p][1] != rootsRanks[p][1] || leaves[p][1] != roots[p][1] || leavesRanks[p][2] != rootsRanks[p][2] || leaves[p][2] != roots[p][2] || leavesRanks[p][3] != rootsRanks[p][3] || leaves[p][3] != roots[p][3]) {
814d89e6e46SMatthew G. Knepley       /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
815d89e6e46SMatthew G. Knepley       for (c = 0; c < PetscMin(coneSize, 4); ++c) {
816d89e6e46SMatthew G. Knepley         PetscInt rS, rN;
817d89e6e46SMatthew G. Knepley 
81827d0e99aSVaclav Hapla         if (leavesRanks[p][c] == rank) {
819d89e6e46SMatthew G. Knepley           /* A local leaf is just taken as it is */
8209dddd249SSatish Balay           mainCone[c] = leaves[p][c];
82127d0e99aSVaclav Hapla           continue;
82227d0e99aSVaclav Hapla         }
823f80536cbSVaclav Hapla         /* Find index of rank leavesRanks[p][c] among remote ranks */
824f80536cbSVaclav Hapla         /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
8259566063dSJacob Faibussowitsch         PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r));
82663a3b9bcSJacob 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]);
8271dca8a05SBarry 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]);
828f80536cbSVaclav Hapla         /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
829d89e6e46SMatthew G. Knepley         rS = roffset[r];
830d89e6e46SMatthew G. Knepley         rN = roffset[r + 1] - rS;
8319566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
83263a3b9bcSJacob 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]);
833f80536cbSVaclav Hapla         /* Get the corresponding local point */
8345f80ce2aSJacob Faibussowitsch         mainCone[c] = rmine1[rS + ind0];
835f80536cbSVaclav Hapla       }
83663a3b9bcSJacob 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]));
83727d0e99aSVaclav Hapla       /* Set the desired order of p's cone points and fix orientations accordingly */
8389566063dSJacob Faibussowitsch       PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
8399566063dSJacob Faibussowitsch       PetscCall(DMPlexOrientPoint(dm, p, o));
8409566063dSJacob Faibussowitsch     } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
84123aaf07bSVaclav Hapla   }
84227d0e99aSVaclav Hapla   if (debug) {
8439566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, NULL));
8449566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(comm));
8452e745bdaSMatthew G. Knepley   }
8469566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
8479566063dSJacob Faibussowitsch   PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
8489566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rmine1, rremote1));
8493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8502e745bdaSMatthew G. Knepley }
8512e745bdaSMatthew G. Knepley 
852d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
853d71ae5a4SJacob Faibussowitsch {
8542e72742cSMatthew G. Knepley   PetscInt    idx;
8552e72742cSMatthew G. Knepley   PetscMPIInt rank;
8562e72742cSMatthew G. Knepley   PetscBool   flg;
8577bffde78SMichael Lange 
8587bffde78SMichael Lange   PetscFunctionBegin;
8599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
8603ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
8619566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8629566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
86363a3b9bcSJacob Faibussowitsch   for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
8649566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
8653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8662e72742cSMatthew G. Knepley }
8672e72742cSMatthew G. Knepley 
868d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
869d71ae5a4SJacob Faibussowitsch {
8702e72742cSMatthew G. Knepley   PetscInt    idx;
8712e72742cSMatthew G. Knepley   PetscMPIInt rank;
8722e72742cSMatthew G. Knepley   PetscBool   flg;
8732e72742cSMatthew G. Knepley 
8742e72742cSMatthew G. Knepley   PetscFunctionBegin;
8759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
8763ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
8779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8789566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
8792e72742cSMatthew G. Knepley   if (idxname) {
88063a3b9bcSJacob 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));
8812e72742cSMatthew G. Knepley   } else {
88263a3b9bcSJacob 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));
8832e72742cSMatthew G. Knepley   }
8849566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
8853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8862e72742cSMatthew G. Knepley }
8872e72742cSMatthew G. Knepley 
888d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
889d71ae5a4SJacob Faibussowitsch {
8903be36e83SMatthew G. Knepley   PetscSF         sf;
8913be36e83SMatthew G. Knepley   const PetscInt *locals;
8923be36e83SMatthew G. Knepley   PetscMPIInt     rank;
8932e72742cSMatthew G. Knepley 
8942e72742cSMatthew G. Knepley   PetscFunctionBegin;
8959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8969566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
8979566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
8985f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
8992e72742cSMatthew G. Knepley   if (remotePoint.rank == rank) {
9002e72742cSMatthew G. Knepley     *localPoint = remotePoint.index;
9012e72742cSMatthew G. Knepley   } else {
9022e72742cSMatthew G. Knepley     PetscHashIJKey key;
9033be36e83SMatthew G. Knepley     PetscInt       l;
9042e72742cSMatthew G. Knepley 
9052e72742cSMatthew G. Knepley     key.i = remotePoint.index;
9062e72742cSMatthew G. Knepley     key.j = remotePoint.rank;
9079566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(remotehash, key, &l));
9083be36e83SMatthew G. Knepley     if (l >= 0) {
9093be36e83SMatthew G. Knepley       *localPoint = locals[l];
9105f80ce2aSJacob Faibussowitsch     } else if (mapFailed) *mapFailed = PETSC_TRUE;
9112e72742cSMatthew G. Knepley   }
9123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9132e72742cSMatthew G. Knepley }
9142e72742cSMatthew G. Knepley 
915d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
916d71ae5a4SJacob Faibussowitsch {
9173be36e83SMatthew G. Knepley   PetscSF            sf;
9183be36e83SMatthew G. Knepley   const PetscInt    *locals, *rootdegree;
9193be36e83SMatthew G. Knepley   const PetscSFNode *remotes;
9203be36e83SMatthew G. Knepley   PetscInt           Nl, l;
9213be36e83SMatthew G. Knepley   PetscMPIInt        rank;
9223be36e83SMatthew G. Knepley 
9233be36e83SMatthew G. Knepley   PetscFunctionBegin;
9245f80ce2aSJacob Faibussowitsch   if (mapFailed) *mapFailed = PETSC_FALSE;
9259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9269566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9279566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
9283be36e83SMatthew G. Knepley   if (Nl < 0) goto owned;
9299566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9309566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9313be36e83SMatthew G. Knepley   if (rootdegree[localPoint]) goto owned;
9329566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
9339371c9d4SSatish Balay   if (l < 0) {
9349371c9d4SSatish Balay     if (mapFailed) *mapFailed = PETSC_TRUE;
9359371c9d4SSatish Balay   } else *remotePoint = remotes[l];
9363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9373be36e83SMatthew G. Knepley owned:
9383be36e83SMatthew G. Knepley   remotePoint->rank  = rank;
9393be36e83SMatthew G. Knepley   remotePoint->index = localPoint;
9403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9413be36e83SMatthew G. Knepley }
9423be36e83SMatthew G. Knepley 
943d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
944d71ae5a4SJacob Faibussowitsch {
9453be36e83SMatthew G. Knepley   PetscSF         sf;
9463be36e83SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
9473be36e83SMatthew G. Knepley   PetscInt        Nl, idx;
9483be36e83SMatthew G. Knepley 
9493be36e83SMatthew G. Knepley   PetscFunctionBegin;
9503be36e83SMatthew G. Knepley   *isShared = PETSC_FALSE;
9519566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
9529566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
9533ba16761SJacob Faibussowitsch   if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS);
9549566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, Nl, locals, &idx));
9559371c9d4SSatish Balay   if (idx >= 0) {
9569371c9d4SSatish Balay     *isShared = PETSC_TRUE;
9573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9589371c9d4SSatish Balay   }
9599566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
9609566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
9613be36e83SMatthew G. Knepley   if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
9623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9633be36e83SMatthew G. Knepley }
9643be36e83SMatthew G. Knepley 
965d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
966d71ae5a4SJacob Faibussowitsch {
9673be36e83SMatthew G. Knepley   const PetscInt *cone;
9683be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9693be36e83SMatthew G. Knepley   PetscBool       cShared = PETSC_TRUE;
9703be36e83SMatthew G. Knepley 
9713be36e83SMatthew G. Knepley   PetscFunctionBegin;
9729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
9739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
9743be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
9753be36e83SMatthew G. Knepley     PetscBool pointShared;
9763be36e83SMatthew G. Knepley 
9779566063dSJacob Faibussowitsch     PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
9783be36e83SMatthew G. Knepley     cShared = (PetscBool)(cShared && pointShared);
9793be36e83SMatthew G. Knepley   }
9803be36e83SMatthew G. Knepley   *isShared = coneSize ? cShared : PETSC_FALSE;
9813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9823be36e83SMatthew G. Knepley }
9833be36e83SMatthew G. Knepley 
984d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
985d71ae5a4SJacob Faibussowitsch {
9863be36e83SMatthew G. Knepley   const PetscInt *cone;
9873be36e83SMatthew G. Knepley   PetscInt        coneSize, c;
9883be36e83SMatthew G. Knepley   PetscSFNode     cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1};
9893be36e83SMatthew G. Knepley 
9903be36e83SMatthew G. Knepley   PetscFunctionBegin;
9919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
9929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, p, &cone));
9933be36e83SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
9943be36e83SMatthew G. Knepley     PetscSFNode rcp;
9955f80ce2aSJacob Faibussowitsch     PetscBool   mapFailed;
9963be36e83SMatthew G. Knepley 
9979566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
9985f80ce2aSJacob Faibussowitsch     if (mapFailed) {
9993be36e83SMatthew G. Knepley       cmin = missing;
10003be36e83SMatthew G. Knepley     } else {
10013be36e83SMatthew G. Knepley       cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10023be36e83SMatthew G. Knepley     }
10033be36e83SMatthew G. Knepley   }
10043be36e83SMatthew G. Knepley   *cpmin = coneSize ? cmin : missing;
10053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10063be36e83SMatthew G. Knepley }
10073be36e83SMatthew G. Knepley 
10083be36e83SMatthew G. Knepley /*
10093be36e83SMatthew G. Knepley   Each shared face has an entry in the candidates array:
10103be36e83SMatthew G. Knepley     (-1, coneSize-1), {(global cone point)}
10113be36e83SMatthew G. Knepley   where the set is missing the point p which we use as the key for the face
10123be36e83SMatthew G. Knepley */
1013d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
1014d71ae5a4SJacob Faibussowitsch {
10153be36e83SMatthew G. Knepley   MPI_Comm        comm;
10163be36e83SMatthew G. Knepley   const PetscInt *support;
1017cf4dc471SVaclav Hapla   PetscInt        supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10183be36e83SMatthew G. Knepley   PetscMPIInt     rank;
10193be36e83SMatthew G. Knepley 
10203be36e83SMatthew G. Knepley   PetscFunctionBegin;
10219566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
10229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
10249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
10259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPointHeight(dm, p, &height));
1026cf4dc471SVaclav Hapla   if (!overlap && height <= cellHeight + 1) {
1027cf4dc471SVaclav Hapla     /* cells can't be shared for non-overlapping meshes */
102863a3b9bcSJacob 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));
10293ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1030cf4dc471SVaclav Hapla   }
10319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
10329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupport(dm, p, &support));
10339566063dSJacob Faibussowitsch   if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
10343be36e83SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
10353be36e83SMatthew G. Knepley     const PetscInt  face = support[s];
10363be36e83SMatthew G. Knepley     const PetscInt *cone;
10373be36e83SMatthew G. Knepley     PetscSFNode     cpmin = {-1, -1}, rp = {-1, -1};
10383be36e83SMatthew G. Knepley     PetscInt        coneSize, c, f;
10393be36e83SMatthew G. Knepley     PetscBool       isShared = PETSC_FALSE;
10403be36e83SMatthew G. Knepley     PetscHashIJKey  key;
10413be36e83SMatthew G. Knepley 
10423be36e83SMatthew G. Knepley     /* Only add point once */
104363a3b9bcSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Support face %" PetscInt_FMT "\n", rank, face));
10443be36e83SMatthew G. Knepley     key.i = p;
10453be36e83SMatthew G. Knepley     key.j = face;
10469566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJGet(faceHash, key, &f));
10473be36e83SMatthew G. Knepley     if (f >= 0) continue;
10489566063dSJacob Faibussowitsch     PetscCall(DMPlexConeIsShared(dm, face, &isShared));
10499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
10509566063dSJacob Faibussowitsch     PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
10513be36e83SMatthew G. Knepley     if (debug) {
105263a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d]      Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
105363a3b9bcSJacob 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));
10543be36e83SMatthew G. Knepley     }
10553be36e83SMatthew G. Knepley     if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
10569566063dSJacob Faibussowitsch       PetscCall(PetscHMapIJSet(faceHash, key, p));
10573be36e83SMatthew G. Knepley       if (candidates) {
105863a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d]     ", rank, face, idx, rank));
10599566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
10609566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, face, &cone));
10613be36e83SMatthew G. Knepley         candidates[off + idx].rank    = -1;
10623be36e83SMatthew G. Knepley         candidates[off + idx++].index = coneSize - 1;
10633be36e83SMatthew G. Knepley         candidates[off + idx].rank    = rank;
10643be36e83SMatthew G. Knepley         candidates[off + idx++].index = face;
10653be36e83SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
10663be36e83SMatthew G. Knepley           const PetscInt cp = cone[c];
10673be36e83SMatthew G. Knepley 
10683be36e83SMatthew G. Knepley           if (cp == p) continue;
10699566063dSJacob Faibussowitsch           PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
107063a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
10713be36e83SMatthew G. Knepley           ++idx;
10723be36e83SMatthew G. Knepley         }
10739566063dSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
10743be36e83SMatthew G. Knepley       } else {
10753be36e83SMatthew G. Knepley         /* Add cone size to section */
107663a3b9bcSJacob Faibussowitsch         if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Scheduling shared face %" PetscInt_FMT "\n", rank, face));
10779566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
10789566063dSJacob Faibussowitsch         PetscCall(PetscHMapIJSet(faceHash, key, p));
10799566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
10803be36e83SMatthew G. Knepley       }
10813be36e83SMatthew G. Knepley     }
10823be36e83SMatthew G. Knepley   }
10833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10843be36e83SMatthew G. Knepley }
10853be36e83SMatthew G. Knepley 
10862e72742cSMatthew G. Knepley /*@
108720f4b53cSBarry Smith   DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation
10882e72742cSMatthew G. Knepley 
108920f4b53cSBarry Smith   Collective
10902e72742cSMatthew G. Knepley 
10912e72742cSMatthew G. Knepley   Input Parameters:
109220f4b53cSBarry Smith + dm      - The interpolated `DMPLEX`
109320f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points
10942e72742cSMatthew G. Knepley 
1095f0cfc026SVaclav Hapla   Level: developer
10962e72742cSMatthew G. Knepley 
109720f4b53cSBarry Smith    Note:
109820f4b53cSBarry Smith    Debugging for this process can be turned on with the options: `-dm_interp_pre_view` `-petscsf_interp_pre_view` `-petscsection_interp_candidate_view` `-petscsection_interp_candidate_remote_view` `-petscsection_interp_claim_view` `-petscsf_interp_pre_view` `-dmplex_interp_debug`
10992e72742cSMatthew G. Knepley 
110020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()`
11012e72742cSMatthew G. Knepley @*/
1102d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
1103d71ae5a4SJacob Faibussowitsch {
11043be36e83SMatthew G. Knepley   MPI_Comm           comm;
11053be36e83SMatthew G. Knepley   PetscHMapIJ        remoteHash;
11063be36e83SMatthew G. Knepley   PetscHMapI         claimshash;
11073be36e83SMatthew G. Knepley   PetscSection       candidateSection, candidateRemoteSection, claimSection;
11083be36e83SMatthew G. Knepley   PetscSFNode       *candidates, *candidatesRemote, *claims;
11092e72742cSMatthew G. Knepley   const PetscInt    *localPoints, *rootdegree;
11102e72742cSMatthew G. Knepley   const PetscSFNode *remotePoints;
11113be36e83SMatthew G. Knepley   PetscInt           ov, Nr, r, Nl, l;
11123be36e83SMatthew G. Knepley   PetscInt           candidatesSize, candidatesRemoteSize, claimsSize;
11133be36e83SMatthew G. Knepley   PetscBool          flg, debug = PETSC_FALSE;
1114f0cfc026SVaclav Hapla   PetscMPIInt        rank;
11152e72742cSMatthew G. Knepley 
11162e72742cSMatthew G. Knepley   PetscFunctionBegin;
1117f0cfc026SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1118064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11199566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &flg));
11203ba16761SJacob Faibussowitsch   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
11213be36e83SMatthew G. Knepley   /* Set initial SF so that lower level queries work */
11229566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, pointSF));
11239566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &ov));
112628b400f6SJacob Faibussowitsch   PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
11279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
11289566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
11299566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
11309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
11313be36e83SMatthew G. Knepley   /* Step 0: Precalculations */
11329566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
113308401ef6SPierre Jolivet   PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
11349566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJCreate(&remoteHash));
11353be36e83SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
11363be36e83SMatthew G. Knepley     PetscHashIJKey key;
11372e72742cSMatthew G. Knepley     key.i = remotePoints[l].index;
11382e72742cSMatthew G. Knepley     key.j = remotePoints[l].rank;
11399566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJSet(remoteHash, key, l));
11407bffde78SMichael Lange   }
114166aa2a39SMatthew G. Knepley   /*   Compute root degree to identify shared points */
11429566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
11439566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
11449566063dSJacob Faibussowitsch   PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
11453be36e83SMatthew G. Knepley   /*
11463be36e83SMatthew G. Knepley   1) Loop over each leaf point $p$ at depth $d$ in the SF
11473be36e83SMatthew G. Knepley   \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
11483be36e83SMatthew G. Knepley   \begin{itemize}
11493be36e83SMatthew G. Knepley     \item all cone points of $f$ are shared
11503be36e83SMatthew G. Knepley     \item $p$ is the cone point with smallest canonical number
11513be36e83SMatthew G. Knepley   \end{itemize}
11523be36e83SMatthew G. Knepley   \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
11533be36e83SMatthew 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
11543be36e83SMatthew G. Knepley   \item Send the root face from the root back to all leaf process
11553be36e83SMatthew G. Knepley   \item Leaf processes add the shared face to the SF
11563be36e83SMatthew G. Knepley   */
11573be36e83SMatthew G. Knepley   /* Step 1: Construct section+SFNode array
11583be36e83SMatthew G. Knepley        The section has entries for all shared faces for which we have a leaf point in the cone
1159da81f932SPierre Jolivet        The array holds candidate shared faces, each face is referred to by the leaf point */
11609566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &candidateSection));
11619566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
11627bffde78SMichael Lange   {
11633be36e83SMatthew G. Knepley     PetscHMapIJ faceHash;
11642e72742cSMatthew G. Knepley 
11659566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJCreate(&faceHash));
11663be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11673be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11682e72742cSMatthew G. Knepley 
116963a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  First pass leaf point %" PetscInt_FMT "\n", rank, p));
11709566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
11712e72742cSMatthew G. Knepley     }
11729566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJClear(faceHash));
11739566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(candidateSection));
11749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
11759566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesSize, &candidates));
11763be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
11773be36e83SMatthew G. Knepley       const PetscInt p = localPoints[l];
11782e72742cSMatthew G. Knepley 
117963a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Second pass leaf point %" PetscInt_FMT "\n", rank, p));
11809566063dSJacob Faibussowitsch       PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
11812e72742cSMatthew G. Knepley     }
11829566063dSJacob Faibussowitsch     PetscCall(PetscHMapIJDestroy(&faceHash));
11839566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
11847bffde78SMichael Lange   }
11859566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
11869566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
11879566063dSJacob Faibussowitsch   PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
11883be36e83SMatthew G. Knepley   /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
11892e72742cSMatthew G. Knepley   /*   Note that this section is indexed by offsets into leaves, not by point number */
11907bffde78SMichael Lange   {
11917bffde78SMichael Lange     PetscSF   sfMulti, sfInverse, sfCandidates;
11927bffde78SMichael Lange     PetscInt *remoteOffsets;
11932e72742cSMatthew G. Knepley 
11949566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
11959566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
11969566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
11979566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
11989566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
11999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
12009566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
12019566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12029566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE));
12039566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfInverse));
12049566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfCandidates));
12059566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
12062e72742cSMatthew G. Knepley 
12079566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12089566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12099566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12107bffde78SMichael Lange   }
12113be36e83SMatthew 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 */
12127bffde78SMichael Lange   {
1213a03d55ffSStefano Zampini     PetscHMapIJKLRemote faceTable;
12143be36e83SMatthew G. Knepley     PetscInt            idx, idx2;
12153be36e83SMatthew G. Knepley 
1216a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteCreate(&faceTable));
12172e72742cSMatthew G. Knepley     /* There is a section point for every leaf attached to a given root point */
12183be36e83SMatthew G. Knepley     for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12192e72742cSMatthew G. Knepley       PetscInt deg;
12203be36e83SMatthew G. Knepley 
12212e72742cSMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
12222e72742cSMatthew G. Knepley         PetscInt offset, dof, d;
12232e72742cSMatthew G. Knepley 
12249566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
12259566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
12263be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12272e72742cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12283be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
12293be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
12303be36e83SMatthew G. Knepley           const PetscSFNode      rface = candidatesRemote[hidx + 1];
12313be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
12323be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
12333be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
12342e72742cSMatthew G. Knepley           const PetscInt        *join = NULL;
1235a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
12363be36e83SMatthew G. Knepley           PetscHashIter          iter;
12375f80ce2aSJacob Faibussowitsch           PetscBool              missing, mapToLocalPointFailed = PETSC_FALSE;
12382e72742cSMatthew G. Knepley           PetscInt               points[1024], p, joinSize;
12392e72742cSMatthew G. Knepley 
12409371c9d4SSatish Balay           if (debug)
12419371c9d4SSatish Balay             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,
12429371c9d4SSatish Balay                                               rface.index, r, idx, d, Np));
124363a3b9bcSJacob 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);
12443be36e83SMatthew G. Knepley           fcp0.rank  = rank;
12453be36e83SMatthew G. Knepley           fcp0.index = r;
12463be36e83SMatthew G. Knepley           d += Np;
12473be36e83SMatthew G. Knepley           /* Put remote face in hash table */
12483be36e83SMatthew G. Knepley           key.i = fcp0;
12493be36e83SMatthew G. Knepley           key.j = fcone[0];
12503be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
12513be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
12529566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
1253a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
12543be36e83SMatthew G. Knepley           if (missing) {
125563a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1256a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
12573be36e83SMatthew G. Knepley           } else {
12583be36e83SMatthew G. Knepley             PetscSFNode oface;
12593be36e83SMatthew G. Knepley 
1260a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
12613be36e83SMatthew G. Knepley             if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
126263a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1263a03d55ffSStefano Zampini               PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
12643be36e83SMatthew G. Knepley             }
12653be36e83SMatthew G. Knepley           }
12663be36e83SMatthew G. Knepley           /* Check for local face */
12672e72742cSMatthew G. Knepley           points[0] = r;
12683be36e83SMatthew G. Knepley           for (p = 1; p < Np; ++p) {
12699566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
12705f80ce2aSJacob Faibussowitsch             if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
127163a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
12727bffde78SMichael Lange           }
12735f80ce2aSJacob Faibussowitsch           if (mapToLocalPointFailed) continue;
12749566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
12757bffde78SMichael Lange           if (joinSize == 1) {
12763be36e83SMatthew G. Knepley             PetscSFNode lface;
12773be36e83SMatthew G. Knepley             PetscSFNode oface;
12783be36e83SMatthew G. Knepley 
12793be36e83SMatthew G. Knepley             /* Always replace with local face */
12803be36e83SMatthew G. Knepley             lface.rank  = rank;
12813be36e83SMatthew G. Knepley             lface.index = join[0];
1282a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
12839371c9d4SSatish Balay             if (debug)
12849371c9d4SSatish Balay               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));
1285a03d55ffSStefano Zampini             PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface));
12867bffde78SMichael Lange           }
12879566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
12883be36e83SMatthew G. Knepley         }
12893be36e83SMatthew G. Knepley       }
12903be36e83SMatthew G. Knepley       /* Put back faces for this root */
12913be36e83SMatthew G. Knepley       for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
12923be36e83SMatthew G. Knepley         PetscInt offset, dof, d;
12933be36e83SMatthew G. Knepley 
12949566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
12959566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
12963be36e83SMatthew G. Knepley         /* dof may include many faces from the remote process */
12973be36e83SMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12983be36e83SMatthew G. Knepley           const PetscInt         hidx  = offset + d;
12993be36e83SMatthew G. Knepley           const PetscInt         Np    = candidatesRemote[hidx].index + 1;
13003be36e83SMatthew G. Knepley           const PetscSFNode     *fcone = &candidatesRemote[hidx + 2];
13013be36e83SMatthew G. Knepley           PetscSFNode            fcp0;
13023be36e83SMatthew G. Knepley           const PetscSFNode      pmax = {PETSC_MAX_INT, PETSC_MAX_INT};
1303a03d55ffSStefano Zampini           PetscHMapIJKLRemoteKey key;
13043be36e83SMatthew G. Knepley           PetscHashIter          iter;
13053be36e83SMatthew G. Knepley           PetscBool              missing;
13063be36e83SMatthew G. Knepley 
130763a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d]  Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
130863a3b9bcSJacob Faibussowitsch           PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13093be36e83SMatthew G. Knepley           fcp0.rank  = rank;
13103be36e83SMatthew G. Knepley           fcp0.index = r;
13113be36e83SMatthew G. Knepley           d += Np;
13123be36e83SMatthew G. Knepley           /* Find remote face in hash table */
13133be36e83SMatthew G. Knepley           key.i = fcp0;
13143be36e83SMatthew G. Knepley           key.j = fcone[0];
13153be36e83SMatthew G. Knepley           key.k = Np > 2 ? fcone[1] : pmax;
13163be36e83SMatthew G. Knepley           key.l = Np > 3 ? fcone[2] : pmax;
13179566063dSJacob Faibussowitsch           PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13189371c9d4SSatish Balay           if (debug)
13199371c9d4SSatish Balay             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,
13209371c9d4SSatish Balay                                               key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index));
1321a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
132263a3b9bcSJacob Faibussowitsch           PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1323a03d55ffSStefano Zampini           PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
13247bffde78SMichael Lange         }
13257bffde78SMichael Lange       }
13267bffde78SMichael Lange     }
13279566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
1328a03d55ffSStefano Zampini     PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable));
13297bffde78SMichael Lange   }
13303be36e83SMatthew G. Knepley   /* Step 4: Push back owned faces */
13317bffde78SMichael Lange   {
13327bffde78SMichael Lange     PetscSF      sfMulti, sfClaims, sfPointNew;
13337bffde78SMichael Lange     PetscSFNode *remotePointsNew;
13342e72742cSMatthew G. Knepley     PetscInt    *remoteOffsets, *localPointsNew;
13353be36e83SMatthew G. Knepley     PetscInt     pStart, pEnd, r, NlNew, p;
13362e72742cSMatthew G. Knepley 
13373be36e83SMatthew G. Knepley     /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
13389566063dSJacob Faibussowitsch     PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
13399566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(comm, &claimSection));
13409566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
13419566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
13429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
13439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(claimsSize, &claims));
13443be36e83SMatthew G. Knepley     for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
13459566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13469566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE));
13479566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfClaims));
13489566063dSJacob Faibussowitsch     PetscCall(PetscFree(remoteOffsets));
13499566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
13509566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
13519566063dSJacob Faibussowitsch     PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
13523be36e83SMatthew G. Knepley     /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
13533be36e83SMatthew 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 */
13549566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&claimshash));
13553be36e83SMatthew G. Knepley     for (r = 0; r < Nr; ++r) {
13563be36e83SMatthew G. Knepley       PetscInt dof, off, d;
13572e72742cSMatthew G. Knepley 
135863a3b9bcSJacob Faibussowitsch       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]  Checking root for claims %" PetscInt_FMT "\n", rank, r));
13599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
13609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
13612e72742cSMatthew G. Knepley       for (d = 0; d < dof;) {
13623be36e83SMatthew G. Knepley         if (claims[off + d].rank >= 0) {
13633be36e83SMatthew G. Knepley           const PetscInt  faceInd = off + d;
13643be36e83SMatthew G. Knepley           const PetscInt  Np      = candidates[off + d].index;
13652e72742cSMatthew G. Knepley           const PetscInt *join    = NULL;
13662e72742cSMatthew G. Knepley           PetscInt        joinSize, points[1024], c;
13672e72742cSMatthew G. Knepley 
136863a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
13693be36e83SMatthew G. Knepley           points[0] = r;
137063a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[0]));
13713be36e83SMatthew G. Knepley           for (c = 0, d += 2; c < Np; ++c, ++d) {
13729566063dSJacob Faibussowitsch             PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
137363a3b9bcSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]      point %" PetscInt_FMT "\n", rank, points[c + 1]));
13742e72742cSMatthew G. Knepley           }
13759566063dSJacob Faibussowitsch           PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
13762e72742cSMatthew G. Knepley           if (joinSize == 1) {
13773be36e83SMatthew G. Knepley             if (claims[faceInd].rank == rank) {
137863a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
13793be36e83SMatthew G. Knepley             } else {
138063a3b9bcSJacob Faibussowitsch               if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Found local face %" PetscInt_FMT "\n", rank, join[0]));
13819566063dSJacob Faibussowitsch               PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
13822e72742cSMatthew G. Knepley             }
13833be36e83SMatthew G. Knepley           } else {
13849566063dSJacob Faibussowitsch             if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    Failed to find face\n", rank));
13853be36e83SMatthew G. Knepley           }
13869566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
13873be36e83SMatthew G. Knepley         } else {
138863a3b9bcSJacob Faibussowitsch           if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d]    No claim for point %" PetscInt_FMT "\n", rank, r));
13893be36e83SMatthew G. Knepley           d += claims[off + d].index + 1;
13907bffde78SMichael Lange         }
13917bffde78SMichael Lange       }
13923be36e83SMatthew G. Knepley     }
13939566063dSJacob Faibussowitsch     if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
13943be36e83SMatthew G. Knepley     /* Step 6) Create new pointSF from hashed claims */
13959566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
13969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
13979566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
13989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
13993be36e83SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
14003be36e83SMatthew G. Knepley       localPointsNew[l]        = localPoints[l];
14013be36e83SMatthew G. Knepley       remotePointsNew[l].index = remotePoints[l].index;
14023be36e83SMatthew G. Knepley       remotePointsNew[l].rank  = remotePoints[l].rank;
14037bffde78SMichael Lange     }
14043be36e83SMatthew G. Knepley     p = Nl;
14059566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
14063be36e83SMatthew G. Knepley     /* We sort new points, and assume they are numbered after all existing points */
14079566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(NlNew, &localPointsNew[Nl]));
14083be36e83SMatthew G. Knepley     for (p = Nl; p < Nl + NlNew; ++p) {
14093be36e83SMatthew G. Knepley       PetscInt off;
14109566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
14111dca8a05SBarry 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);
14123be36e83SMatthew G. Knepley       remotePointsNew[p] = claims[off];
14137bffde78SMichael Lange     }
14149566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sfPointNew));
14159566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14169566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sfPointNew));
14179566063dSJacob Faibussowitsch     PetscCall(DMSetPointSF(dm, sfPointNew));
14189566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1419d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
14209566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfPointNew));
14219566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&claimshash));
14227bffde78SMichael Lange   }
14239566063dSJacob Faibussowitsch   PetscCall(PetscHMapIJDestroy(&remoteHash));
14249566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateSection));
14259566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&candidateRemoteSection));
14269566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&claimSection));
14279566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidates));
14289566063dSJacob Faibussowitsch   PetscCall(PetscFree(candidatesRemote));
14299566063dSJacob Faibussowitsch   PetscCall(PetscFree(claims));
14309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
14313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14327bffde78SMichael Lange }
14337bffde78SMichael Lange 
1434248eb259SVaclav Hapla /*@
143580330477SMatthew G. Knepley   DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
143680330477SMatthew G. Knepley 
143720f4b53cSBarry Smith   Collective
143880330477SMatthew G. Knepley 
143920f4b53cSBarry Smith   Input Parameter:
144020f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices
144180330477SMatthew G. Knepley 
144280330477SMatthew G. Knepley   Output Parameter:
144320f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object
144480330477SMatthew G. Knepley 
144580330477SMatthew G. Knepley   Level: intermediate
144680330477SMatthew G. Knepley 
144720f4b53cSBarry Smith   Note:
14487fb59074SVaclav Hapla     Labels and coordinates are copied.
144943eeeb2dSStefano Zampini 
145020f4b53cSBarry Smith   Developer Note:
145120f4b53cSBarry Smith     It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`.
14529ade3219SVaclav Hapla 
145320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
145480330477SMatthew G. Knepley @*/
1455d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
1456d71ae5a4SJacob Faibussowitsch {
1457a7748839SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
14589a5b13a2SMatthew G Knepley   DM                     idm, odm = dm;
14597bffde78SMichael Lange   PetscSF                sfPoint;
14602e1b13c2SMatthew G. Knepley   PetscInt               depth, dim, d;
146110a67516SMatthew G. Knepley   const char            *name;
1462b325530aSVaclav Hapla   PetscBool              flg = PETSC_TRUE;
14639f074e33SMatthew G Knepley 
14649f074e33SMatthew G Knepley   PetscFunctionBegin;
146510a67516SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
146610a67516SMatthew G. Knepley   PetscValidPointer(dmInt, 2);
14679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
14689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
14699566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
14709566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
147108401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1472827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_FULL) {
14739566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
147476b791aaSMatthew G. Knepley     idm = dm;
1475b21b8912SMatthew G. Knepley   } else {
14769a5b13a2SMatthew G Knepley     for (d = 1; d < dim; ++d) {
14779a5b13a2SMatthew G Knepley       /* Create interpolated mesh */
14789566063dSJacob Faibussowitsch       PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
14799566063dSJacob Faibussowitsch       PetscCall(DMSetType(idm, DMPLEX));
14809566063dSJacob Faibussowitsch       PetscCall(DMSetDimension(idm, dim));
14817bffde78SMichael Lange       if (depth > 0) {
14829566063dSJacob Faibussowitsch         PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
14839566063dSJacob Faibussowitsch         PetscCall(DMGetPointSF(odm, &sfPoint));
1484d7d32a9aSMatthew G. Knepley         if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
148594488200SVaclav Hapla         {
14863be36e83SMatthew G. Knepley           /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
148794488200SVaclav Hapla           PetscInt nroots;
14889566063dSJacob Faibussowitsch           PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
14899566063dSJacob Faibussowitsch           if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
149094488200SVaclav Hapla         }
14917bffde78SMichael Lange       }
14929566063dSJacob Faibussowitsch       if (odm != dm) PetscCall(DMDestroy(&odm));
14939a5b13a2SMatthew G Knepley       odm = idm;
14949f074e33SMatthew G Knepley     }
14959566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
14969566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)idm, name));
14979566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, idm));
14989566063dSJacob Faibussowitsch     PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
14999566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
15009566063dSJacob Faibussowitsch     if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
150184699f70SSatish Balay   }
1502827c4036SVaclav Hapla   /* This function makes the mesh fully interpolated on all ranks */
1503827c4036SVaclav Hapla   {
1504d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)idm->data;
1505827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1506827c4036SVaclav Hapla   }
15075de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
15089a5b13a2SMatthew G Knepley   *dmInt = idm;
15099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
15103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15119f074e33SMatthew G Knepley }
151207b0a1fcSMatthew G Knepley 
151380330477SMatthew G. Knepley /*@
151480330477SMatthew G. Knepley   DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
151580330477SMatthew G. Knepley 
151620f4b53cSBarry Smith   Collective
151780330477SMatthew G. Knepley 
151880330477SMatthew G. Knepley   Input Parameter:
151920f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates
152080330477SMatthew G. Knepley 
152180330477SMatthew G. Knepley   Output Parameter:
152220f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates
152380330477SMatthew G. Knepley 
152480330477SMatthew G. Knepley   Level: intermediate
152580330477SMatthew G. Knepley 
152620f4b53cSBarry Smith   Note:
152720f4b53cSBarry Smith   This is typically used when adding pieces other than vertices to a mesh
152880330477SMatthew G. Knepley 
152920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
153080330477SMatthew G. Knepley @*/
1531d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
1532d71ae5a4SJacob Faibussowitsch {
153307b0a1fcSMatthew G Knepley   Vec          coordinatesA, coordinatesB;
153443eeeb2dSStefano Zampini   VecType      vtype;
153507b0a1fcSMatthew G Knepley   PetscSection coordSectionA, coordSectionB;
153607b0a1fcSMatthew G Knepley   PetscScalar *coordsA, *coordsB;
15370bedd6beSMatthew G. Knepley   PetscInt     spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
153890a8aa44SJed Brown   PetscInt     cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
153943eeeb2dSStefano Zampini   PetscBool    lc = PETSC_FALSE;
154007b0a1fcSMatthew G Knepley 
154107b0a1fcSMatthew G Knepley   PetscFunctionBegin;
154243eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
154343eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
15443ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
15459566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmA, &cdim));
15469566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dmB, cdim));
15479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
15489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
154963a3b9bcSJacob 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);
155061a622f3SMatthew G. Knepley   /* Copy over discretization if it exists */
155161a622f3SMatthew G. Knepley   {
155261a622f3SMatthew G. Knepley     DM                 cdmA, cdmB;
155361a622f3SMatthew G. Knepley     PetscDS            dsA, dsB;
155461a622f3SMatthew G. Knepley     PetscObject        objA, objB;
155561a622f3SMatthew G. Knepley     PetscClassId       idA, idB;
155661a622f3SMatthew G. Knepley     const PetscScalar *constants;
155761a622f3SMatthew G. Knepley     PetscInt           cdim, Nc;
155861a622f3SMatthew G. Knepley 
15599566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmA, &cdmA));
15609566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmB, &cdmB));
15619566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmA, 0, NULL, &objA));
15629566063dSJacob Faibussowitsch     PetscCall(DMGetField(cdmB, 0, NULL, &objB));
15639566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objA, &idA));
15649566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetClassId(objB, &idB));
156561a622f3SMatthew G. Knepley     if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
15669566063dSJacob Faibussowitsch       PetscCall(DMSetField(cdmB, 0, NULL, objA));
15679566063dSJacob Faibussowitsch       PetscCall(DMCreateDS(cdmB));
15689566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmA, &dsA));
15699566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdmB, &dsB));
15709566063dSJacob Faibussowitsch       PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
15719566063dSJacob Faibussowitsch       PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
15729566063dSJacob Faibussowitsch       PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
15739566063dSJacob Faibussowitsch       PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
157461a622f3SMatthew G. Knepley     }
157561a622f3SMatthew G. Knepley   }
15769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
15779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
15789566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
15799566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
15803ba16761SJacob Faibussowitsch   if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS);
15819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
15823ba16761SJacob Faibussowitsch   if (!Nf) PetscFunctionReturn(PETSC_SUCCESS);
158363a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1584df26b574SMatthew G. Knepley   if (!coordSectionB) {
1585df26b574SMatthew G. Knepley     PetscInt dim;
1586df26b574SMatthew G. Knepley 
15879566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
15889566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dmA, &dim));
15899566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
15909566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1591df26b574SMatthew G. Knepley   }
15929566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
15939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
15949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
15959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
159643eeeb2dSStefano Zampini   if (cStartA <= cS && cS < cEndA) { /* localized coordinates */
159763a3b9bcSJacob 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);
159843eeeb2dSStefano Zampini     cS = cS - cStartA + cStartB;
159943eeeb2dSStefano Zampini     cE = vEndB;
160043eeeb2dSStefano Zampini     lc = PETSC_TRUE;
160143eeeb2dSStefano Zampini   } else {
160243eeeb2dSStefano Zampini     cS = vStartB;
160343eeeb2dSStefano Zampini     cE = vEndB;
160443eeeb2dSStefano Zampini   }
16059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
160607b0a1fcSMatthew G Knepley   for (v = vStartB; v < vEndB; ++v) {
16079566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
16089566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
160907b0a1fcSMatthew G Knepley   }
161043eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
161143eeeb2dSStefano Zampini     PetscInt c;
161243eeeb2dSStefano Zampini 
161343eeeb2dSStefano Zampini     for (c = cS - cStartB; c < cEndB - cStartB; c++) {
161443eeeb2dSStefano Zampini       PetscInt dof;
161543eeeb2dSStefano Zampini 
16169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
16179566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSectionB, c + cStartB, dof));
16189566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof));
161943eeeb2dSStefano Zampini     }
162043eeeb2dSStefano Zampini   }
16219566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSectionB));
16229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
16239566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
16249566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
16259566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
16269566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
16279566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(coordinatesA, &d));
16289566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinatesB, d));
16299566063dSJacob Faibussowitsch   PetscCall(VecGetType(coordinatesA, &vtype));
16309566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinatesB, vtype));
16319566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesA, &coordsA));
16329566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinatesB, &coordsB));
163307b0a1fcSMatthew G Knepley   for (v = 0; v < vEndB - vStartB; ++v) {
163443eeeb2dSStefano Zampini     PetscInt offA, offB;
163543eeeb2dSStefano Zampini 
16369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
16379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1638ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
163943eeeb2dSStefano Zampini   }
164043eeeb2dSStefano Zampini   if (lc) { /* localized coordinates */
164143eeeb2dSStefano Zampini     PetscInt c;
164243eeeb2dSStefano Zampini 
164343eeeb2dSStefano Zampini     for (c = cS - cStartB; c < cEndB - cStartB; c++) {
164443eeeb2dSStefano Zampini       PetscInt dof, offA, offB;
164543eeeb2dSStefano Zampini 
16469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA));
16479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB));
16489566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof));
16499566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(coordsB + offB, coordsA + offA, dof));
165007b0a1fcSMatthew G Knepley     }
165107b0a1fcSMatthew G Knepley   }
16529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesA, &coordsA));
16539566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinatesB, &coordsB));
16549566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
16559566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinatesB));
16563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
165707b0a1fcSMatthew G Knepley }
16585c386225SMatthew G. Knepley 
16594e3744c5SMatthew G. Knepley /*@
16604e3744c5SMatthew G. Knepley   DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
16614e3744c5SMatthew G. Knepley 
166220f4b53cSBarry Smith   Collective
16634e3744c5SMatthew G. Knepley 
16644e3744c5SMatthew G. Knepley   Input Parameter:
166520f4b53cSBarry Smith . dm - The complete `DMPLEX` object
16664e3744c5SMatthew G. Knepley 
16674e3744c5SMatthew G. Knepley   Output Parameter:
166820f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices
16694e3744c5SMatthew G. Knepley 
16704e3744c5SMatthew G. Knepley   Level: intermediate
16714e3744c5SMatthew G. Knepley 
167220f4b53cSBarry Smith   Note:
167395452b02SPatrick Sanan     It does not copy over the coordinates.
167443eeeb2dSStefano Zampini 
167520f4b53cSBarry Smith   Developer Note:
167620f4b53cSBarry Smith   Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
16779ade3219SVaclav Hapla 
167820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
16794e3744c5SMatthew G. Knepley @*/
1680d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
1681d71ae5a4SJacob Faibussowitsch {
1682827c4036SVaclav Hapla   DMPlexInterpolatedFlag interpolated;
16834e3744c5SMatthew G. Knepley   DM                     udm;
1684412e9a14SMatthew G. Knepley   PetscInt               dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
16854e3744c5SMatthew G. Knepley 
16864e3744c5SMatthew G. Knepley   PetscFunctionBegin;
168743eeeb2dSStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
168843eeeb2dSStefano Zampini   PetscValidPointer(dmUnint, 2);
1689*172ee266SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0));
16909566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
16919566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpolated));
169208401ef6SPierre Jolivet   PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1693827c4036SVaclav Hapla   if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1694827c4036SVaclav Hapla     /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
16959566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
1696595d4abbSMatthew G. Knepley     *dmUnint = dm;
16973ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
16984e3744c5SMatthew G. Knepley   }
16999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
17009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17019566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
17029566063dSJacob Faibussowitsch   PetscCall(DMSetType(udm, DMPLEX));
17039566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(udm, dim));
17049566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(udm, cStart, vEnd));
17054e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1706595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17074e3744c5SMatthew G. Knepley 
17089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17094e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17104e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17114e3744c5SMatthew G. Knepley 
17124e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
17134e3744c5SMatthew G. Knepley     }
17149566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17159566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1716595d4abbSMatthew G. Knepley     maxConeSize = PetscMax(maxConeSize, coneSize);
17174e3744c5SMatthew G. Knepley   }
17189566063dSJacob Faibussowitsch   PetscCall(DMSetUp(udm));
17199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxConeSize, &cone));
17204e3744c5SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1721595d4abbSMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
17224e3744c5SMatthew G. Knepley 
17239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17244e3744c5SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
17254e3744c5SMatthew G. Knepley       const PetscInt p = closure[cl];
17264e3744c5SMatthew G. Knepley 
17274e3744c5SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
17284e3744c5SMatthew G. Knepley     }
17299566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(udm, c, cone));
17314e3744c5SMatthew G. Knepley   }
17329566063dSJacob Faibussowitsch   PetscCall(PetscFree(cone));
17339566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(udm));
17349566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(udm));
17355c7de58aSMatthew G. Knepley   /* Reduce SF */
17365c7de58aSMatthew G. Knepley   {
17375c7de58aSMatthew G. Knepley     PetscSF            sfPoint, sfPointUn;
17385c7de58aSMatthew G. Knepley     const PetscSFNode *remotePoints;
17395c7de58aSMatthew G. Knepley     const PetscInt    *localPoints;
17405c7de58aSMatthew G. Knepley     PetscSFNode       *remotePointsUn;
17415c7de58aSMatthew G. Knepley     PetscInt          *localPointsUn;
174222fd0ad9SVaclav Hapla     PetscInt           numRoots, numLeaves, l;
17435c7de58aSMatthew G. Knepley     PetscInt           numLeavesUn = 0, n = 0;
17445c7de58aSMatthew G. Knepley 
17455c7de58aSMatthew G. Knepley     /* Get original SF information */
17469566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm, &sfPoint));
1747d7d32a9aSMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
17489566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(udm, &sfPointUn));
17499566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
175022fd0ad9SVaclav Hapla     if (numRoots >= 0) {
17515c7de58aSMatthew G. Knepley       /* Allocate space for cells and vertices */
175222fd0ad9SVaclav Hapla       for (l = 0; l < numLeaves; ++l) {
175322fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
175422fd0ad9SVaclav Hapla 
175522fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
175622fd0ad9SVaclav Hapla       }
17575c7de58aSMatthew G. Knepley       /* Fill in leaves */
17589566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
17599566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
17605c7de58aSMatthew G. Knepley       for (l = 0; l < numLeaves; l++) {
176122fd0ad9SVaclav Hapla         const PetscInt p = localPoints[l];
176222fd0ad9SVaclav Hapla 
176322fd0ad9SVaclav Hapla         if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
176422fd0ad9SVaclav Hapla           localPointsUn[n]        = p;
17655c7de58aSMatthew G. Knepley           remotePointsUn[n].rank  = remotePoints[l].rank;
17665c7de58aSMatthew G. Knepley           remotePointsUn[n].index = remotePoints[l].index;
17675c7de58aSMatthew G. Knepley           ++n;
17685c7de58aSMatthew G. Knepley         }
17695c7de58aSMatthew G. Knepley       }
177063a3b9bcSJacob Faibussowitsch       PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
177122fd0ad9SVaclav Hapla       PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
17725c7de58aSMatthew G. Knepley     }
17735c7de58aSMatthew G. Knepley   }
1774827c4036SVaclav Hapla   /* This function makes the mesh fully uninterpolated on all ranks */
1775827c4036SVaclav Hapla   {
1776d6e9e4f7SVaclav Hapla     DM_Plex *plex      = (DM_Plex *)udm->data;
1777827c4036SVaclav Hapla     plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1778827c4036SVaclav Hapla   }
17795de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1780d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
17814e3744c5SMatthew G. Knepley   *dmUnint = udm;
1782*172ee266SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0));
17833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17844e3744c5SMatthew G. Knepley }
1785a7748839SVaclav Hapla 
1786d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1787d71ae5a4SJacob Faibussowitsch {
1788a7748839SVaclav Hapla   PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1789a7748839SVaclav Hapla   MPI_Comm comm;
1790a7748839SVaclav Hapla 
1791a7748839SVaclav Hapla   PetscFunctionBegin;
17929566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
17939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
17949566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1795a7748839SVaclav Hapla 
1796a7748839SVaclav Hapla   if (depth == dim) {
1797a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_FULL;
1798a7748839SVaclav Hapla     if (!dim) goto finish;
1799a7748839SVaclav Hapla 
1800a7748839SVaclav Hapla     /* Check points at height = dim are vertices (have no cones) */
18019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1802a7748839SVaclav Hapla     for (p = pStart; p < pEnd; p++) {
18039566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1804a7748839SVaclav Hapla       if (coneSize) {
1805a7748839SVaclav Hapla         *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1806a7748839SVaclav Hapla         goto finish;
1807a7748839SVaclav Hapla       }
1808a7748839SVaclav Hapla     }
1809a7748839SVaclav Hapla 
1810a7748839SVaclav Hapla     /* Check points at height < dim have cones */
1811a7748839SVaclav Hapla     for (h = 0; h < dim; h++) {
18129566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1813a7748839SVaclav Hapla       for (p = pStart; p < pEnd; p++) {
18149566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1815a7748839SVaclav Hapla         if (!coneSize) {
1816a7748839SVaclav Hapla           *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1817a7748839SVaclav Hapla           goto finish;
1818a7748839SVaclav Hapla         }
1819a7748839SVaclav Hapla       }
1820a7748839SVaclav Hapla     }
1821a7748839SVaclav Hapla   } else if (depth == 1) {
1822a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_NONE;
1823a7748839SVaclav Hapla   } else {
1824a7748839SVaclav Hapla     *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1825a7748839SVaclav Hapla   }
1826a7748839SVaclav Hapla finish:
18273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1828a7748839SVaclav Hapla }
1829a7748839SVaclav Hapla 
1830a7748839SVaclav Hapla /*@
183120f4b53cSBarry Smith   DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated.
1832a7748839SVaclav Hapla 
1833a7748839SVaclav Hapla   Not Collective
1834a7748839SVaclav Hapla 
1835a7748839SVaclav Hapla   Input Parameter:
183620f4b53cSBarry Smith . dm      - The `DMPLEX` object
1837a7748839SVaclav Hapla 
1838a7748839SVaclav Hapla   Output Parameter:
183920f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1840a7748839SVaclav Hapla 
1841a7748839SVaclav Hapla   Level: intermediate
1842a7748839SVaclav Hapla 
1843a7748839SVaclav Hapla   Notes:
184420f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective
18459ade3219SVaclav Hapla   so the results can be different on different ranks in special cases.
184620f4b53cSBarry Smith   However, `DMPlexInterpolate()` guarantees the result is the same on all.
18479ade3219SVaclav Hapla 
184820f4b53cSBarry Smith   Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`.
1849a7748839SVaclav Hapla 
18509ade3219SVaclav Hapla   Developer Notes:
185120f4b53cSBarry Smith   Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`.
18529ade3219SVaclav Hapla 
185320f4b53cSBarry Smith   If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called.
18549ade3219SVaclav Hapla   It checks the actual topology and sets plex->interpolated on each rank separately to one of
185520f4b53cSBarry Smith   `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`.
18569ade3219SVaclav Hapla 
185720f4b53cSBarry Smith   If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated.
18589ade3219SVaclav Hapla 
185920f4b53cSBarry Smith   `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`,
186020f4b53cSBarry Smith   and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
18619ade3219SVaclav Hapla 
186220f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1863a7748839SVaclav Hapla @*/
1864d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1865d71ae5a4SJacob Faibussowitsch {
1866a7748839SVaclav Hapla   DM_Plex *plex = (DM_Plex *)dm->data;
1867a7748839SVaclav Hapla 
1868a7748839SVaclav Hapla   PetscFunctionBegin;
1869a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1870a7748839SVaclav Hapla   PetscValidPointer(interpolated, 2);
1871a7748839SVaclav Hapla   if (plex->interpolated < 0) {
18729566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
187376bd3646SJed Brown   } else if (PetscDefined(USE_DEBUG)) {
1874a7748839SVaclav Hapla     DMPlexInterpolatedFlag flg;
1875a7748839SVaclav Hapla 
18769566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
187708401ef6SPierre Jolivet     PetscCheck(flg == plex->interpolated, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1878a7748839SVaclav Hapla   }
1879a7748839SVaclav Hapla   *interpolated = plex->interpolated;
18803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1881a7748839SVaclav Hapla }
1882a7748839SVaclav Hapla 
1883a7748839SVaclav Hapla /*@
188420f4b53cSBarry Smith   DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner).
1885a7748839SVaclav Hapla 
18862666ff3cSVaclav Hapla   Collective
1887a7748839SVaclav Hapla 
1888a7748839SVaclav Hapla   Input Parameter:
188920f4b53cSBarry Smith . dm      - The `DMPLEX` object
1890a7748839SVaclav Hapla 
1891a7748839SVaclav Hapla   Output Parameter:
189220f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1893a7748839SVaclav Hapla 
1894a7748839SVaclav Hapla   Level: intermediate
1895a7748839SVaclav Hapla 
1896a7748839SVaclav Hapla   Notes:
189720f4b53cSBarry Smith   Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks.
18989ade3219SVaclav Hapla 
189920f4b53cSBarry Smith   This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks.
19009ade3219SVaclav Hapla 
19019ade3219SVaclav Hapla   Developer Notes:
190220f4b53cSBarry Smith   Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`.
19039ade3219SVaclav Hapla 
190420f4b53cSBarry Smith   If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated.
190520f4b53cSBarry Smith   `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
190620f4b53cSBarry Smith   if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`,
19079ade3219SVaclav Hapla   otherwise sets plex->interpolatedCollective = plex->interpolated.
19089ade3219SVaclav Hapla 
190920f4b53cSBarry Smith   If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective.
1910a7748839SVaclav Hapla 
191120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
1912a7748839SVaclav Hapla @*/
1913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
1914d71ae5a4SJacob Faibussowitsch {
1915a7748839SVaclav Hapla   DM_Plex  *plex  = (DM_Plex *)dm->data;
1916a7748839SVaclav Hapla   PetscBool debug = PETSC_FALSE;
1917a7748839SVaclav Hapla 
1918a7748839SVaclav Hapla   PetscFunctionBegin;
1919a7748839SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1920a7748839SVaclav Hapla   PetscValidPointer(interpolated, 2);
19219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
1922a7748839SVaclav Hapla   if (plex->interpolatedCollective < 0) {
1923a7748839SVaclav Hapla     DMPlexInterpolatedFlag min, max;
1924a7748839SVaclav Hapla     MPI_Comm               comm;
1925a7748839SVaclav Hapla 
19269566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19279566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
1928712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
1929712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
1930a7748839SVaclav Hapla     if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
1931a7748839SVaclav Hapla     if (debug) {
1932a7748839SVaclav Hapla       PetscMPIInt rank;
1933a7748839SVaclav Hapla 
19349566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
19359566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
19369566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
1937a7748839SVaclav Hapla     }
1938a7748839SVaclav Hapla   }
1939a7748839SVaclav Hapla   *interpolated = plex->interpolatedCollective;
19403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1941a7748839SVaclav Hapla }
1942