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
PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP (HMapIJKLRemote,PetscHMapIJKLRemoteKey,PetscSFNode,PetscHMapIJKLRemoteKeyHash,PetscHMapIJKLRemoteKeyEqual,_PetscInvalidSFNode))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 */
DMPlexGetRawFaces_Internal(DM dm,DMPolytopeType ct,const PetscInt cone[],PetscInt * numFaces,const DMPolytopeType * faceTypes[],const PetscInt * faceSizes[],const PetscInt * faces[])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 {
48442f3b32SStefano Zampini DMPolytopeType *typesTmp = NULL;
49442f3b32SStefano Zampini PetscInt *sizesTmp = NULL, *facesTmp = NULL;
50442f3b32SStefano Zampini PetscInt *tmp;
51442f3b32SStefano Zampini PetscInt maxConeSize, maxSupportSize, maxSize;
52442f3b32SStefano Zampini PetscInt getSize = 0;
53439ece16SMatthew G. Knepley
54439ece16SMatthew G. Knepley PetscFunctionBegin;
55439ece16SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
564f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3);
579566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
58442f3b32SStefano Zampini maxSize = PetscMax(maxConeSize, maxSupportSize);
59442f3b32SStefano Zampini if (faceTypes) getSize += maxSize;
60442f3b32SStefano Zampini if (faceSizes) getSize += maxSize;
61442f3b32SStefano Zampini if (faces) getSize += PetscSqr(maxSize);
62442f3b32SStefano Zampini PetscCall(DMGetWorkArray(dm, getSize, MPIU_INT, &tmp));
63442f3b32SStefano Zampini if (faceTypes) {
64442f3b32SStefano Zampini typesTmp = (DMPolytopeType *)tmp;
65442f3b32SStefano Zampini tmp += maxSize;
66442f3b32SStefano Zampini }
67442f3b32SStefano Zampini if (faceSizes) {
68442f3b32SStefano Zampini sizesTmp = tmp;
69442f3b32SStefano Zampini tmp += maxSize;
70442f3b32SStefano Zampini }
71442f3b32SStefano Zampini if (faces) facesTmp = tmp;
72ba2698f1SMatthew G. Knepley switch (ct) {
73ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT:
74ba2698f1SMatthew G. Knepley if (numFaces) *numFaces = 0;
756f5c9017SMatthew G. Knepley if (faceTypes) *faceTypes = typesTmp;
766f5c9017SMatthew G. Knepley if (faceSizes) *faceSizes = sizesTmp;
776f5c9017SMatthew G. Knepley if (faces) *faces = facesTmp;
78ba2698f1SMatthew G. Knepley break;
79ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT:
80412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 2;
81412e9a14SMatthew G. Knepley if (faceTypes) {
829371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_POINT;
839371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_POINT;
84412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
85412e9a14SMatthew G. Knepley }
86412e9a14SMatthew G. Knepley if (faceSizes) {
879371c9d4SSatish Balay sizesTmp[0] = 1;
889371c9d4SSatish Balay sizesTmp[1] = 1;
89412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
90412e9a14SMatthew G. Knepley }
91c49d9212SMatthew G. Knepley if (faces) {
929371c9d4SSatish Balay facesTmp[0] = cone[0];
939371c9d4SSatish Balay facesTmp[1] = cone[1];
94c49d9212SMatthew G. Knepley *faces = facesTmp;
95c49d9212SMatthew G. Knepley }
96412e9a14SMatthew G. Knepley break;
97412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR:
98c49d9212SMatthew G. Knepley if (numFaces) *numFaces = 2;
99412e9a14SMatthew G. Knepley if (faceTypes) {
1009371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_POINT;
1019371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_POINT;
102412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
103412e9a14SMatthew G. Knepley }
104412e9a14SMatthew G. Knepley if (faceSizes) {
1059371c9d4SSatish Balay sizesTmp[0] = 1;
1069371c9d4SSatish Balay sizesTmp[1] = 1;
107412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
108412e9a14SMatthew G. Knepley }
109412e9a14SMatthew G. Knepley if (faces) {
1109371c9d4SSatish Balay facesTmp[0] = cone[0];
1119371c9d4SSatish Balay facesTmp[1] = cone[1];
112412e9a14SMatthew G. Knepley *faces = facesTmp;
113412e9a14SMatthew G. Knepley }
114c49d9212SMatthew G. Knepley break;
115ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE:
116412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 3;
117412e9a14SMatthew G. Knepley if (faceTypes) {
1189371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT;
1199371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT;
1209371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEGMENT;
121412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
122412e9a14SMatthew G. Knepley }
123412e9a14SMatthew G. Knepley if (faceSizes) {
1249371c9d4SSatish Balay sizesTmp[0] = 2;
1259371c9d4SSatish Balay sizesTmp[1] = 2;
1269371c9d4SSatish Balay sizesTmp[2] = 2;
127412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
128412e9a14SMatthew G. Knepley }
1299a5b13a2SMatthew G Knepley if (faces) {
1309371c9d4SSatish Balay facesTmp[0] = cone[0];
1319371c9d4SSatish Balay facesTmp[1] = cone[1];
1329371c9d4SSatish Balay facesTmp[2] = cone[1];
1339371c9d4SSatish Balay facesTmp[3] = cone[2];
1349371c9d4SSatish Balay facesTmp[4] = cone[2];
1359371c9d4SSatish Balay facesTmp[5] = cone[0];
1369a5b13a2SMatthew G Knepley *faces = facesTmp;
1379a5b13a2SMatthew G Knepley }
1389f074e33SMatthew G Knepley break;
139ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL:
1409a5b13a2SMatthew G Knepley /* Vertices follow right hand rule */
141412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4;
142412e9a14SMatthew G. Knepley if (faceTypes) {
1439371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT;
1449371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT;
1459371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEGMENT;
1469371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEGMENT;
147412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
148412e9a14SMatthew G. Knepley }
149412e9a14SMatthew G. Knepley if (faceSizes) {
1509371c9d4SSatish Balay sizesTmp[0] = 2;
1519371c9d4SSatish Balay sizesTmp[1] = 2;
1529371c9d4SSatish Balay sizesTmp[2] = 2;
1539371c9d4SSatish Balay sizesTmp[3] = 2;
154412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
155412e9a14SMatthew G. Knepley }
1569a5b13a2SMatthew G Knepley if (faces) {
1579371c9d4SSatish Balay facesTmp[0] = cone[0];
1589371c9d4SSatish Balay facesTmp[1] = cone[1];
1599371c9d4SSatish Balay facesTmp[2] = cone[1];
1609371c9d4SSatish Balay facesTmp[3] = cone[2];
1619371c9d4SSatish Balay facesTmp[4] = cone[2];
1629371c9d4SSatish Balay facesTmp[5] = cone[3];
1639371c9d4SSatish Balay facesTmp[6] = cone[3];
1649371c9d4SSatish Balay facesTmp[7] = cone[0];
1659a5b13a2SMatthew G Knepley *faces = facesTmp;
1669a5b13a2SMatthew G Knepley }
167412e9a14SMatthew G. Knepley break;
168412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR:
1699a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4;
170412e9a14SMatthew G. Knepley if (faceTypes) {
1719371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT;
1729371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT;
1739371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1749371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR;
175412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
176412e9a14SMatthew G. Knepley }
177412e9a14SMatthew G. Knepley if (faceSizes) {
1789371c9d4SSatish Balay sizesTmp[0] = 2;
1799371c9d4SSatish Balay sizesTmp[1] = 2;
1809371c9d4SSatish Balay sizesTmp[2] = 2;
1819371c9d4SSatish Balay sizesTmp[3] = 2;
182412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
183412e9a14SMatthew G. Knepley }
184412e9a14SMatthew G. Knepley if (faces) {
1859371c9d4SSatish Balay facesTmp[0] = cone[0];
1869371c9d4SSatish Balay facesTmp[1] = cone[1];
1879371c9d4SSatish Balay facesTmp[2] = cone[2];
1889371c9d4SSatish Balay facesTmp[3] = cone[3];
1899371c9d4SSatish Balay facesTmp[4] = cone[0];
1909371c9d4SSatish Balay facesTmp[5] = cone[2];
1919371c9d4SSatish Balay facesTmp[6] = cone[1];
1929371c9d4SSatish Balay facesTmp[7] = cone[3];
193412e9a14SMatthew G. Knepley *faces = facesTmp;
194412e9a14SMatthew G. Knepley }
1959f074e33SMatthew G Knepley break;
196ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON:
1972e1b13c2SMatthew G. Knepley /* Vertices of first face follow right hand rule and normal points away from last vertex */
198412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4;
199412e9a14SMatthew G. Knepley if (faceTypes) {
2009371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2019371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2029371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_TRIANGLE;
2039371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_TRIANGLE;
204412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
205412e9a14SMatthew G. Knepley }
206412e9a14SMatthew G. Knepley if (faceSizes) {
2079371c9d4SSatish Balay sizesTmp[0] = 3;
2089371c9d4SSatish Balay sizesTmp[1] = 3;
2099371c9d4SSatish Balay sizesTmp[2] = 3;
2109371c9d4SSatish Balay sizesTmp[3] = 3;
211412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
212412e9a14SMatthew G. Knepley }
2139a5b13a2SMatthew G Knepley if (faces) {
2149371c9d4SSatish Balay facesTmp[0] = cone[0];
2159371c9d4SSatish Balay facesTmp[1] = cone[1];
2169371c9d4SSatish Balay facesTmp[2] = cone[2];
2179371c9d4SSatish Balay facesTmp[3] = cone[0];
2189371c9d4SSatish Balay facesTmp[4] = cone[3];
2199371c9d4SSatish Balay facesTmp[5] = cone[1];
2209371c9d4SSatish Balay facesTmp[6] = cone[0];
2219371c9d4SSatish Balay facesTmp[7] = cone[2];
2229371c9d4SSatish Balay facesTmp[8] = cone[3];
2239371c9d4SSatish Balay facesTmp[9] = cone[2];
2249371c9d4SSatish Balay facesTmp[10] = cone[1];
2259371c9d4SSatish Balay facesTmp[11] = cone[3];
2269a5b13a2SMatthew G Knepley *faces = facesTmp;
2279a5b13a2SMatthew G Knepley }
2289a5b13a2SMatthew G Knepley break;
229ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON:
230e368ef20SMatthew G. Knepley /* 7--------6
231e368ef20SMatthew G. Knepley /| /|
232e368ef20SMatthew G. Knepley / | / |
233e368ef20SMatthew G. Knepley 4--------5 |
234e368ef20SMatthew G. Knepley | | | |
235e368ef20SMatthew G. Knepley | | | |
236e368ef20SMatthew G. Knepley | 1--------2
237e368ef20SMatthew G. Knepley | / | /
238e368ef20SMatthew G. Knepley |/ |/
239e368ef20SMatthew G. Knepley 0--------3
240e368ef20SMatthew G. Knepley */
241412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6;
242412e9a14SMatthew G. Knepley if (faceTypes) {
2439371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
2449371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
2459371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2469371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2479371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
2489371c9d4SSatish Balay typesTmp[5] = DM_POLYTOPE_QUADRILATERAL;
249412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
250412e9a14SMatthew G. Knepley }
251412e9a14SMatthew G. Knepley if (faceSizes) {
2529371c9d4SSatish Balay sizesTmp[0] = 4;
2539371c9d4SSatish Balay sizesTmp[1] = 4;
2549371c9d4SSatish Balay sizesTmp[2] = 4;
2559371c9d4SSatish Balay sizesTmp[3] = 4;
2569371c9d4SSatish Balay sizesTmp[4] = 4;
2579371c9d4SSatish Balay sizesTmp[5] = 4;
258412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
259412e9a14SMatthew G. Knepley }
2609a5b13a2SMatthew G Knepley if (faces) {
2619371c9d4SSatish Balay facesTmp[0] = cone[0];
2629371c9d4SSatish Balay facesTmp[1] = cone[1];
2639371c9d4SSatish Balay facesTmp[2] = cone[2];
2649371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */
2659371c9d4SSatish Balay facesTmp[4] = cone[4];
2669371c9d4SSatish Balay facesTmp[5] = cone[5];
2679371c9d4SSatish Balay facesTmp[6] = cone[6];
2689371c9d4SSatish Balay facesTmp[7] = cone[7]; /* Top */
2699371c9d4SSatish Balay facesTmp[8] = cone[0];
2709371c9d4SSatish Balay facesTmp[9] = cone[3];
2719371c9d4SSatish Balay facesTmp[10] = cone[5];
2729371c9d4SSatish Balay facesTmp[11] = cone[4]; /* Front */
2739371c9d4SSatish Balay facesTmp[12] = cone[2];
2749371c9d4SSatish Balay facesTmp[13] = cone[1];
2759371c9d4SSatish Balay facesTmp[14] = cone[7];
2769371c9d4SSatish Balay facesTmp[15] = cone[6]; /* Back */
2779371c9d4SSatish Balay facesTmp[16] = cone[3];
2789371c9d4SSatish Balay facesTmp[17] = cone[2];
2799371c9d4SSatish Balay facesTmp[18] = cone[6];
2809371c9d4SSatish Balay facesTmp[19] = cone[5]; /* Right */
2819371c9d4SSatish Balay facesTmp[20] = cone[0];
2829371c9d4SSatish Balay facesTmp[21] = cone[4];
2839371c9d4SSatish Balay facesTmp[22] = cone[7];
2849371c9d4SSatish Balay facesTmp[23] = cone[1]; /* Left */
2859a5b13a2SMatthew G Knepley *faces = facesTmp;
2869a5b13a2SMatthew G Knepley }
28799836e0eSStefano Zampini break;
288ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM:
289412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5;
290412e9a14SMatthew G. Knepley if (faceTypes) {
2919371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE;
2929371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE;
2939371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_QUADRILATERAL;
2949371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_QUADRILATERAL;
2959371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_QUADRILATERAL;
296412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
297412e9a14SMatthew G. Knepley }
298412e9a14SMatthew G. Knepley if (faceSizes) {
2999371c9d4SSatish Balay sizesTmp[0] = 3;
3009371c9d4SSatish Balay sizesTmp[1] = 3;
3019371c9d4SSatish Balay sizesTmp[2] = 4;
3029371c9d4SSatish Balay sizesTmp[3] = 4;
3039371c9d4SSatish Balay sizesTmp[4] = 4;
304412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
305412e9a14SMatthew G. Knepley }
306ba2698f1SMatthew G. Knepley if (faces) {
3079371c9d4SSatish Balay facesTmp[0] = cone[0];
3089371c9d4SSatish Balay facesTmp[1] = cone[1];
3099371c9d4SSatish Balay facesTmp[2] = cone[2]; /* Bottom */
3109371c9d4SSatish Balay facesTmp[3] = cone[3];
3119371c9d4SSatish Balay facesTmp[4] = cone[4];
3129371c9d4SSatish Balay facesTmp[5] = cone[5]; /* Top */
3139371c9d4SSatish Balay facesTmp[6] = cone[0];
3149371c9d4SSatish Balay facesTmp[7] = cone[2];
3159371c9d4SSatish Balay facesTmp[8] = cone[4];
3169371c9d4SSatish Balay facesTmp[9] = cone[3]; /* Back left */
3179371c9d4SSatish Balay facesTmp[10] = cone[2];
3189371c9d4SSatish Balay facesTmp[11] = cone[1];
3199371c9d4SSatish Balay facesTmp[12] = cone[5];
3209371c9d4SSatish Balay facesTmp[13] = cone[4]; /* Front */
3219371c9d4SSatish Balay facesTmp[14] = cone[1];
3229371c9d4SSatish Balay facesTmp[15] = cone[0];
3239371c9d4SSatish Balay facesTmp[16] = cone[3];
3249371c9d4SSatish Balay facesTmp[17] = cone[5]; /* Back right */
325ba2698f1SMatthew G. Knepley *faces = facesTmp;
32699836e0eSStefano Zampini }
32799836e0eSStefano Zampini break;
328ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR:
329412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5;
330412e9a14SMatthew G. Knepley if (faceTypes) {
3319371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE;
3329371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE;
3339371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3349371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3359371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
336412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
337412e9a14SMatthew G. Knepley }
338412e9a14SMatthew G. Knepley if (faceSizes) {
3399371c9d4SSatish Balay sizesTmp[0] = 3;
3409371c9d4SSatish Balay sizesTmp[1] = 3;
3419371c9d4SSatish Balay sizesTmp[2] = 4;
3429371c9d4SSatish Balay sizesTmp[3] = 4;
3439371c9d4SSatish Balay sizesTmp[4] = 4;
344412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
345412e9a14SMatthew G. Knepley }
34699836e0eSStefano Zampini if (faces) {
3479371c9d4SSatish Balay facesTmp[0] = cone[0];
3489371c9d4SSatish Balay facesTmp[1] = cone[1];
3499371c9d4SSatish Balay facesTmp[2] = cone[2]; /* Bottom */
3509371c9d4SSatish Balay facesTmp[3] = cone[3];
3519371c9d4SSatish Balay facesTmp[4] = cone[4];
3529371c9d4SSatish Balay facesTmp[5] = cone[5]; /* Top */
3539371c9d4SSatish Balay facesTmp[6] = cone[0];
3549371c9d4SSatish Balay facesTmp[7] = cone[1];
3559371c9d4SSatish Balay facesTmp[8] = cone[3];
3569371c9d4SSatish Balay facesTmp[9] = cone[4]; /* Back left */
3579371c9d4SSatish Balay facesTmp[10] = cone[1];
3589371c9d4SSatish Balay facesTmp[11] = cone[2];
3599371c9d4SSatish Balay facesTmp[12] = cone[4];
3609371c9d4SSatish Balay facesTmp[13] = cone[5]; /* Back right */
3619371c9d4SSatish Balay facesTmp[14] = cone[2];
3629371c9d4SSatish Balay facesTmp[15] = cone[0];
3639371c9d4SSatish Balay facesTmp[16] = cone[5];
3649371c9d4SSatish Balay facesTmp[17] = cone[3]; /* Front */
36599836e0eSStefano Zampini *faces = facesTmp;
36699836e0eSStefano Zampini }
367412e9a14SMatthew G. Knepley break;
368412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR:
369412e9a14SMatthew G. Knepley /* 7--------6
370412e9a14SMatthew G. Knepley /| /|
371412e9a14SMatthew G. Knepley / | / |
372412e9a14SMatthew G. Knepley 4--------5 |
373412e9a14SMatthew G. Knepley | | | |
374412e9a14SMatthew G. Knepley | | | |
375412e9a14SMatthew G. Knepley | 3--------2
376412e9a14SMatthew G. Knepley | / | /
377412e9a14SMatthew G. Knepley |/ |/
378412e9a14SMatthew G. Knepley 0--------1
379412e9a14SMatthew G. Knepley */
380412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6;
381412e9a14SMatthew G. Knepley if (faceTypes) {
3829371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
3839371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_QUADRILATERAL;
3849371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3859371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3869371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR;
3879371c9d4SSatish Balay typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR;
388412e9a14SMatthew G. Knepley *faceTypes = typesTmp;
389412e9a14SMatthew G. Knepley }
390412e9a14SMatthew G. Knepley if (faceSizes) {
3919371c9d4SSatish Balay sizesTmp[0] = 4;
3929371c9d4SSatish Balay sizesTmp[1] = 4;
3939371c9d4SSatish Balay sizesTmp[2] = 4;
3949371c9d4SSatish Balay sizesTmp[3] = 4;
3959371c9d4SSatish Balay sizesTmp[4] = 4;
3969371c9d4SSatish Balay sizesTmp[5] = 4;
397412e9a14SMatthew G. Knepley *faceSizes = sizesTmp;
398412e9a14SMatthew G. Knepley }
399412e9a14SMatthew G. Knepley if (faces) {
4009371c9d4SSatish Balay facesTmp[0] = cone[0];
4019371c9d4SSatish Balay facesTmp[1] = cone[1];
4029371c9d4SSatish Balay facesTmp[2] = cone[2];
4039371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */
4049371c9d4SSatish Balay facesTmp[4] = cone[4];
4059371c9d4SSatish Balay facesTmp[5] = cone[5];
4069371c9d4SSatish Balay facesTmp[6] = cone[6];
4079371c9d4SSatish Balay facesTmp[7] = cone[7]; /* Top */
4089371c9d4SSatish Balay facesTmp[8] = cone[0];
4099371c9d4SSatish Balay facesTmp[9] = cone[1];
4109371c9d4SSatish Balay facesTmp[10] = cone[4];
4119371c9d4SSatish Balay facesTmp[11] = cone[5]; /* Front */
4129371c9d4SSatish Balay facesTmp[12] = cone[1];
4139371c9d4SSatish Balay facesTmp[13] = cone[2];
4149371c9d4SSatish Balay facesTmp[14] = cone[5];
4159371c9d4SSatish Balay facesTmp[15] = cone[6]; /* Right */
4169371c9d4SSatish Balay facesTmp[16] = cone[2];
4179371c9d4SSatish Balay facesTmp[17] = cone[3];
4189371c9d4SSatish Balay facesTmp[18] = cone[6];
4199371c9d4SSatish Balay facesTmp[19] = cone[7]; /* Back */
4209371c9d4SSatish Balay facesTmp[20] = cone[3];
4219371c9d4SSatish Balay facesTmp[21] = cone[0];
4229371c9d4SSatish Balay facesTmp[22] = cone[7];
4239371c9d4SSatish Balay facesTmp[23] = cone[4]; /* Left */
424412e9a14SMatthew G. Knepley *faces = facesTmp;
425412e9a14SMatthew G. Knepley }
42699836e0eSStefano Zampini break;
427da9060c4SMatthew G. Knepley case DM_POLYTOPE_PYRAMID:
428da9060c4SMatthew G. Knepley /*
429da9060c4SMatthew G. Knepley 4----
430da9060c4SMatthew G. Knepley |\-\ \-----
431da9060c4SMatthew G. Knepley | \ -\ \
432da9060c4SMatthew G. Knepley | 1--\-----2
433da9060c4SMatthew G. Knepley | / \ /
434da9060c4SMatthew G. Knepley |/ \ /
435da9060c4SMatthew G. Knepley 0--------3
436da9060c4SMatthew G. Knepley */
437da9060c4SMatthew G. Knepley if (numFaces) *numFaces = 5;
438da9060c4SMatthew G. Knepley if (faceTypes) {
439da9060c4SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL;
4409371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE;
4419371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_TRIANGLE;
4429371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_TRIANGLE;
4439371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_TRIANGLE;
444da9060c4SMatthew G. Knepley *faceTypes = typesTmp;
445da9060c4SMatthew G. Knepley }
446da9060c4SMatthew G. Knepley if (faceSizes) {
447da9060c4SMatthew G. Knepley sizesTmp[0] = 4;
4489371c9d4SSatish Balay sizesTmp[1] = 3;
4499371c9d4SSatish Balay sizesTmp[2] = 3;
4509371c9d4SSatish Balay sizesTmp[3] = 3;
4519371c9d4SSatish Balay sizesTmp[4] = 3;
452da9060c4SMatthew G. Knepley *faceSizes = sizesTmp;
453da9060c4SMatthew G. Knepley }
454da9060c4SMatthew G. Knepley if (faces) {
4559371c9d4SSatish Balay facesTmp[0] = cone[0];
4569371c9d4SSatish Balay facesTmp[1] = cone[1];
4579371c9d4SSatish Balay facesTmp[2] = cone[2];
4589371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */
4599371c9d4SSatish Balay facesTmp[4] = cone[0];
4609371c9d4SSatish Balay facesTmp[5] = cone[3];
4619371c9d4SSatish Balay facesTmp[6] = cone[4]; /* Front */
4629371c9d4SSatish Balay facesTmp[7] = cone[3];
4639371c9d4SSatish Balay facesTmp[8] = cone[2];
4649371c9d4SSatish Balay facesTmp[9] = cone[4]; /* Right */
4659371c9d4SSatish Balay facesTmp[10] = cone[2];
4669371c9d4SSatish Balay facesTmp[11] = cone[1];
4679371c9d4SSatish Balay facesTmp[12] = cone[4]; /* Back */
4689371c9d4SSatish Balay facesTmp[13] = cone[1];
4699371c9d4SSatish Balay facesTmp[14] = cone[0];
4709371c9d4SSatish Balay facesTmp[15] = cone[4]; /* Left */
471da9060c4SMatthew G. Knepley *faces = facesTmp;
472da9060c4SMatthew G. Knepley }
473da9060c4SMatthew G. Knepley break;
474d71ae5a4SJacob Faibussowitsch default:
475d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]);
47699836e0eSStefano Zampini }
4773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
47899836e0eSStefano Zampini }
47999836e0eSStefano Zampini
DMPlexRestoreRawFaces_Internal(DM dm,DMPolytopeType ct,const PetscInt cone[],PetscInt * numFaces,const DMPolytopeType * faceTypes[],const PetscInt * faceSizes[],const PetscInt * faces[])480d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[])
481d71ae5a4SJacob Faibussowitsch {
48299836e0eSStefano Zampini PetscFunctionBegin;
4839566063dSJacob Faibussowitsch if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes));
484442f3b32SStefano Zampini else if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes));
485442f3b32SStefano Zampini else if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces));
486442f3b32SStefano Zampini if (faceTypes) *faceTypes = NULL;
487442f3b32SStefano Zampini if (faceSizes) *faceSizes = NULL;
488442f3b32SStefano Zampini if (faces) *faces = NULL;
4893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49099836e0eSStefano Zampini }
49199836e0eSStefano Zampini
4929a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */
DMPlexInterpolateFaces_Internal(DM dm,PetscInt cellDepth,DM idm)4939fbdc704SMatthew G. Knepley PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm)
494d71ae5a4SJacob Faibussowitsch {
495412e9a14SMatthew G. Knepley DMLabel ctLabel;
496a03d55ffSStefano Zampini PetscHMapIJKL faceTable;
497412e9a14SMatthew G. Knepley PetscInt faceTypeNum[DM_NUM_POLYTOPES];
4981afe9b7dSMatthew G. Knepley PetscInt depth, pStart, Np, cStart, cEnd, fStart, fEnd, vStart, vEnd;
499a03d55ffSStefano Zampini PetscInt cntFaces, *facesId, minCone;
5009f074e33SMatthew G Knepley
5019f074e33SMatthew G Knepley PetscFunctionBegin;
5029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
503a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLCreate(&faceTable));
5049566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES));
5051afe9b7dSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
5069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd));
5071afe9b7dSMatthew G. Knepley // If the range incorporates the vertices, it means we have a non-manifold topology, so choose just cells
5081afe9b7dSMatthew G. Knepley if (cStart <= vStart && cEnd >= vEnd) cEnd = vStart;
5095c2c0cecSMatthew G. Knepley // Number new faces and save face vertices in hash table
5101afe9b7dSMatthew G. Knepley // If depth > cellDepth, meaning we are interpolating faces, put the new (d-1)-faces after them
5111afe9b7dSMatthew G. Knepley // otherwise, we are interpolating cells, so put the faces after the vertices
5129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart));
513412e9a14SMatthew G. Knepley fEnd = fStart;
514591a860aSStefano Zampini
5151690c2aeSBarry Smith minCone = PETSC_INT_MAX;
5165c2c0cecSMatthew G. Knepley cntFaces = 0;
5175c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
518591a860aSStefano Zampini const PetscInt *cone;
519591a860aSStefano Zampini DMPolytopeType ct;
520ed896b67SJose E. Roman PetscInt numFaces = 0, coneSize;
521591a860aSStefano Zampini
522591a860aSStefano Zampini PetscCall(DMPlexGetCellType(dm, c, &ct));
523591a860aSStefano Zampini PetscCall(DMPlexGetCone(dm, c, &cone));
524a03d55ffSStefano Zampini PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
525a03d55ffSStefano Zampini for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone);
5266f5c9017SMatthew G. Knepley // Ignore faces since they are interpolated
5276f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL));
528591a860aSStefano Zampini cntFaces += numFaces;
529591a860aSStefano Zampini }
5301690c2aeSBarry Smith // Encode so that we can use 0 as an excluded value, instead of PETSC_INT_MAX
531a03d55ffSStefano Zampini minCone = -(minCone - 1);
532591a860aSStefano Zampini
533591a860aSStefano Zampini PetscCall(PetscMalloc1(cntFaces, &facesId));
534591a860aSStefano Zampini
5355c2c0cecSMatthew G. Knepley cntFaces = 0;
5365c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
537412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces;
538412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes;
539ba2698f1SMatthew G. Knepley DMPolytopeType ct;
5405c2c0cecSMatthew G. Knepley PetscInt numFaces, foff = 0;
54199836e0eSStefano Zampini
5429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct));
5439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone));
5446f5c9017SMatthew G. Knepley // Ignore faces since they are interpolated
5456f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5469566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5476f5c9017SMatthew G. Knepley } else {
5486f5c9017SMatthew G. Knepley numFaces = 0;
5496f5c9017SMatthew G. Knepley }
5505c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
551412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf];
552412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf];
553412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff];
5549a5b13a2SMatthew G Knepley PetscHashIJKLKey key;
555e8f14785SLisandro Dalcin PetscHashIter iter;
556e8f14785SLisandro Dalcin PetscBool missing;
5579f074e33SMatthew G Knepley
5585f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize);
559a03d55ffSStefano Zampini key.i = face[0] + minCone;
560a03d55ffSStefano Zampini key.j = faceSize > 1 ? face[1] + minCone : 0;
561a03d55ffSStefano Zampini key.k = faceSize > 2 ? face[2] + minCone : 0;
562a03d55ffSStefano Zampini key.l = faceSize > 3 ? face[3] + minCone : 0;
5639566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
564a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
565e9fa77a1SMatthew G. Knepley if (missing) {
566591a860aSStefano Zampini facesId[cntFaces] = fEnd;
567a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++));
568412e9a14SMatthew G. Knepley ++faceTypeNum[faceType];
569a03d55ffSStefano Zampini } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
570591a860aSStefano Zampini cntFaces++;
5719a5b13a2SMatthew G Knepley }
5726f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
57399836e0eSStefano Zampini }
574412e9a14SMatthew G. Knepley /* We need to number faces contiguously among types */
575412e9a14SMatthew G. Knepley {
576412e9a14SMatthew G. Knepley PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0;
57799836e0eSStefano Zampini
5789371c9d4SSatish Balay for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {
5799371c9d4SSatish Balay if (faceTypeNum[ct]) ++numFT;
5809371c9d4SSatish Balay faceTypeStart[ct] = 0;
5819371c9d4SSatish Balay }
582412e9a14SMatthew G. Knepley if (numFT > 1) {
583a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLClear(faceTable));
584412e9a14SMatthew G. Knepley faceTypeStart[0] = fStart;
585412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1];
5865c2c0cecSMatthew G. Knepley cntFaces = 0;
5875c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
588412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces;
589412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes;
590ba2698f1SMatthew G. Knepley DMPolytopeType ct;
5915c2c0cecSMatthew G. Knepley PetscInt numFaces, foff = 0;
59299836e0eSStefano Zampini
5939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct));
5949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone));
5956f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
5969566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
5976f5c9017SMatthew G. Knepley } else {
5986f5c9017SMatthew G. Knepley numFaces = 0;
5996f5c9017SMatthew G. Knepley }
6005c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
601412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf];
602412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf];
603412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff];
60499836e0eSStefano Zampini PetscHashIJKLKey key;
60599836e0eSStefano Zampini PetscHashIter iter;
60699836e0eSStefano Zampini PetscBool missing;
60799836e0eSStefano Zampini
608a03d55ffSStefano Zampini key.i = face[0] + minCone;
609a03d55ffSStefano Zampini key.j = faceSize > 1 ? face[1] + minCone : 0;
610a03d55ffSStefano Zampini key.k = faceSize > 2 ? face[2] + minCone : 0;
611a03d55ffSStefano Zampini key.l = faceSize > 3 ? face[3] + minCone : 0;
6129566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key));
613a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing));
614591a860aSStefano Zampini if (missing) {
615591a860aSStefano Zampini facesId[cntFaces] = faceTypeStart[faceType];
616a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++));
617a03d55ffSStefano Zampini } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces]));
618591a860aSStefano Zampini cntFaces++;
61999836e0eSStefano Zampini }
6206f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
62199836e0eSStefano Zampini }
622412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) {
6231dca8a05SBarry 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]);
6249a5b13a2SMatthew G Knepley }
6259a5b13a2SMatthew G Knepley }
626412e9a14SMatthew G. Knepley }
627a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLDestroy(&faceTable));
628591a860aSStefano Zampini
6295c2c0cecSMatthew G. Knepley // Add new points, perhaps inserting into the numbering
6309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &Np));
6319566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart)));
6325c2c0cecSMatthew G. Knepley // Set cone sizes
6335c2c0cecSMatthew G. Knepley // Must create the celltype label here so that we do not automatically try to compute the types
6349566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(idm, "celltype"));
6359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel));
6365c2c0cecSMatthew G. Knepley for (PetscInt d = 0; d <= depth; ++d) {
637412e9a14SMatthew G. Knepley DMPolytopeType ct;
6385c2c0cecSMatthew G. Knepley PetscInt coneSize, pStart, pEnd, poff = 0;
6399f074e33SMatthew G Knepley
6409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
6411afe9b7dSMatthew G. Knepley // Check for non-manifold condition
6421afe9b7dSMatthew G. Knepley if (d == cellDepth) {
6431afe9b7dSMatthew G. Knepley if (pEnd == cEnd) continue;
6441afe9b7dSMatthew G. Knepley else pStart = vEnd;
6451afe9b7dSMatthew G. Knepley }
6465c2c0cecSMatthew G. Knepley // Account for insertion
6475c2c0cecSMatthew G. Knepley if (pStart >= fStart) poff = fEnd - fStart;
6485c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) {
6499566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
6505c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, p + poff, coneSize));
6519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct));
6525c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, p + poff, ct));
6539f074e33SMatthew G Knepley }
6549f074e33SMatthew G Knepley }
6555c2c0cecSMatthew G. Knepley cntFaces = 0;
6565c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
657591a860aSStefano Zampini const PetscInt *cone, *faceSizes;
658412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes;
659412e9a14SMatthew G. Knepley DMPolytopeType ct;
6605c2c0cecSMatthew G. Knepley PetscInt numFaces, poff = 0;
661412e9a14SMatthew G. Knepley
6629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct));
6639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone));
6645c2c0cecSMatthew G. Knepley if (c >= fStart) poff = fEnd - fStart;
6656f5c9017SMatthew G. Knepley if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
6665c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, c + poff, ct));
6675c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, c + poff, 2));
6686f5c9017SMatthew G. Knepley continue;
6696f5c9017SMatthew G. Knepley }
670591a860aSStefano Zampini PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6715c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, c + poff, ct));
6725c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, c + poff, numFaces));
6735c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; ++cf) {
674591a860aSStefano Zampini const PetscInt f = facesId[cntFaces];
675591a860aSStefano Zampini DMPolytopeType faceType = faceTypes[cf];
676412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf];
6779566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, f, faceSize));
6789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, f, faceType));
679591a860aSStefano Zampini cntFaces++;
680412e9a14SMatthew G. Knepley }
681591a860aSStefano Zampini PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL));
6829f074e33SMatthew G Knepley }
6839566063dSJacob Faibussowitsch PetscCall(DMSetUp(idm));
6845c2c0cecSMatthew G. Knepley // Initialize cones so we do not need the bash table to tell us that a cone has been set
685412e9a14SMatthew G. Knepley {
686412e9a14SMatthew G. Knepley PetscSection cs;
687412e9a14SMatthew G. Knepley PetscInt *cones, csize;
6889a5b13a2SMatthew G Knepley
6899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(idm, &cs));
6909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(idm, &cones));
6919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cs, &csize));
6925c2c0cecSMatthew G. Knepley for (PetscInt c = 0; c < csize; ++c) cones[c] = -1;
693412e9a14SMatthew G. Knepley }
6945c2c0cecSMatthew G. Knepley // Set cones
6955c2c0cecSMatthew G. Knepley {
6965c2c0cecSMatthew G. Knepley PetscInt *icone;
6975c2c0cecSMatthew G. Knepley PetscInt maxConeSize;
6985c2c0cecSMatthew G. Knepley
6995c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL));
7005c2c0cecSMatthew G. Knepley PetscCall(PetscMalloc1(maxConeSize, &icone));
7015c2c0cecSMatthew G. Knepley for (PetscInt d = 0; d <= depth; ++d) {
702412e9a14SMatthew G. Knepley const PetscInt *cone;
7035c2c0cecSMatthew G. Knepley PetscInt pStart, pEnd, poff = 0, coneSize;
704412e9a14SMatthew G. Knepley
7059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
7061afe9b7dSMatthew G. Knepley // Check for non-manifold condition
7071afe9b7dSMatthew G. Knepley if (d == cellDepth) {
7081afe9b7dSMatthew G. Knepley if (pEnd == cEnd) continue;
7091afe9b7dSMatthew G. Knepley else pStart = vEnd;
7101afe9b7dSMatthew G. Knepley }
7115c2c0cecSMatthew G. Knepley // Account for insertion
7125c2c0cecSMatthew G. Knepley if (pStart >= fStart) poff = fEnd - fStart;
7135c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) {
7149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
7155c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
7165c2c0cecSMatthew G. Knepley for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0);
7175c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCone(idm, p + poff, icone));
7189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &cone));
7195c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeOrientation(idm, p + poff, cone));
7209f074e33SMatthew G Knepley }
7219a5b13a2SMatthew G Knepley }
7225c2c0cecSMatthew G. Knepley cntFaces = 0;
7235c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
724412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces;
725412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes;
726ba2698f1SMatthew G. Knepley DMPolytopeType ct;
7275c2c0cecSMatthew G. Knepley PetscInt coneSize, numFaces, foff = 0, poff = 0;
72899836e0eSStefano Zampini
7299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct));
7309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone));
7315c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
7325c2c0cecSMatthew G. Knepley if (c >= fStart) poff = fEnd - fStart;
7336f5c9017SMatthew G. Knepley if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
7345c2c0cecSMatthew G. Knepley for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0);
7355c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCone(idm, c + poff, icone));
7366f5c9017SMatthew G. Knepley PetscCall(DMPlexGetConeOrientation(dm, c, &cone));
7375c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeOrientation(idm, c + poff, cone));
7386f5c9017SMatthew G. Knepley continue;
7396f5c9017SMatthew G. Knepley }
7409566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
7415c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) {
742412e9a14SMatthew G. Knepley DMPolytopeType faceType = faceTypes[cf];
743412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf];
744591a860aSStefano Zampini const PetscInt f = facesId[cntFaces];
745412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff];
746412e9a14SMatthew G. Knepley const PetscInt *fcone;
7479f074e33SMatthew G Knepley
7489566063dSJacob Faibussowitsch PetscCall(DMPlexInsertCone(idm, c, cf, f));
7499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(idm, f, &fcone));
7509566063dSJacob Faibussowitsch if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face));
751412e9a14SMatthew G. Knepley {
7521afe9b7dSMatthew G. Knepley const PetscInt *fcone2;
7535c2c0cecSMatthew G. Knepley PetscInt ornt;
754a74221b0SStefano Zampini
7559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(idm, f, &coneSize));
7561afe9b7dSMatthew G. Knepley PetscCall(DMPlexGetCone(idm, f, &fcone2));
75763a3b9bcSJacob 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);
758d89e6e46SMatthew G. Knepley /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */
7591afe9b7dSMatthew G. Knepley PetscCall(DMPolytopeGetVertexOrientation(faceType, fcone2, face, &ornt));
7605c2c0cecSMatthew G. Knepley PetscCall(DMPlexInsertConeOrientation(idm, c + poff, cf, ornt));
76199836e0eSStefano Zampini }
762591a860aSStefano Zampini cntFaces++;
76399836e0eSStefano Zampini }
7649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces));
76599836e0eSStefano Zampini }
7665c2c0cecSMatthew G. Knepley PetscCall(PetscFree(icone));
7675c2c0cecSMatthew G. Knepley }
768591a860aSStefano Zampini PetscCall(PetscFree(facesId));
7699566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(idm));
7709566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(idm));
7713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
7729f074e33SMatthew G Knepley }
7739f074e33SMatthew G Knepley
SortRmineRremoteByRemote_Private(PetscSF sf,PetscInt * rmine1[],PetscInt * rremote1[])774d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[])
775d71ae5a4SJacob Faibussowitsch {
776f80536cbSVaclav Hapla PetscInt nleaves;
7776497c311SBarry Smith PetscMPIInt nranks;
778a0d42dbcSVaclav Hapla const PetscMPIInt *ranks = NULL;
779a0d42dbcSVaclav Hapla const PetscInt *roffset = NULL, *rmine = NULL, *rremote = NULL;
7806497c311SBarry Smith PetscInt n, o;
781f80536cbSVaclav Hapla
782f80536cbSVaclav Hapla PetscFunctionBegin;
7839566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
784f80536cbSVaclav Hapla nleaves = roffset[nranks];
7859566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1));
7866497c311SBarry Smith for (PetscMPIInt r = 0; r < nranks; r++) {
787f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote
788f80536cbSVaclav Hapla - to unify order with the other side */
789f80536cbSVaclav Hapla o = roffset[r];
790f80536cbSVaclav Hapla n = roffset[r + 1] - o;
7919566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n));
7929566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n));
7939566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]));
794f80536cbSVaclav Hapla }
7953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
796f80536cbSVaclav Hapla }
797f80536cbSVaclav Hapla
DMPlexOrientInterface_Internal(DM dm)798d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm)
799d71ae5a4SJacob Faibussowitsch {
800d89e6e46SMatthew G. Knepley PetscSF sf;
801d89e6e46SMatthew G. Knepley const PetscInt *locals;
802d89e6e46SMatthew G. Knepley const PetscSFNode *remotes;
803d89e6e46SMatthew G. Knepley const PetscMPIInt *ranks;
804d89e6e46SMatthew G. Knepley const PetscInt *roffset;
805d89e6e46SMatthew G. Knepley PetscInt *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */
8066497c311SBarry Smith PetscInt nroots, p, nleaves, maxConeSize = 0;
8076497c311SBarry Smith PetscMPIInt nranks, r;
808d89e6e46SMatthew G. Knepley PetscInt (*roots)[4], (*leaves)[4], mainCone[4];
809d89e6e46SMatthew G. Knepley PetscMPIInt (*rootsRanks)[4], (*leavesRanks)[4];
8102e745bdaSMatthew G. Knepley MPI_Comm comm;
81127d0e99aSVaclav Hapla PetscMPIInt rank, size;
8122e745bdaSMatthew G. Knepley PetscInt debug = 0;
8132e745bdaSMatthew G. Knepley
8142e745bdaSMatthew G. Knepley PetscFunctionBegin;
8159566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
8179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
8189566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf));
8199566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view"));
820d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE));
8219566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes));
8223ba16761SJacob Faibussowitsch if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS);
8239566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf));
8249566063dSJacob Faibussowitsch PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1));
825d89e6e46SMatthew G. Knepley for (p = 0; p < nleaves; ++p) {
826d89e6e46SMatthew G. Knepley PetscInt coneSize;
8279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize));
828d89e6e46SMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize);
829d89e6e46SMatthew G. Knepley }
83063a3b9bcSJacob Faibussowitsch PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize);
8319566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks));
8329e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) {
833d89e6e46SMatthew G. Knepley const PetscInt *cone;
834d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0;
835d89e6e46SMatthew G. Knepley
8369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
838d89e6e46SMatthew G. Knepley /* Ignore vertices */
83927d0e99aSVaclav Hapla if (coneSize < 2) {
840d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) {
84127d0e99aSVaclav Hapla roots[p][c] = -1;
84227d0e99aSVaclav Hapla rootsRanks[p][c] = -1;
84327d0e99aSVaclav Hapla }
84427d0e99aSVaclav Hapla continue;
84527d0e99aSVaclav Hapla }
8462e745bdaSMatthew G. Knepley /* Translate all points to root numbering */
847d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); c++) {
8489566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0));
8498a650c75SVaclav Hapla if (ind0 < 0) {
8508a650c75SVaclav Hapla roots[p][c] = cone[c];
8518a650c75SVaclav Hapla rootsRanks[p][c] = rank;
852c8148b97SVaclav Hapla } else {
8538a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index;
854835f2295SStefano Zampini PetscCall(PetscMPIIntCast(remotes[ind0].rank, &rootsRanks[p][c]));
8558a650c75SVaclav Hapla }
8562e745bdaSMatthew G. Knepley }
857d89e6e46SMatthew G. Knepley for (c = coneSize; c < 4; c++) {
858d89e6e46SMatthew G. Knepley roots[p][c] = -1;
859d89e6e46SMatthew G. Knepley rootsRanks[p][c] = -1;
860d89e6e46SMatthew G. Knepley }
8612e745bdaSMatthew G. Knepley }
8629e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) {
863d89e6e46SMatthew G. Knepley PetscInt c;
864d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) {
8658ccb905dSVaclav Hapla leaves[p][c] = -2;
8668ccb905dSVaclav Hapla leavesRanks[p][c] = -2;
8678ccb905dSVaclav Hapla }
868c8148b97SVaclav Hapla }
8699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
8719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE));
8729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE));
873d89e6e46SMatthew G. Knepley if (debug) {
8749566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL));
875c5853193SPierre Jolivet if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n"));
876d89e6e46SMatthew G. Knepley }
8779566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL));
8789e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) {
879d89e6e46SMatthew G. Knepley DMPolytopeType ct;
880d89e6e46SMatthew G. Knepley const PetscInt *cone;
8816497c311SBarry Smith PetscInt coneSize, c, ind0, o, ir;
882d89e6e46SMatthew G. Knepley
883d89e6e46SMatthew G. Knepley if (leaves[p][0] < 0) continue; /* Ignore vertices */
8849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct));
8859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
887d89e6e46SMatthew G. Knepley if (debug) {
8889371c9d4SSatish 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]));
889d89e6e46SMatthew G. Knepley }
8909371c9d4SSatish 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]) {
891d89e6e46SMatthew G. Knepley /* Translate these leaves to my cone points; mainCone means desired order p's cone points */
892d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); ++c) {
893d89e6e46SMatthew G. Knepley PetscInt rS, rN;
894d89e6e46SMatthew G. Knepley
89527d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) {
896d89e6e46SMatthew G. Knepley /* A local leaf is just taken as it is */
8979dddd249SSatish Balay mainCone[c] = leaves[p][c];
89827d0e99aSVaclav Hapla continue;
89927d0e99aSVaclav Hapla }
900f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */
901f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */
902835f2295SStefano Zampini PetscCall(PetscFindMPIInt(leavesRanks[p][c], nranks, ranks, &ir));
9036497c311SBarry Smith PetscCall(PetscMPIIntCast(ir, &r));
90463a3b9bcSJacob 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]);
9056497c311SBarry Smith PetscCheck(ranks[r] >= 0 && ranks[r] < size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%" PetscInt_FMT " c=%" PetscInt_FMT " commsize=%d: ranks[%d] = %d makes no sense", p, c, size, r, ranks[r]);
906f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */
907d89e6e46SMatthew G. Knepley rS = roffset[r];
908d89e6e46SMatthew G. Knepley rN = roffset[r + 1] - rS;
9099566063dSJacob Faibussowitsch PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0));
91063a3b9bcSJacob 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]);
911f80536cbSVaclav Hapla /* Get the corresponding local point */
9125f80ce2aSJacob Faibussowitsch mainCone[c] = rmine1[rS + ind0];
913f80536cbSVaclav Hapla }
91463a3b9bcSJacob 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]));
91527d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */
9169566063dSJacob Faibussowitsch PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o));
9179566063dSJacob Faibussowitsch PetscCall(DMPlexOrientPoint(dm, p, o));
9189566063dSJacob Faibussowitsch } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n"));
91923aaf07bSVaclav Hapla }
92027d0e99aSVaclav Hapla if (debug) {
9219566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL));
9229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm));
9232e745bdaSMatthew G. Knepley }
9249566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view"));
9259566063dSJacob Faibussowitsch PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks));
9269566063dSJacob Faibussowitsch PetscCall(PetscFree2(rmine1, rremote1));
9273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9282e745bdaSMatthew G. Knepley }
9292e745bdaSMatthew G. Knepley
IntArrayViewFromOptions(MPI_Comm comm,const char opt[],const char name[],const char idxname[],const char valname[],PetscInt n,const PetscInt a[])930d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[])
931d71ae5a4SJacob Faibussowitsch {
9322e72742cSMatthew G. Knepley PetscInt idx;
9332e72742cSMatthew G. Knepley PetscMPIInt rank;
9342e72742cSMatthew G. Knepley PetscBool flg;
9357bffde78SMichael Lange
9367bffde78SMichael Lange PetscFunctionBegin;
9379566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9383ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
9409566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
94163a3b9bcSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx]));
9429566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL));
9433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9442e72742cSMatthew G. Knepley }
9452e72742cSMatthew G. Knepley
SFNodeArrayViewFromOptions(MPI_Comm comm,const char opt[],const char name[],const char idxname[],PetscInt n,const PetscSFNode a[])946d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[])
947d71ae5a4SJacob Faibussowitsch {
9482e72742cSMatthew G. Knepley PetscInt idx;
9492e72742cSMatthew G. Knepley PetscMPIInt rank;
9502e72742cSMatthew G. Knepley PetscBool flg;
9512e72742cSMatthew G. Knepley
9522e72742cSMatthew G. Knepley PetscFunctionBegin;
9539566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg));
9543ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
9559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
9569566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name));
9572e72742cSMatthew G. Knepley if (idxname) {
958835f2295SStefano Zampini 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));
9592e72742cSMatthew G. Knepley } else {
960835f2295SStefano Zampini for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]rank %" PetscInt_FMT " index %" PetscInt_FMT "\n", rank, a[idx].rank, a[idx].index));
9612e72742cSMatthew G. Knepley }
9629566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL));
9633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9642e72742cSMatthew G. Knepley }
9652e72742cSMatthew G. Knepley
DMPlexMapToLocalPoint(DM dm,PetscHMapIJ remotehash,PetscSFNode remotePoint,PetscInt * localPoint,PetscBool * mapFailed)966d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed)
967d71ae5a4SJacob Faibussowitsch {
9683be36e83SMatthew G. Knepley PetscSF sf;
9693be36e83SMatthew G. Knepley const PetscInt *locals;
9703be36e83SMatthew G. Knepley PetscMPIInt rank;
9712e72742cSMatthew G. Knepley
9722e72742cSMatthew G. Knepley PetscFunctionBegin;
9739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9749566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf));
9759566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL));
9765f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE;
9772e72742cSMatthew G. Knepley if (remotePoint.rank == rank) {
9782e72742cSMatthew G. Knepley *localPoint = remotePoint.index;
9792e72742cSMatthew G. Knepley } else {
9802e72742cSMatthew G. Knepley PetscHashIJKey key;
9813be36e83SMatthew G. Knepley PetscInt l;
9822e72742cSMatthew G. Knepley
9832e72742cSMatthew G. Knepley key.i = remotePoint.index;
9842e72742cSMatthew G. Knepley key.j = remotePoint.rank;
9859566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(remotehash, key, &l));
9863be36e83SMatthew G. Knepley if (l >= 0) {
9873be36e83SMatthew G. Knepley *localPoint = locals[l];
9885f80ce2aSJacob Faibussowitsch } else if (mapFailed) *mapFailed = PETSC_TRUE;
9892e72742cSMatthew G. Knepley }
9903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9912e72742cSMatthew G. Knepley }
9922e72742cSMatthew G. Knepley
DMPlexMapToGlobalPoint(DM dm,PetscInt localPoint,PetscSFNode * remotePoint,PetscBool * mapFailed)993d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed)
994d71ae5a4SJacob Faibussowitsch {
9953be36e83SMatthew G. Knepley PetscSF sf;
9963be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree;
9973be36e83SMatthew G. Knepley const PetscSFNode *remotes;
9983be36e83SMatthew G. Knepley PetscInt Nl, l;
9993be36e83SMatthew G. Knepley PetscMPIInt rank;
10003be36e83SMatthew G. Knepley
10013be36e83SMatthew G. Knepley PetscFunctionBegin;
10025f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE;
10039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10049566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf));
10059566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes));
10063be36e83SMatthew G. Knepley if (Nl < 0) goto owned;
10079566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
10089566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
10093be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned;
10109566063dSJacob Faibussowitsch PetscCall(PetscFindInt(localPoint, Nl, locals, &l));
10119371c9d4SSatish Balay if (l < 0) {
10129371c9d4SSatish Balay if (mapFailed) *mapFailed = PETSC_TRUE;
10139371c9d4SSatish Balay } else *remotePoint = remotes[l];
10143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10153be36e83SMatthew G. Knepley owned:
10163be36e83SMatthew G. Knepley remotePoint->rank = rank;
10173be36e83SMatthew G. Knepley remotePoint->index = localPoint;
10183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10193be36e83SMatthew G. Knepley }
10203be36e83SMatthew G. Knepley
DMPlexPointIsShared(DM dm,PetscInt p,PetscBool * isShared)1021d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared)
1022d71ae5a4SJacob Faibussowitsch {
10233be36e83SMatthew G. Knepley PetscSF sf;
10243be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree;
10253be36e83SMatthew G. Knepley PetscInt Nl, idx;
10263be36e83SMatthew G. Knepley
10273be36e83SMatthew G. Knepley PetscFunctionBegin;
10283be36e83SMatthew G. Knepley *isShared = PETSC_FALSE;
10299566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf));
10309566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL));
10313ba16761SJacob Faibussowitsch if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS);
10329566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, Nl, locals, &idx));
10339371c9d4SSatish Balay if (idx >= 0) {
10349371c9d4SSatish Balay *isShared = PETSC_TRUE;
10353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10369371c9d4SSatish Balay }
10379566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
10389566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
10393be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE;
10403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10413be36e83SMatthew G. Knepley }
10423be36e83SMatthew G. Knepley
DMPlexConeIsShared(DM dm,PetscInt p,PetscBool * isShared)1043d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared)
1044d71ae5a4SJacob Faibussowitsch {
10453be36e83SMatthew G. Knepley const PetscInt *cone;
10463be36e83SMatthew G. Knepley PetscInt coneSize, c;
10473be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE;
10483be36e83SMatthew G. Knepley
10493be36e83SMatthew G. Knepley PetscFunctionBegin;
10509566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
10523be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) {
10533be36e83SMatthew G. Knepley PetscBool pointShared;
10543be36e83SMatthew G. Knepley
10559566063dSJacob Faibussowitsch PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared));
10563be36e83SMatthew G. Knepley cShared = (PetscBool)(cShared && pointShared);
10573be36e83SMatthew G. Knepley }
10583be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE;
10593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10603be36e83SMatthew G. Knepley }
10613be36e83SMatthew G. Knepley
DMPlexGetConeMinimum(DM dm,PetscInt p,PetscSFNode * cpmin)1062d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin)
1063d71ae5a4SJacob Faibussowitsch {
10643be36e83SMatthew G. Knepley const PetscInt *cone;
10653be36e83SMatthew G. Knepley PetscInt coneSize, c;
10666497c311SBarry Smith PetscSFNode cmin = {PETSC_INT_MAX, PETSC_MPI_INT_MAX}, missing = {-1, -1};
10673be36e83SMatthew G. Knepley
10683be36e83SMatthew G. Knepley PetscFunctionBegin;
10699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
10709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
10713be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) {
10723be36e83SMatthew G. Knepley PetscSFNode rcp;
10735f80ce2aSJacob Faibussowitsch PetscBool mapFailed;
10743be36e83SMatthew G. Knepley
10759566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed));
10765f80ce2aSJacob Faibussowitsch if (mapFailed) {
10773be36e83SMatthew G. Knepley cmin = missing;
10783be36e83SMatthew G. Knepley } else {
10793be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin;
10803be36e83SMatthew G. Knepley }
10813be36e83SMatthew G. Knepley }
10823be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing;
10833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10843be36e83SMatthew G. Knepley }
10853be36e83SMatthew G. Knepley
10863be36e83SMatthew G. Knepley /*
10873be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array:
10883be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)}
10893be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face
10903be36e83SMatthew G. Knepley */
DMPlexAddSharedFace_Private(DM dm,PetscSection candidateSection,PetscSFNode candidates[],PetscHMapIJ faceHash,PetscInt p,PetscBool debug)1091d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug)
1092d71ae5a4SJacob Faibussowitsch {
10933be36e83SMatthew G. Knepley MPI_Comm comm;
10943be36e83SMatthew G. Knepley const PetscInt *support;
1095cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height;
10963be36e83SMatthew G. Knepley PetscMPIInt rank;
10973be36e83SMatthew G. Knepley
10983be36e83SMatthew G. Knepley PetscFunctionBegin;
10999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
11019566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap));
11029566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
11039566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointHeight(dm, p, &height));
1104cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight + 1) {
1105cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */
110663a3b9bcSJacob 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));
11073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1108cf4dc471SVaclav Hapla }
11099566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
11109566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support));
11119566063dSJacob Faibussowitsch if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off));
11123be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) {
11133be36e83SMatthew G. Knepley const PetscInt face = support[s];
11143be36e83SMatthew G. Knepley const PetscInt *cone;
11153be36e83SMatthew G. Knepley PetscSFNode cpmin = {-1, -1}, rp = {-1, -1};
11163be36e83SMatthew G. Knepley PetscInt coneSize, c, f;
11173be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE;
11183be36e83SMatthew G. Knepley PetscHashIJKey key;
11193be36e83SMatthew G. Knepley
11203be36e83SMatthew G. Knepley /* Only add point once */
112163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Support face %" PetscInt_FMT "\n", rank, face));
11223be36e83SMatthew G. Knepley key.i = p;
11233be36e83SMatthew G. Knepley key.j = face;
11249566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(faceHash, key, &f));
11253be36e83SMatthew G. Knepley if (f >= 0) continue;
11269566063dSJacob Faibussowitsch PetscCall(DMPlexConeIsShared(dm, face, &isShared));
11279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin));
11289566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL));
11293be36e83SMatthew G. Knepley if (debug) {
113063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared));
1131835f2295SStefano Zampini 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));
11323be36e83SMatthew G. Knepley }
11333be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) {
11349566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p));
11353be36e83SMatthew G. Knepley if (candidates) {
113663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d] ", rank, face, idx, rank));
11379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, face, &cone));
11393be36e83SMatthew G. Knepley candidates[off + idx].rank = -1;
11403be36e83SMatthew G. Knepley candidates[off + idx++].index = coneSize - 1;
11413be36e83SMatthew G. Knepley candidates[off + idx].rank = rank;
11423be36e83SMatthew G. Knepley candidates[off + idx++].index = face;
11433be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) {
11443be36e83SMatthew G. Knepley const PetscInt cp = cone[c];
11453be36e83SMatthew G. Knepley
11463be36e83SMatthew G. Knepley if (cp == p) continue;
11479566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL));
1148835f2295SStefano Zampini if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT "),%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index));
11493be36e83SMatthew G. Knepley ++idx;
11503be36e83SMatthew G. Knepley }
11519566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n"));
11523be36e83SMatthew G. Knepley } else {
11533be36e83SMatthew G. Knepley /* Add cone size to section */
115463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %" PetscInt_FMT "\n", rank, face));
11559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize));
11569566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p));
11579566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1));
11583be36e83SMatthew G. Knepley }
11593be36e83SMatthew G. Knepley }
11603be36e83SMatthew G. Knepley }
11613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
11623be36e83SMatthew G. Knepley }
11633be36e83SMatthew G. Knepley
11642e72742cSMatthew G. Knepley /*@
116520f4b53cSBarry Smith DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation
11662e72742cSMatthew G. Knepley
116720f4b53cSBarry Smith Collective
11682e72742cSMatthew G. Knepley
11692e72742cSMatthew G. Knepley Input Parameters:
117020f4b53cSBarry Smith + dm - The interpolated `DMPLEX`
117120f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points
11722e72742cSMatthew G. Knepley
1173f0cfc026SVaclav Hapla Level: developer
11742e72742cSMatthew G. Knepley
117520f4b53cSBarry Smith Note:
117620f4b53cSBarry 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`
11772e72742cSMatthew G. Knepley
117820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()`
11792e72742cSMatthew G. Knepley @*/
DMPlexInterpolatePointSF(DM dm,PetscSF pointSF)1180d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF)
1181d71ae5a4SJacob Faibussowitsch {
11823be36e83SMatthew G. Knepley MPI_Comm comm;
11833be36e83SMatthew G. Knepley PetscHMapIJ remoteHash;
11843be36e83SMatthew G. Knepley PetscHMapI claimshash;
11853be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection;
11863be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims;
11872e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree;
11882e72742cSMatthew G. Knepley const PetscSFNode *remotePoints;
11893be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l;
11903be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize;
11913be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE;
1192f0cfc026SVaclav Hapla PetscMPIInt rank;
11932e72742cSMatthew G. Knepley
11942e72742cSMatthew G. Knepley PetscFunctionBegin;
1195f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1196064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
11979566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &flg));
11983ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
11993be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */
12009566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF));
12019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
12029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
12039566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &ov));
120428b400f6SJacob Faibussowitsch PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet");
12059566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug));
12069566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view"));
12079566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view"));
12089566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0));
12093be36e83SMatthew G. Knepley /* Step 0: Precalculations */
12109566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints));
121108401ef6SPierre Jolivet PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set");
12129566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&remoteHash));
12133be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) {
12143be36e83SMatthew G. Knepley PetscHashIJKey key;
12156497c311SBarry Smith
12162e72742cSMatthew G. Knepley key.i = remotePoints[l].index;
12172e72742cSMatthew G. Knepley key.j = remotePoints[l].rank;
12189566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(remoteHash, key, l));
12197bffde78SMichael Lange }
122066aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */
12219566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
12229566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
12239566063dSJacob Faibussowitsch PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree));
12243be36e83SMatthew G. Knepley /*
12253be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF
12263be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which
12273be36e83SMatthew G. Knepley \begin{itemize}
12283be36e83SMatthew G. Knepley \item all cone points of $f$ are shared
12293be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number
12303be36e83SMatthew G. Knepley \end{itemize}
12313be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$
12323be36e83SMatthew 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
12333be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process
12343be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF
12353be36e83SMatthew G. Knepley */
12363be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array
12373be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone
1238da81f932SPierre Jolivet The array holds candidate shared faces, each face is referred to by the leaf point */
12399566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateSection));
12409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(candidateSection, 0, Nr));
12417bffde78SMichael Lange {
12423be36e83SMatthew G. Knepley PetscHMapIJ faceHash;
12432e72742cSMatthew G. Knepley
12449566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&faceHash));
12453be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) {
12463be36e83SMatthew G. Knepley const PetscInt p = localPoints[l];
12472e72742cSMatthew G. Knepley
124863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %" PetscInt_FMT "\n", rank, p));
12499566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug));
12502e72742cSMatthew G. Knepley }
12519566063dSJacob Faibussowitsch PetscCall(PetscHMapIJClear(faceHash));
12529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(candidateSection));
12539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize));
12549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesSize, &candidates));
12553be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) {
12563be36e83SMatthew G. Knepley const PetscInt p = localPoints[l];
12572e72742cSMatthew G. Knepley
125863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %" PetscInt_FMT "\n", rank, p));
12599566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug));
12602e72742cSMatthew G. Knepley }
12619566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&faceHash));
12629566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
12637bffde78SMichael Lange }
12649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section"));
12659566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view"));
12669566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates));
12673be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */
12682e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */
12697bffde78SMichael Lange {
12707bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates;
12717bffde78SMichael Lange PetscInt *remoteOffsets;
12722e72742cSMatthew G. Knepley
12739566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
12749566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse));
12759566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateRemoteSection));
12769566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection));
12779566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates));
12789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize));
12799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote));
12806497c311SBarry Smith PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_SF_NODE, candidates, candidatesRemote, MPI_REPLACE));
12816497c311SBarry Smith PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_SF_NODE, candidates, candidatesRemote, MPI_REPLACE));
12829566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfInverse));
12839566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfCandidates));
12849566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets));
12852e72742cSMatthew G. Knepley
12869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section"));
12879566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view"));
12889566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote));
12897bffde78SMichael Lange }
12903be36e83SMatthew 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 */
12917bffde78SMichael Lange {
1292a03d55ffSStefano Zampini PetscHMapIJKLRemote faceTable;
12933be36e83SMatthew G. Knepley PetscInt idx, idx2;
12943be36e83SMatthew G. Knepley
1295a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteCreate(&faceTable));
12962e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */
12973be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) {
12982e72742cSMatthew G. Knepley PetscInt deg;
12993be36e83SMatthew G. Knepley
13002e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) {
13012e72742cSMatthew G. Knepley PetscInt offset, dof, d;
13022e72742cSMatthew G. Knepley
13039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof));
13049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset));
13053be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */
13062e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) {
13073be36e83SMatthew G. Knepley const PetscInt hidx = offset + d;
13083be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1;
13093be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx + 1];
13103be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2];
13113be36e83SMatthew G. Knepley PetscSFNode fcp0;
1312d9dd0fdcSStefano Zampini const PetscSFNode pmax = {-1, -1};
13132e72742cSMatthew G. Knepley const PetscInt *join = NULL;
1314a03d55ffSStefano Zampini PetscHMapIJKLRemoteKey key;
13153be36e83SMatthew G. Knepley PetscHashIter iter;
13165f80ce2aSJacob Faibussowitsch PetscBool missing, mapToLocalPointFailed = PETSC_FALSE;
13172e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize;
13182e72742cSMatthew G. Knepley
13199371c9d4SSatish Balay if (debug)
1320835f2295SStefano Zampini 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,
13219371c9d4SSatish Balay rface.index, r, idx, d, Np));
13226497c311SBarry Smith
1323835f2295SStefano Zampini 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);
13243be36e83SMatthew G. Knepley fcp0.rank = rank;
13253be36e83SMatthew G. Knepley fcp0.index = r;
13263be36e83SMatthew G. Knepley d += Np;
13273be36e83SMatthew G. Knepley /* Put remote face in hash table */
13283be36e83SMatthew G. Knepley key.i = fcp0;
13293be36e83SMatthew G. Knepley key.j = fcone[0];
13303be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax;
13313be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax;
13329566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
1333a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
13343be36e83SMatthew G. Knepley if (missing) {
1335835f2295SStefano Zampini if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT "))\n", rank, rface.index, rface.rank));
1336a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13373be36e83SMatthew G. Knepley } else {
13383be36e83SMatthew G. Knepley PetscSFNode oface;
13393be36e83SMatthew G. Knepley
1340a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13413be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) {
1342835f2295SStefano Zampini if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank));
1343a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface));
13443be36e83SMatthew G. Knepley }
13453be36e83SMatthew G. Knepley }
13463be36e83SMatthew G. Knepley /* Check for local face */
13472e72742cSMatthew G. Knepley points[0] = r;
13483be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) {
13499566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed));
13505f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) break; /* We got a point not in our overlap */
135163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Checking local candidate %" PetscInt_FMT "\n", rank, points[p]));
13527bffde78SMichael Lange }
13535f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) continue;
13549566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join));
13557bffde78SMichael Lange if (joinSize == 1) {
13563be36e83SMatthew G. Knepley PetscSFNode lface;
13573be36e83SMatthew G. Knepley PetscSFNode oface;
13583be36e83SMatthew G. Knepley
13593be36e83SMatthew G. Knepley /* Always replace with local face */
13603be36e83SMatthew G. Knepley lface.rank = rank;
13613be36e83SMatthew G. Knepley lface.index = join[0];
1362a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface));
13639371c9d4SSatish Balay if (debug)
1364835f2295SStefano Zampini 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));
1365a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface));
13667bffde78SMichael Lange }
13679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join));
13683be36e83SMatthew G. Knepley }
13693be36e83SMatthew G. Knepley }
13703be36e83SMatthew G. Knepley /* Put back faces for this root */
13713be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) {
13723be36e83SMatthew G. Knepley PetscInt offset, dof, d;
13733be36e83SMatthew G. Knepley
13749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof));
13759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset));
13763be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */
13773be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) {
13783be36e83SMatthew G. Knepley const PetscInt hidx = offset + d;
13793be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1;
13803be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2];
13813be36e83SMatthew G. Knepley PetscSFNode fcp0;
1382d9dd0fdcSStefano Zampini const PetscSFNode pmax = {-1, -1};
1383a03d55ffSStefano Zampini PetscHMapIJKLRemoteKey key;
13843be36e83SMatthew G. Knepley PetscHashIter iter;
13853be36e83SMatthew G. Knepley PetscBool missing;
13863be36e83SMatthew G. Knepley
138763a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx));
138863a3b9bcSJacob Faibussowitsch PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np);
13893be36e83SMatthew G. Knepley fcp0.rank = rank;
13903be36e83SMatthew G. Knepley fcp0.index = r;
13913be36e83SMatthew G. Knepley d += Np;
13923be36e83SMatthew G. Knepley /* Find remote face in hash table */
13933be36e83SMatthew G. Knepley key.i = fcp0;
13943be36e83SMatthew G. Knepley key.j = fcone[0];
13953be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax;
13963be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax;
13979566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key));
13989371c9d4SSatish Balay if (debug)
1399835f2295SStefano Zampini 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,
1400835f2295SStefano Zampini key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index));
1401a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing));
140263a3b9bcSJacob Faibussowitsch PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2);
1403a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]));
14047bffde78SMichael Lange }
14057bffde78SMichael Lange }
14067bffde78SMichael Lange }
14079566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL));
1408a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable));
14097bffde78SMichael Lange }
14103be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */
14117bffde78SMichael Lange {
14127bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew;
14137bffde78SMichael Lange PetscSFNode *remotePointsNew;
14142e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew;
14153be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p;
14162e72742cSMatthew G. Knepley
14173be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */
14189566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti));
14199566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &claimSection));
14209566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection));
14219566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims));
14229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize));
14239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(claimsSize, &claims));
14243be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1;
14256497c311SBarry Smith PetscCall(PetscSFBcastBegin(sfClaims, MPIU_SF_NODE, candidatesRemote, claims, MPI_REPLACE));
14266497c311SBarry Smith PetscCall(PetscSFBcastEnd(sfClaims, MPIU_SF_NODE, candidatesRemote, claims, MPI_REPLACE));
14279566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfClaims));
14289566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets));
14299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section"));
14309566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view"));
14319566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims));
14323be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */
14333be36e83SMatthew 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 */
14349566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&claimshash));
14353be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) {
14363be36e83SMatthew G. Knepley PetscInt dof, off, d;
14372e72742cSMatthew G. Knepley
143863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %" PetscInt_FMT "\n", rank, r));
14399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateSection, r, &dof));
14409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateSection, r, &off));
14412e72742cSMatthew G. Knepley for (d = 0; d < dof;) {
14423be36e83SMatthew G. Knepley if (claims[off + d].rank >= 0) {
14433be36e83SMatthew G. Knepley const PetscInt faceInd = off + d;
14443be36e83SMatthew G. Knepley const PetscInt Np = candidates[off + d].index;
14452e72742cSMatthew G. Knepley const PetscInt *join = NULL;
14462e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c;
14472e72742cSMatthew G. Knepley
1448835f2295SStefano Zampini if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index));
14493be36e83SMatthew G. Knepley points[0] = r;
145063a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[0]));
14513be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) {
14529566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL));
145363a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[c + 1]));
14542e72742cSMatthew G. Knepley }
14559566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join));
14562e72742cSMatthew G. Knepley if (joinSize == 1) {
14573be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) {
145863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0]));
14593be36e83SMatthew G. Knepley } else {
146063a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found local face %" PetscInt_FMT "\n", rank, join[0]));
14619566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(claimshash, join[0], faceInd));
14622e72742cSMatthew G. Knepley }
14633be36e83SMatthew G. Knepley } else {
14649566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank));
14653be36e83SMatthew G. Knepley }
14669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join));
14673be36e83SMatthew G. Knepley } else {
146863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] No claim for point %" PetscInt_FMT "\n", rank, r));
14693be36e83SMatthew G. Knepley d += claims[off + d].index + 1;
14707bffde78SMichael Lange }
14717bffde78SMichael Lange }
14723be36e83SMatthew G. Knepley }
14739566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
14743be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */
14759566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(claimshash, &NlNew));
14769566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew));
14789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew));
14793be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) {
14803be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l];
14813be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index;
14823be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank;
14837bffde78SMichael Lange }
14843be36e83SMatthew G. Knepley p = Nl;
14859566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew));
14863be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */
14878e3a54c0SPierre Jolivet PetscCall(PetscSortInt(NlNew, PetscSafePointerPlusOffset(localPointsNew, Nl)));
14883be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) {
14893be36e83SMatthew G. Knepley PetscInt off;
14909566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off));
1491835f2295SStefano Zampini 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);
14923be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off];
14937bffde78SMichael Lange }
14949566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfPointNew));
14959566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
14969566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfPointNew));
14979566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPointNew));
14989566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view"));
1499d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE));
15009566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPointNew));
15019566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&claimshash));
15027bffde78SMichael Lange }
15039566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&remoteHash));
15049566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateSection));
15059566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateRemoteSection));
15069566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&claimSection));
15079566063dSJacob Faibussowitsch PetscCall(PetscFree(candidates));
15089566063dSJacob Faibussowitsch PetscCall(PetscFree(candidatesRemote));
15099566063dSJacob Faibussowitsch PetscCall(PetscFree(claims));
15109566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0));
15113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
15127bffde78SMichael Lange }
15137bffde78SMichael Lange
1514248eb259SVaclav Hapla /*@
151580330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc.
151680330477SMatthew G. Knepley
151720f4b53cSBarry Smith Collective
151880330477SMatthew G. Knepley
151920f4b53cSBarry Smith Input Parameter:
152020f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices
152180330477SMatthew G. Knepley
152280330477SMatthew G. Knepley Output Parameter:
152320f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object
152480330477SMatthew G. Knepley
152580330477SMatthew G. Knepley Level: intermediate
152680330477SMatthew G. Knepley
152720f4b53cSBarry Smith Note:
15287fb59074SVaclav Hapla Labels and coordinates are copied.
152943eeeb2dSStefano Zampini
153060225df5SJacob Faibussowitsch Developer Notes:
153120f4b53cSBarry Smith It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`.
15329ade3219SVaclav Hapla
153320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
153480330477SMatthew G. Knepley @*/
DMPlexInterpolate(DM dm,DM * dmInt)1535d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt)
1536d71ae5a4SJacob Faibussowitsch {
1537a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated;
15389a5b13a2SMatthew G Knepley DM idm, odm = dm;
15397bffde78SMichael Lange PetscSF sfPoint;
15402e1b13c2SMatthew G. Knepley PetscInt depth, dim, d;
154110a67516SMatthew G. Knepley const char *name;
1542b325530aSVaclav Hapla PetscBool flg = PETSC_TRUE;
15439f074e33SMatthew G Knepley
15449f074e33SMatthew G Knepley PetscFunctionBegin;
154510a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15464f572ea9SToby Isaac PetscAssertPointer(dmInt, 2);
15479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0));
15489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
15499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
15509566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated));
155108401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1552827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) {
15539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm));
155476b791aaSMatthew G. Knepley idm = dm;
1555b21b8912SMatthew G. Knepley } else {
15565c2c0cecSMatthew G. Knepley PetscBool nonmanifold = PETSC_FALSE;
15575c2c0cecSMatthew G. Knepley
15585c2c0cecSMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &nonmanifold, NULL));
15595c2c0cecSMatthew G. Knepley if (nonmanifold) {
15605c2c0cecSMatthew G. Knepley do {
15615c2c0cecSMatthew G. Knepley const char *prefix;
15625c2c0cecSMatthew G. Knepley PetscInt pStart, pEnd, pdepth;
15635c2c0cecSMatthew G. Knepley PetscBool done = PETSC_TRUE;
15645c2c0cecSMatthew G. Knepley
15655c2c0cecSMatthew G. Knepley // Find a point which is not correctly interpolated
15665c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetChart(odm, &pStart, &pEnd));
15675c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) {
15685c2c0cecSMatthew G. Knepley DMPolytopeType ct;
15695c2c0cecSMatthew G. Knepley const PetscInt *cone;
15705c2c0cecSMatthew G. Knepley PetscInt coneSize, cdepth;
15715c2c0cecSMatthew G. Knepley
15725c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(odm, p, &pdepth));
15735c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetCellType(odm, p, &ct));
15745c2c0cecSMatthew G. Knepley // Check against celltype
15755c2c0cecSMatthew G. Knepley if (pdepth != DMPolytopeTypeGetDim(ct)) {
15765c2c0cecSMatthew G. Knepley done = PETSC_FALSE;
15775c2c0cecSMatthew G. Knepley break;
15785c2c0cecSMatthew G. Knepley }
15795c2c0cecSMatthew G. Knepley // Check against boundary
15805c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetCone(odm, p, &cone));
15815c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(odm, p, &coneSize));
15825c2c0cecSMatthew G. Knepley for (PetscInt c = 0; c < coneSize; ++c) {
15835c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(odm, cone[c], &cdepth));
15845c2c0cecSMatthew G. Knepley if (cdepth != pdepth - 1) {
15855c2c0cecSMatthew G. Knepley done = PETSC_FALSE;
15865c2c0cecSMatthew G. Knepley p = pEnd;
15875c2c0cecSMatthew G. Knepley break;
15885c2c0cecSMatthew G. Knepley }
15895c2c0cecSMatthew G. Knepley }
15905c2c0cecSMatthew G. Knepley }
15915c2c0cecSMatthew G. Knepley if (done) break;
15925c2c0cecSMatthew G. Knepley /* Create interpolated mesh */
15935c2c0cecSMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
15945c2c0cecSMatthew G. Knepley PetscCall(DMSetType(idm, DMPLEX));
15955c2c0cecSMatthew G. Knepley PetscCall(DMSetDimension(idm, dim));
15965c2c0cecSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
15975c2c0cecSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
15985c2c0cecSMatthew G. Knepley if (depth > 0) {
15995c2c0cecSMatthew G. Knepley PetscCall(DMPlexInterpolateFaces_Internal(odm, pdepth, idm));
16005c2c0cecSMatthew G. Knepley PetscCall(DMGetPointSF(odm, &sfPoint));
16015c2c0cecSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
16025c2c0cecSMatthew G. Knepley {
16035c2c0cecSMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
16045c2c0cecSMatthew G. Knepley PetscInt nroots;
16055c2c0cecSMatthew G. Knepley PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
16065c2c0cecSMatthew G. Knepley if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
16075c2c0cecSMatthew G. Knepley }
16085c2c0cecSMatthew G. Knepley }
16095c2c0cecSMatthew G. Knepley if (odm != dm) PetscCall(DMDestroy(&odm));
16105c2c0cecSMatthew G. Knepley odm = idm;
16115c2c0cecSMatthew G. Knepley } while (1);
16125c2c0cecSMatthew G. Knepley } else {
16139a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) {
16146f5c9017SMatthew G. Knepley const char *prefix;
16156f5c9017SMatthew G. Knepley
16169a5b13a2SMatthew G Knepley /* Create interpolated mesh */
16179566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm));
16189566063dSJacob Faibussowitsch PetscCall(DMSetType(idm, DMPLEX));
16199566063dSJacob Faibussowitsch PetscCall(DMSetDimension(idm, dim));
16206f5c9017SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
16216f5c9017SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix));
16227bffde78SMichael Lange if (depth > 0) {
16239566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm));
16249566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(odm, &sfPoint));
1625d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE));
162694488200SVaclav Hapla {
16273be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */
162894488200SVaclav Hapla PetscInt nroots;
16299566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
16309566063dSJacob Faibussowitsch if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint));
163194488200SVaclav Hapla }
16327bffde78SMichael Lange }
16339566063dSJacob Faibussowitsch if (odm != dm) PetscCall(DMDestroy(&odm));
16349a5b13a2SMatthew G Knepley odm = idm;
16359f074e33SMatthew G Knepley }
16365c2c0cecSMatthew G. Knepley }
16379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name));
16389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)idm, name));
16399566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm));
16409566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL));
16419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL));
16429566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexOrientInterface_Internal(idm));
164384699f70SSatish Balay }
1644827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */
1645827c4036SVaclav Hapla {
1646d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)idm->data;
1647827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL;
1648827c4036SVaclav Hapla }
16495de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm));
16509a5b13a2SMatthew G Knepley *dmInt = idm;
16519566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0));
16523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
16539f074e33SMatthew G Knepley }
165407b0a1fcSMatthew G Knepley
165580330477SMatthew G. Knepley /*@
165680330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices
165780330477SMatthew G. Knepley
165820f4b53cSBarry Smith Collective
165980330477SMatthew G. Knepley
166080330477SMatthew G. Knepley Input Parameter:
166120f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates
166280330477SMatthew G. Knepley
166380330477SMatthew G. Knepley Output Parameter:
166420f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates
166580330477SMatthew G. Knepley
166680330477SMatthew G. Knepley Level: intermediate
166780330477SMatthew G. Knepley
16686f5c9017SMatthew G. Knepley Notes:
166920f4b53cSBarry Smith This is typically used when adding pieces other than vertices to a mesh
167080330477SMatthew G. Knepley
16716f5c9017SMatthew G. Knepley This function does not copy localized coordinates.
16726f5c9017SMatthew G. Knepley
167320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()`
167480330477SMatthew G. Knepley @*/
DMPlexCopyCoordinates(DM dmA,DM dmB)1675d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB)
1676d71ae5a4SJacob Faibussowitsch {
167707b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB;
167843eeeb2dSStefano Zampini VecType vtype;
167907b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB;
168007b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB;
16810bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d;
168290a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim;
168307b0a1fcSMatthew G Knepley
168407b0a1fcSMatthew G Knepley PetscFunctionBegin;
168543eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
168643eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
16873ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
16889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &cdim));
16899566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dmB, cdim));
16909566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA));
16919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB));
169263a3b9bcSJacob 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);
169361a622f3SMatthew G. Knepley /* Copy over discretization if it exists */
169461a622f3SMatthew G. Knepley {
169561a622f3SMatthew G. Knepley DM cdmA, cdmB;
169661a622f3SMatthew G. Knepley PetscDS dsA, dsB;
169761a622f3SMatthew G. Knepley PetscObject objA, objB;
169861a622f3SMatthew G. Knepley PetscClassId idA, idB;
169961a622f3SMatthew G. Knepley const PetscScalar *constants;
170061a622f3SMatthew G. Knepley PetscInt cdim, Nc;
170161a622f3SMatthew G. Knepley
17029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &cdmA));
17039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &cdmB));
17049566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmA, 0, NULL, &objA));
17059566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmB, 0, NULL, &objB));
17069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objA, &idA));
17079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objB, &idB));
170861a622f3SMatthew G. Knepley if ((idA == PETSCFE_CLASSID) && (idA != idB)) {
17099566063dSJacob Faibussowitsch PetscCall(DMSetField(cdmB, 0, NULL, objA));
17109566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdmB));
17119566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmA, &dsA));
17129566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmB, &dsB));
17139566063dSJacob Faibussowitsch PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim));
17149566063dSJacob Faibussowitsch PetscCall(PetscDSSetCoordinateDimension(dsB, cdim));
17159566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(dsA, &Nc, &constants));
17169566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants));
171761a622f3SMatthew G. Knepley }
171861a622f3SMatthew G. Knepley }
17199566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA));
17209566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB));
17219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmA, &coordSectionA));
17229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmB, &coordSectionB));
17233ba16761SJacob Faibussowitsch if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS);
17249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf));
17253ba16761SJacob Faibussowitsch if (!Nf) PetscFunctionReturn(PETSC_SUCCESS);
172663a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf);
1727df26b574SMatthew G. Knepley if (!coordSectionB) {
1728df26b574SMatthew G. Knepley PetscInt dim;
1729df26b574SMatthew G. Knepley
17309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB));
17319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &dim));
17329566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB));
17339566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordSectionB));
1734df26b574SMatthew G. Knepley }
17359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSectionB, 1));
17369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim));
17379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim));
17389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE));
173943eeeb2dSStefano Zampini cS = vStartB;
174043eeeb2dSStefano Zampini cE = vEndB;
17419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSectionB, cS, cE));
174207b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) {
17439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim));
17449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim));
174507b0a1fcSMatthew G Knepley }
17469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSectionB));
17479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB));
17489566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA));
17499566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB));
17509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates"));
17519566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE));
17529566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(coordinatesA, &d));
17539566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinatesB, d));
17549566063dSJacob Faibussowitsch PetscCall(VecGetType(coordinatesA, &vtype));
17559566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinatesB, vtype));
17569566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesA, &coordsA));
17579566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesB, &coordsB));
175807b0a1fcSMatthew G Knepley for (v = 0; v < vEndB - vStartB; ++v) {
175943eeeb2dSStefano Zampini PetscInt offA, offB;
176043eeeb2dSStefano Zampini
17619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA));
17629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB));
1763ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d];
176443eeeb2dSStefano Zampini }
17659566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesA, &coordsA));
17669566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesB, &coordsB));
17679566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB));
17689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinatesB));
17693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
177007b0a1fcSMatthew G Knepley }
17715c386225SMatthew G. Knepley
17724e3744c5SMatthew G. Knepley /*@
17734e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh
17744e3744c5SMatthew G. Knepley
177520f4b53cSBarry Smith Collective
17764e3744c5SMatthew G. Knepley
17774e3744c5SMatthew G. Knepley Input Parameter:
177820f4b53cSBarry Smith . dm - The complete `DMPLEX` object
17794e3744c5SMatthew G. Knepley
17804e3744c5SMatthew G. Knepley Output Parameter:
178120f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices
17824e3744c5SMatthew G. Knepley
17834e3744c5SMatthew G. Knepley Level: intermediate
17844e3744c5SMatthew G. Knepley
178520f4b53cSBarry Smith Note:
178695452b02SPatrick Sanan It does not copy over the coordinates.
178743eeeb2dSStefano Zampini
178860225df5SJacob Faibussowitsch Developer Notes:
178920f4b53cSBarry Smith Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
17909ade3219SVaclav Hapla
179120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()`
17924e3744c5SMatthew G. Knepley @*/
DMPlexUninterpolate(DM dm,DM * dmUnint)1793d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint)
1794d71ae5a4SJacob Faibussowitsch {
1795827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated;
17964e3744c5SMatthew G. Knepley DM udm;
1797412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone;
17984e3744c5SMatthew G. Knepley
17994e3744c5SMatthew G. Knepley PetscFunctionBegin;
180043eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18014f572ea9SToby Isaac PetscAssertPointer(dmUnint, 2);
1802172ee266SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0));
18039566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
18049566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated));
180508401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes");
1806827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) {
1807827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */
18089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm));
1809595d4abbSMatthew G. Knepley *dmUnint = dm;
18103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
18114e3744c5SMatthew G. Knepley }
18129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
18139566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
18149566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm));
18159566063dSJacob Faibussowitsch PetscCall(DMSetType(udm, DMPLEX));
18169566063dSJacob Faibussowitsch PetscCall(DMSetDimension(udm, dim));
18179566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(udm, cStart, vEnd));
18184e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
1819595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
18204e3744c5SMatthew G. Knepley
18219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18224e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) {
18234e3744c5SMatthew G. Knepley const PetscInt p = closure[cl];
18244e3744c5SMatthew G. Knepley
18254e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize;
18264e3744c5SMatthew G. Knepley }
18279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18289566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(udm, c, coneSize));
1829595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize);
18304e3744c5SMatthew G. Knepley }
18319566063dSJacob Faibussowitsch PetscCall(DMSetUp(udm));
18329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConeSize, &cone));
18334e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
1834595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
18354e3744c5SMatthew G. Knepley
18369566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18374e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) {
18384e3744c5SMatthew G. Knepley const PetscInt p = closure[cl];
18394e3744c5SMatthew G. Knepley
18404e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p;
18414e3744c5SMatthew G. Knepley }
18429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
18439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(udm, c, cone));
18444e3744c5SMatthew G. Knepley }
18459566063dSJacob Faibussowitsch PetscCall(PetscFree(cone));
18469566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(udm));
18479566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(udm));
18485c7de58aSMatthew G. Knepley /* Reduce SF */
18495c7de58aSMatthew G. Knepley {
18505c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn;
18515c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints;
18525c7de58aSMatthew G. Knepley const PetscInt *localPoints;
18535c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn;
18545c7de58aSMatthew G. Knepley PetscInt *localPointsUn;
185522fd0ad9SVaclav Hapla PetscInt numRoots, numLeaves, l;
18565c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0;
18575c7de58aSMatthew G. Knepley
18585c7de58aSMatthew G. Knepley /* Get original SF information */
18599566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint));
1860d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE));
18619566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(udm, &sfPointUn));
18629566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints));
186322fd0ad9SVaclav Hapla if (numRoots >= 0) {
18645c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */
186522fd0ad9SVaclav Hapla for (l = 0; l < numLeaves; ++l) {
186622fd0ad9SVaclav Hapla const PetscInt p = localPoints[l];
186722fd0ad9SVaclav Hapla
186822fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++;
186922fd0ad9SVaclav Hapla }
18705c7de58aSMatthew G. Knepley /* Fill in leaves */
18719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn));
18729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn));
18735c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) {
187422fd0ad9SVaclav Hapla const PetscInt p = localPoints[l];
187522fd0ad9SVaclav Hapla
187622fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) {
187722fd0ad9SVaclav Hapla localPointsUn[n] = p;
18785c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank;
18795c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index;
18805c7de58aSMatthew G. Knepley ++n;
18815c7de58aSMatthew G. Knepley }
18825c7de58aSMatthew G. Knepley }
188363a3b9bcSJacob Faibussowitsch PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn);
188422fd0ad9SVaclav Hapla PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER));
18855c7de58aSMatthew G. Knepley }
18865c7de58aSMatthew G. Knepley }
1887827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */
1888827c4036SVaclav Hapla {
1889d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)udm->data;
1890827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE;
1891827c4036SVaclav Hapla }
18925de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm));
1893d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE));
18944e3744c5SMatthew G. Knepley *dmUnint = udm;
1895172ee266SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0));
18963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
18974e3744c5SMatthew G. Knepley }
1898a7748839SVaclav Hapla
DMPlexIsInterpolated_Internal(DM dm,DMPlexInterpolatedFlag * interpolated)1899d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated)
1900d71ae5a4SJacob Faibussowitsch {
1901a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd;
1902a7748839SVaclav Hapla MPI_Comm comm;
1903a7748839SVaclav Hapla
1904a7748839SVaclav Hapla PetscFunctionBegin;
19059566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
19079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
1908a7748839SVaclav Hapla
1909a7748839SVaclav Hapla if (depth == dim) {
1910a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL;
1911a7748839SVaclav Hapla if (!dim) goto finish;
1912a7748839SVaclav Hapla
1913a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */
19149566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd));
1915a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) {
19169566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1917a7748839SVaclav Hapla if (coneSize) {
1918a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1919a7748839SVaclav Hapla goto finish;
1920a7748839SVaclav Hapla }
1921a7748839SVaclav Hapla }
1922a7748839SVaclav Hapla
1923a7748839SVaclav Hapla /* Check points at height < dim have cones */
1924a7748839SVaclav Hapla for (h = 0; h < dim; h++) {
19259566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
1926a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) {
19279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1928a7748839SVaclav Hapla if (!coneSize) {
1929a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1930a7748839SVaclav Hapla goto finish;
1931a7748839SVaclav Hapla }
1932a7748839SVaclav Hapla }
1933a7748839SVaclav Hapla }
1934a7748839SVaclav Hapla } else if (depth == 1) {
1935a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE;
1936a7748839SVaclav Hapla } else {
1937a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL;
1938a7748839SVaclav Hapla }
1939a7748839SVaclav Hapla finish:
19403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1941a7748839SVaclav Hapla }
1942a7748839SVaclav Hapla
1943a7748839SVaclav Hapla /*@
194420f4b53cSBarry Smith DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated.
1945a7748839SVaclav Hapla
1946a7748839SVaclav Hapla Not Collective
1947a7748839SVaclav Hapla
1948a7748839SVaclav Hapla Input Parameter:
194920f4b53cSBarry Smith . dm - The `DMPLEX` object
1950a7748839SVaclav Hapla
1951a7748839SVaclav Hapla Output Parameter:
195220f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
1953a7748839SVaclav Hapla
1954a7748839SVaclav Hapla Level: intermediate
1955a7748839SVaclav Hapla
1956a7748839SVaclav Hapla Notes:
195720f4b53cSBarry Smith Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective
19589ade3219SVaclav Hapla so the results can be different on different ranks in special cases.
195920f4b53cSBarry Smith However, `DMPlexInterpolate()` guarantees the result is the same on all.
19609ade3219SVaclav Hapla
196120f4b53cSBarry Smith Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`.
1962a7748839SVaclav Hapla
19639ade3219SVaclav Hapla Developer Notes:
196420f4b53cSBarry Smith Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`.
19659ade3219SVaclav Hapla
196620f4b53cSBarry Smith If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called.
19679ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of
196820f4b53cSBarry Smith `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`.
19699ade3219SVaclav Hapla
197020f4b53cSBarry Smith If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated.
19719ade3219SVaclav Hapla
197220f4b53cSBarry Smith `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`,
197320f4b53cSBarry Smith and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`.
19749ade3219SVaclav Hapla
197520f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
1976a7748839SVaclav Hapla @*/
DMPlexIsInterpolated(DM dm,DMPlexInterpolatedFlag * interpolated)1977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated)
1978d71ae5a4SJacob Faibussowitsch {
1979a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data;
1980a7748839SVaclav Hapla
1981a7748839SVaclav Hapla PetscFunctionBegin;
1982a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19834f572ea9SToby Isaac PetscAssertPointer(interpolated, 2);
1984a7748839SVaclav Hapla if (plex->interpolated < 0) {
19859566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated));
198676bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) {
1987a7748839SVaclav Hapla DMPlexInterpolatedFlag flg;
1988a7748839SVaclav Hapla
19899566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &flg));
1990c282ed06SStefano Zampini PetscCheck(plex->tr || flg == plex->interpolated, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]);
1991a7748839SVaclav Hapla }
1992a7748839SVaclav Hapla *interpolated = plex->interpolated;
19933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1994a7748839SVaclav Hapla }
1995a7748839SVaclav Hapla
1996a7748839SVaclav Hapla /*@
199720f4b53cSBarry Smith DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner).
1998a7748839SVaclav Hapla
19992666ff3cSVaclav Hapla Collective
2000a7748839SVaclav Hapla
2001a7748839SVaclav Hapla Input Parameter:
200220f4b53cSBarry Smith . dm - The `DMPLEX` object
2003a7748839SVaclav Hapla
2004a7748839SVaclav Hapla Output Parameter:
200520f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated
2006a7748839SVaclav Hapla
2007a7748839SVaclav Hapla Level: intermediate
2008a7748839SVaclav Hapla
2009a7748839SVaclav Hapla Notes:
201020f4b53cSBarry Smith Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks.
20119ade3219SVaclav Hapla
201220f4b53cSBarry Smith This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks.
20139ade3219SVaclav Hapla
20149ade3219SVaclav Hapla Developer Notes:
201520f4b53cSBarry Smith Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`.
20169ade3219SVaclav Hapla
201720f4b53cSBarry Smith If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated.
201820f4b53cSBarry Smith `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned;
201920f4b53cSBarry Smith if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`,
20209ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated.
20219ade3219SVaclav Hapla
202220f4b53cSBarry Smith If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective.
2023a7748839SVaclav Hapla
202420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()`
2025a7748839SVaclav Hapla @*/
DMPlexIsInterpolatedCollective(DM dm,DMPlexInterpolatedFlag * interpolated)2026d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated)
2027d71ae5a4SJacob Faibussowitsch {
2028a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data;
2029a7748839SVaclav Hapla PetscBool debug = PETSC_FALSE;
2030a7748839SVaclav Hapla
2031a7748839SVaclav Hapla PetscFunctionBegin;
2032a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20334f572ea9SToby Isaac PetscAssertPointer(interpolated, 2);
20349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL));
2035a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) {
2036a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max;
2037a7748839SVaclav Hapla MPI_Comm comm;
2038a7748839SVaclav Hapla
20399566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
20409566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective));
2041462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm));
2042462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm));
2043a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED;
2044a7748839SVaclav Hapla if (debug) {
2045a7748839SVaclav Hapla PetscMPIInt rank;
2046a7748839SVaclav Hapla
20479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
20489566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]));
20499566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
2050a7748839SVaclav Hapla }
2051a7748839SVaclav Hapla }
2052a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective;
20533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2054a7748839SVaclav Hapla }
2055*5e2c5519SMatthew G. Knepley
2056*5e2c5519SMatthew G. Knepley /*@
2057*5e2c5519SMatthew G. Knepley DMPlexGetInterpolatePreferTensor - Get the flag to prefer tensor order when interpolating a cell
2058*5e2c5519SMatthew G. Knepley
2059*5e2c5519SMatthew G. Knepley Not Collective
2060*5e2c5519SMatthew G. Knepley
2061*5e2c5519SMatthew G. Knepley Input Parameter:
2062*5e2c5519SMatthew G. Knepley . dm - The `DMPLEX` object
2063*5e2c5519SMatthew G. Knepley
2064*5e2c5519SMatthew G. Knepley Output Parameter:
2065*5e2c5519SMatthew G. Knepley . preferTensor - Flag to prefer tensor order
2066*5e2c5519SMatthew G. Knepley
2067*5e2c5519SMatthew G. Knepley Level: intermediate
2068*5e2c5519SMatthew G. Knepley
2069*5e2c5519SMatthew G. Knepley Notes:
2070*5e2c5519SMatthew G. Knepley Currently, this just affects triangular prisms,
2071*5e2c5519SMatthew G. Knepley
2072*5e2c5519SMatthew G. Knepley .seealso: `DMPlexSetInterpolatePreferTensor()`, `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
2073*5e2c5519SMatthew G. Knepley @*/
DMPlexGetInterpolatePreferTensor(DM dm,PetscBool * preferTensor)2074*5e2c5519SMatthew G. Knepley PetscErrorCode DMPlexGetInterpolatePreferTensor(DM dm, PetscBool *preferTensor)
2075*5e2c5519SMatthew G. Knepley {
2076*5e2c5519SMatthew G. Knepley DM_Plex *plex = (DM_Plex *)dm->data;
2077*5e2c5519SMatthew G. Knepley
2078*5e2c5519SMatthew G. Knepley PetscFunctionBegin;
2079*5e2c5519SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2080*5e2c5519SMatthew G. Knepley PetscAssertPointer(preferTensor, 2);
2081*5e2c5519SMatthew G. Knepley *preferTensor = plex->interpolatePreferTensor;
2082*5e2c5519SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2083*5e2c5519SMatthew G. Knepley }
2084*5e2c5519SMatthew G. Knepley
2085*5e2c5519SMatthew G. Knepley /*@
2086*5e2c5519SMatthew G. Knepley DMPlexSetInterpolatePreferTensor - Set the flag to prefer tensor order when interpolating a cell
2087*5e2c5519SMatthew G. Knepley
2088*5e2c5519SMatthew G. Knepley Logically Collective
2089*5e2c5519SMatthew G. Knepley
2090*5e2c5519SMatthew G. Knepley Input Parameters:
2091*5e2c5519SMatthew G. Knepley + dm - The `DMPLEX` object
2092*5e2c5519SMatthew G. Knepley - preferTensor - Flag to prefer tensor order
2093*5e2c5519SMatthew G. Knepley
2094*5e2c5519SMatthew G. Knepley Level: intermediate
2095*5e2c5519SMatthew G. Knepley
2096*5e2c5519SMatthew G. Knepley Notes:
2097*5e2c5519SMatthew G. Knepley Currently, this just affects triangular prisms,
2098*5e2c5519SMatthew G. Knepley
2099*5e2c5519SMatthew G. Knepley .seealso: `DMPlexGetInterpolatePreferTensor()`, `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()`
2100*5e2c5519SMatthew G. Knepley @*/
DMPlexSetInterpolatePreferTensor(DM dm,PetscBool preferTensor)2101*5e2c5519SMatthew G. Knepley PetscErrorCode DMPlexSetInterpolatePreferTensor(DM dm, PetscBool preferTensor)
2102*5e2c5519SMatthew G. Knepley {
2103*5e2c5519SMatthew G. Knepley DM_Plex *plex = (DM_Plex *)dm->data;
2104*5e2c5519SMatthew G. Knepley
2105*5e2c5519SMatthew G. Knepley PetscFunctionBegin;
2106*5e2c5519SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2107*5e2c5519SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, preferTensor, 2);
2108*5e2c5519SMatthew G. Knepley plex->interpolatePreferTensor = preferTensor;
2109*5e2c5519SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2110*5e2c5519SMatthew G. Knepley }
2111