1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2e8f14785SLisandro Dalcin #include <petsc/private/hashmapi.h> 3e8f14785SLisandro Dalcin #include <petsc/private/hashmapij.h> 4e8f14785SLisandro Dalcin 5ea78f98cSLisandro Dalcin const char *const DMPlexInterpolatedFlags[] = {"none", "partial", "mixed", "full", "DMPlexInterpolatedFlag", "DMPLEX_INTERPOLATED_", NULL}; 6a7748839SVaclav Hapla 7e8f14785SLisandro Dalcin /* HashIJKL */ 8e8f14785SLisandro Dalcin 9e8f14785SLisandro Dalcin #include <petsc/private/hashmap.h> 10e8f14785SLisandro Dalcin 119371c9d4SSatish Balay typedef struct _PetscHashIJKLKey { 129371c9d4SSatish Balay PetscInt i, j, k, l; 139371c9d4SSatish Balay } PetscHashIJKLKey; 14e8f14785SLisandro Dalcin 159371c9d4SSatish Balay #define PetscHashIJKLKeyHash(key) PetscHashCombine(PetscHashCombine(PetscHashInt((key).i), PetscHashInt((key).j)), PetscHashCombine(PetscHashInt((key).k), PetscHashInt((key).l))) 16e8f14785SLisandro Dalcin 179371c9d4SSatish Balay #define PetscHashIJKLKeyEqual(k1, k2) (((k1).i == (k2).i) ? ((k1).j == (k2).j) ? ((k1).k == (k2).k) ? ((k1).l == (k2).l) : 0 : 0 : 0) 18e8f14785SLisandro Dalcin 19999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKL, PetscHashIJKLKey, PetscInt, PetscHashIJKLKeyHash, PetscHashIJKLKeyEqual, -1)) 20e8f14785SLisandro Dalcin 213be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1}; 223be36e83SMatthew G. Knepley 239371c9d4SSatish Balay typedef struct _PetscHashIJKLRemoteKey { 249371c9d4SSatish Balay PetscSFNode i, j, k, l; 259371c9d4SSatish Balay } PetscHashIJKLRemoteKey; 263be36e83SMatthew G. Knepley 273be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \ 289371c9d4SSatish 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))) 293be36e83SMatthew G. Knepley 303be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyEqual(k1, k2) \ 313be36e83SMatthew G. Knepley (((k1).i.rank == (k2).i.rank) ? ((k1).i.index == (k2).i.index) ? ((k1).j.rank == (k2).j.rank) ? ((k1).j.index == (k2).j.index) ? ((k1).k.rank == (k2).k.rank) ? ((k1).k.index == (k2).k.index) ? ((k1).l.rank == (k2).l.rank) ? ((k1).l.index == (k2).l.index) : 0 : 0 : 0 : 0 : 0 : 0 : 0) 323be36e83SMatthew G. Knepley 33999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode)) 343be36e83SMatthew G. Knepley 359371c9d4SSatish Balay static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[]) { 363be36e83SMatthew G. Knepley PetscInt i; 373be36e83SMatthew G. Knepley 383be36e83SMatthew G. Knepley PetscFunctionBegin; 393be36e83SMatthew G. Knepley for (i = 1; i < n; ++i) { 403be36e83SMatthew G. Knepley PetscSFNode x = A[i]; 413be36e83SMatthew G. Knepley PetscInt j; 423be36e83SMatthew G. Knepley 433be36e83SMatthew G. Knepley for (j = i - 1; j >= 0; --j) { 443be36e83SMatthew G. Knepley if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break; 453be36e83SMatthew G. Knepley A[j + 1] = A[j]; 463be36e83SMatthew G. Knepley } 473be36e83SMatthew G. Knepley A[j + 1] = x; 483be36e83SMatthew G. Knepley } 493be36e83SMatthew G. Knepley PetscFunctionReturn(0); 503be36e83SMatthew G. Knepley } 519f074e33SMatthew G Knepley 529f074e33SMatthew G Knepley /* 53439ece16SMatthew G. Knepley DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone 54439ece16SMatthew G. Knepley */ 559371c9d4SSatish Balay PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) { 56412e9a14SMatthew G. Knepley DMPolytopeType *typesTmp; 57412e9a14SMatthew G. Knepley PetscInt *sizesTmp, *facesTmp; 58439ece16SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 59439ece16SMatthew G. Knepley 60439ece16SMatthew G. Knepley PetscFunctionBegin; 61439ece16SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62ba2698f1SMatthew G. Knepley if (cone) PetscValidIntPointer(cone, 3); 639566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 649566063dSJacob Faibussowitsch if (faceTypes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &typesTmp)); 659566063dSJacob Faibussowitsch if (faceSizes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &sizesTmp)); 669566063dSJacob Faibussowitsch if (faces) PetscCall(DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp)); 67ba2698f1SMatthew G. Knepley switch (ct) { 68ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 69ba2698f1SMatthew G. Knepley if (numFaces) *numFaces = 0; 70ba2698f1SMatthew G. Knepley break; 71ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 72412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 2; 73412e9a14SMatthew G. Knepley if (faceTypes) { 749371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_POINT; 759371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_POINT; 76412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 77412e9a14SMatthew G. Knepley } 78412e9a14SMatthew G. Knepley if (faceSizes) { 799371c9d4SSatish Balay sizesTmp[0] = 1; 809371c9d4SSatish Balay sizesTmp[1] = 1; 81412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 82412e9a14SMatthew G. Knepley } 83c49d9212SMatthew G. Knepley if (faces) { 849371c9d4SSatish Balay facesTmp[0] = cone[0]; 859371c9d4SSatish Balay facesTmp[1] = cone[1]; 86c49d9212SMatthew G. Knepley *faces = facesTmp; 87c49d9212SMatthew G. Knepley } 88412e9a14SMatthew G. Knepley break; 89412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 90c49d9212SMatthew G. Knepley if (numFaces) *numFaces = 2; 91412e9a14SMatthew G. Knepley if (faceTypes) { 929371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_POINT; 939371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_POINT; 94412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 95412e9a14SMatthew G. Knepley } 96412e9a14SMatthew G. Knepley if (faceSizes) { 979371c9d4SSatish Balay sizesTmp[0] = 1; 989371c9d4SSatish Balay sizesTmp[1] = 1; 99412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 100412e9a14SMatthew G. Knepley } 101412e9a14SMatthew G. Knepley if (faces) { 1029371c9d4SSatish Balay facesTmp[0] = cone[0]; 1039371c9d4SSatish Balay facesTmp[1] = cone[1]; 104412e9a14SMatthew G. Knepley *faces = facesTmp; 105412e9a14SMatthew G. Knepley } 106c49d9212SMatthew G. Knepley break; 107ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 108412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 3; 109412e9a14SMatthew G. Knepley if (faceTypes) { 1109371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1119371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1129371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEGMENT; 113412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 114412e9a14SMatthew G. Knepley } 115412e9a14SMatthew G. Knepley if (faceSizes) { 1169371c9d4SSatish Balay sizesTmp[0] = 2; 1179371c9d4SSatish Balay sizesTmp[1] = 2; 1189371c9d4SSatish Balay sizesTmp[2] = 2; 119412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 120412e9a14SMatthew G. Knepley } 1219a5b13a2SMatthew G Knepley if (faces) { 1229371c9d4SSatish Balay facesTmp[0] = cone[0]; 1239371c9d4SSatish Balay facesTmp[1] = cone[1]; 1249371c9d4SSatish Balay facesTmp[2] = cone[1]; 1259371c9d4SSatish Balay facesTmp[3] = cone[2]; 1269371c9d4SSatish Balay facesTmp[4] = cone[2]; 1279371c9d4SSatish Balay facesTmp[5] = cone[0]; 1289a5b13a2SMatthew G Knepley *faces = facesTmp; 1299a5b13a2SMatthew G Knepley } 1309f074e33SMatthew G Knepley break; 131ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 1329a5b13a2SMatthew G Knepley /* Vertices follow right hand rule */ 133412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 134412e9a14SMatthew G. Knepley if (faceTypes) { 1359371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1369371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1379371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEGMENT; 1389371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEGMENT; 139412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 140412e9a14SMatthew G. Knepley } 141412e9a14SMatthew G. Knepley if (faceSizes) { 1429371c9d4SSatish Balay sizesTmp[0] = 2; 1439371c9d4SSatish Balay sizesTmp[1] = 2; 1449371c9d4SSatish Balay sizesTmp[2] = 2; 1459371c9d4SSatish Balay sizesTmp[3] = 2; 146412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 147412e9a14SMatthew G. Knepley } 1489a5b13a2SMatthew G Knepley if (faces) { 1499371c9d4SSatish Balay facesTmp[0] = cone[0]; 1509371c9d4SSatish Balay facesTmp[1] = cone[1]; 1519371c9d4SSatish Balay facesTmp[2] = cone[1]; 1529371c9d4SSatish Balay facesTmp[3] = cone[2]; 1539371c9d4SSatish Balay facesTmp[4] = cone[2]; 1549371c9d4SSatish Balay facesTmp[5] = cone[3]; 1559371c9d4SSatish Balay facesTmp[6] = cone[3]; 1569371c9d4SSatish Balay facesTmp[7] = cone[0]; 1579a5b13a2SMatthew G Knepley *faces = facesTmp; 1589a5b13a2SMatthew G Knepley } 159412e9a14SMatthew G. Knepley break; 160412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 1619a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 162412e9a14SMatthew G. Knepley if (faceTypes) { 1639371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1649371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1659371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1669371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR; 167412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 168412e9a14SMatthew G. Knepley } 169412e9a14SMatthew G. Knepley if (faceSizes) { 1709371c9d4SSatish Balay sizesTmp[0] = 2; 1719371c9d4SSatish Balay sizesTmp[1] = 2; 1729371c9d4SSatish Balay sizesTmp[2] = 2; 1739371c9d4SSatish Balay sizesTmp[3] = 2; 174412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 175412e9a14SMatthew G. Knepley } 176412e9a14SMatthew G. Knepley if (faces) { 1779371c9d4SSatish Balay facesTmp[0] = cone[0]; 1789371c9d4SSatish Balay facesTmp[1] = cone[1]; 1799371c9d4SSatish Balay facesTmp[2] = cone[2]; 1809371c9d4SSatish Balay facesTmp[3] = cone[3]; 1819371c9d4SSatish Balay facesTmp[4] = cone[0]; 1829371c9d4SSatish Balay facesTmp[5] = cone[2]; 1839371c9d4SSatish Balay facesTmp[6] = cone[1]; 1849371c9d4SSatish Balay facesTmp[7] = cone[3]; 185412e9a14SMatthew G. Knepley *faces = facesTmp; 186412e9a14SMatthew G. Knepley } 1879f074e33SMatthew G Knepley break; 188ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 1892e1b13c2SMatthew G. Knepley /* Vertices of first face follow right hand rule and normal points away from last vertex */ 190412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 191412e9a14SMatthew G. Knepley if (faceTypes) { 1929371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 1939371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 1949371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_TRIANGLE; 1959371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_TRIANGLE; 196412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 197412e9a14SMatthew G. Knepley } 198412e9a14SMatthew G. Knepley if (faceSizes) { 1999371c9d4SSatish Balay sizesTmp[0] = 3; 2009371c9d4SSatish Balay sizesTmp[1] = 3; 2019371c9d4SSatish Balay sizesTmp[2] = 3; 2029371c9d4SSatish Balay sizesTmp[3] = 3; 203412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 204412e9a14SMatthew G. Knepley } 2059a5b13a2SMatthew G Knepley if (faces) { 2069371c9d4SSatish Balay facesTmp[0] = cone[0]; 2079371c9d4SSatish Balay facesTmp[1] = cone[1]; 2089371c9d4SSatish Balay facesTmp[2] = cone[2]; 2099371c9d4SSatish Balay facesTmp[3] = cone[0]; 2109371c9d4SSatish Balay facesTmp[4] = cone[3]; 2119371c9d4SSatish Balay facesTmp[5] = cone[1]; 2129371c9d4SSatish Balay facesTmp[6] = cone[0]; 2139371c9d4SSatish Balay facesTmp[7] = cone[2]; 2149371c9d4SSatish Balay facesTmp[8] = cone[3]; 2159371c9d4SSatish Balay facesTmp[9] = cone[2]; 2169371c9d4SSatish Balay facesTmp[10] = cone[1]; 2179371c9d4SSatish Balay facesTmp[11] = cone[3]; 2189a5b13a2SMatthew G Knepley *faces = facesTmp; 2199a5b13a2SMatthew G Knepley } 2209a5b13a2SMatthew G Knepley break; 221ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 222e368ef20SMatthew G. Knepley /* 7--------6 223e368ef20SMatthew G. Knepley /| /| 224e368ef20SMatthew G. Knepley / | / | 225e368ef20SMatthew G. Knepley 4--------5 | 226e368ef20SMatthew G. Knepley | | | | 227e368ef20SMatthew G. Knepley | | | | 228e368ef20SMatthew G. Knepley | 1--------2 229e368ef20SMatthew G. Knepley | / | / 230e368ef20SMatthew G. Knepley |/ |/ 231e368ef20SMatthew G. Knepley 0--------3 232e368ef20SMatthew G. Knepley */ 233412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 234412e9a14SMatthew G. Knepley if (faceTypes) { 2359371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 2369371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; 2379371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; 2389371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; 2399371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; 2409371c9d4SSatish Balay typesTmp[5] = DM_POLYTOPE_QUADRILATERAL; 241412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 242412e9a14SMatthew G. Knepley } 243412e9a14SMatthew G. Knepley if (faceSizes) { 2449371c9d4SSatish Balay sizesTmp[0] = 4; 2459371c9d4SSatish Balay sizesTmp[1] = 4; 2469371c9d4SSatish Balay sizesTmp[2] = 4; 2479371c9d4SSatish Balay sizesTmp[3] = 4; 2489371c9d4SSatish Balay sizesTmp[4] = 4; 2499371c9d4SSatish Balay sizesTmp[5] = 4; 250412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 251412e9a14SMatthew G. Knepley } 2529a5b13a2SMatthew G Knepley if (faces) { 2539371c9d4SSatish Balay facesTmp[0] = cone[0]; 2549371c9d4SSatish Balay facesTmp[1] = cone[1]; 2559371c9d4SSatish Balay facesTmp[2] = cone[2]; 2569371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 2579371c9d4SSatish Balay facesTmp[4] = cone[4]; 2589371c9d4SSatish Balay facesTmp[5] = cone[5]; 2599371c9d4SSatish Balay facesTmp[6] = cone[6]; 2609371c9d4SSatish Balay facesTmp[7] = cone[7]; /* Top */ 2619371c9d4SSatish Balay facesTmp[8] = cone[0]; 2629371c9d4SSatish Balay facesTmp[9] = cone[3]; 2639371c9d4SSatish Balay facesTmp[10] = cone[5]; 2649371c9d4SSatish Balay facesTmp[11] = cone[4]; /* Front */ 2659371c9d4SSatish Balay facesTmp[12] = cone[2]; 2669371c9d4SSatish Balay facesTmp[13] = cone[1]; 2679371c9d4SSatish Balay facesTmp[14] = cone[7]; 2689371c9d4SSatish Balay facesTmp[15] = cone[6]; /* Back */ 2699371c9d4SSatish Balay facesTmp[16] = cone[3]; 2709371c9d4SSatish Balay facesTmp[17] = cone[2]; 2719371c9d4SSatish Balay facesTmp[18] = cone[6]; 2729371c9d4SSatish Balay facesTmp[19] = cone[5]; /* Right */ 2739371c9d4SSatish Balay facesTmp[20] = cone[0]; 2749371c9d4SSatish Balay facesTmp[21] = cone[4]; 2759371c9d4SSatish Balay facesTmp[22] = cone[7]; 2769371c9d4SSatish Balay facesTmp[23] = cone[1]; /* Left */ 2779a5b13a2SMatthew G Knepley *faces = facesTmp; 2789a5b13a2SMatthew G Knepley } 27999836e0eSStefano Zampini break; 280ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 281412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 282412e9a14SMatthew G. Knepley if (faceTypes) { 2839371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 2849371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 2859371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; 2869371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; 2879371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; 288412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 289412e9a14SMatthew G. Knepley } 290412e9a14SMatthew G. Knepley if (faceSizes) { 2919371c9d4SSatish Balay sizesTmp[0] = 3; 2929371c9d4SSatish Balay sizesTmp[1] = 3; 2939371c9d4SSatish Balay sizesTmp[2] = 4; 2949371c9d4SSatish Balay sizesTmp[3] = 4; 2959371c9d4SSatish Balay sizesTmp[4] = 4; 296412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 297412e9a14SMatthew G. Knepley } 298ba2698f1SMatthew G. Knepley if (faces) { 2999371c9d4SSatish Balay facesTmp[0] = cone[0]; 3009371c9d4SSatish Balay facesTmp[1] = cone[1]; 3019371c9d4SSatish Balay facesTmp[2] = cone[2]; /* Bottom */ 3029371c9d4SSatish Balay facesTmp[3] = cone[3]; 3039371c9d4SSatish Balay facesTmp[4] = cone[4]; 3049371c9d4SSatish Balay facesTmp[5] = cone[5]; /* Top */ 3059371c9d4SSatish Balay facesTmp[6] = cone[0]; 3069371c9d4SSatish Balay facesTmp[7] = cone[2]; 3079371c9d4SSatish Balay facesTmp[8] = cone[4]; 3089371c9d4SSatish Balay facesTmp[9] = cone[3]; /* Back left */ 3099371c9d4SSatish Balay facesTmp[10] = cone[2]; 3109371c9d4SSatish Balay facesTmp[11] = cone[1]; 3119371c9d4SSatish Balay facesTmp[12] = cone[5]; 3129371c9d4SSatish Balay facesTmp[13] = cone[4]; /* Front */ 3139371c9d4SSatish Balay facesTmp[14] = cone[1]; 3149371c9d4SSatish Balay facesTmp[15] = cone[0]; 3159371c9d4SSatish Balay facesTmp[16] = cone[3]; 3169371c9d4SSatish Balay facesTmp[17] = cone[5]; /* Back right */ 317ba2698f1SMatthew G. Knepley *faces = facesTmp; 31899836e0eSStefano Zampini } 31999836e0eSStefano Zampini break; 320ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 321412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 322412e9a14SMatthew G. Knepley if (faceTypes) { 3239371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 3249371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 3259371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3269371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3279371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; 328412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 329412e9a14SMatthew G. Knepley } 330412e9a14SMatthew G. Knepley if (faceSizes) { 3319371c9d4SSatish Balay sizesTmp[0] = 3; 3329371c9d4SSatish Balay sizesTmp[1] = 3; 3339371c9d4SSatish Balay sizesTmp[2] = 4; 3349371c9d4SSatish Balay sizesTmp[3] = 4; 3359371c9d4SSatish Balay sizesTmp[4] = 4; 336412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 337412e9a14SMatthew G. Knepley } 33899836e0eSStefano Zampini if (faces) { 3399371c9d4SSatish Balay facesTmp[0] = cone[0]; 3409371c9d4SSatish Balay facesTmp[1] = cone[1]; 3419371c9d4SSatish Balay facesTmp[2] = cone[2]; /* Bottom */ 3429371c9d4SSatish Balay facesTmp[3] = cone[3]; 3439371c9d4SSatish Balay facesTmp[4] = cone[4]; 3449371c9d4SSatish Balay facesTmp[5] = cone[5]; /* Top */ 3459371c9d4SSatish Balay facesTmp[6] = cone[0]; 3469371c9d4SSatish Balay facesTmp[7] = cone[1]; 3479371c9d4SSatish Balay facesTmp[8] = cone[3]; 3489371c9d4SSatish Balay facesTmp[9] = cone[4]; /* Back left */ 3499371c9d4SSatish Balay facesTmp[10] = cone[1]; 3509371c9d4SSatish Balay facesTmp[11] = cone[2]; 3519371c9d4SSatish Balay facesTmp[12] = cone[4]; 3529371c9d4SSatish Balay facesTmp[13] = cone[5]; /* Back right */ 3539371c9d4SSatish Balay facesTmp[14] = cone[2]; 3549371c9d4SSatish Balay facesTmp[15] = cone[0]; 3559371c9d4SSatish Balay facesTmp[16] = cone[5]; 3569371c9d4SSatish Balay facesTmp[17] = cone[3]; /* Front */ 35799836e0eSStefano Zampini *faces = facesTmp; 35899836e0eSStefano Zampini } 359412e9a14SMatthew G. Knepley break; 360412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 361412e9a14SMatthew G. Knepley /* 7--------6 362412e9a14SMatthew G. Knepley /| /| 363412e9a14SMatthew G. Knepley / | / | 364412e9a14SMatthew G. Knepley 4--------5 | 365412e9a14SMatthew G. Knepley | | | | 366412e9a14SMatthew G. Knepley | | | | 367412e9a14SMatthew G. Knepley | 3--------2 368412e9a14SMatthew G. Knepley | / | / 369412e9a14SMatthew G. Knepley |/ |/ 370412e9a14SMatthew G. Knepley 0--------1 371412e9a14SMatthew G. Knepley */ 372412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 373412e9a14SMatthew G. Knepley if (faceTypes) { 3749371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 3759371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; 3769371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3779371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3789371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3799371c9d4SSatish Balay typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR; 380412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 381412e9a14SMatthew G. Knepley } 382412e9a14SMatthew G. Knepley if (faceSizes) { 3839371c9d4SSatish Balay sizesTmp[0] = 4; 3849371c9d4SSatish Balay sizesTmp[1] = 4; 3859371c9d4SSatish Balay sizesTmp[2] = 4; 3869371c9d4SSatish Balay sizesTmp[3] = 4; 3879371c9d4SSatish Balay sizesTmp[4] = 4; 3889371c9d4SSatish Balay sizesTmp[5] = 4; 389412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 390412e9a14SMatthew G. Knepley } 391412e9a14SMatthew G. Knepley if (faces) { 3929371c9d4SSatish Balay facesTmp[0] = cone[0]; 3939371c9d4SSatish Balay facesTmp[1] = cone[1]; 3949371c9d4SSatish Balay facesTmp[2] = cone[2]; 3959371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 3969371c9d4SSatish Balay facesTmp[4] = cone[4]; 3979371c9d4SSatish Balay facesTmp[5] = cone[5]; 3989371c9d4SSatish Balay facesTmp[6] = cone[6]; 3999371c9d4SSatish Balay facesTmp[7] = cone[7]; /* Top */ 4009371c9d4SSatish Balay facesTmp[8] = cone[0]; 4019371c9d4SSatish Balay facesTmp[9] = cone[1]; 4029371c9d4SSatish Balay facesTmp[10] = cone[4]; 4039371c9d4SSatish Balay facesTmp[11] = cone[5]; /* Front */ 4049371c9d4SSatish Balay facesTmp[12] = cone[1]; 4059371c9d4SSatish Balay facesTmp[13] = cone[2]; 4069371c9d4SSatish Balay facesTmp[14] = cone[5]; 4079371c9d4SSatish Balay facesTmp[15] = cone[6]; /* Right */ 4089371c9d4SSatish Balay facesTmp[16] = cone[2]; 4099371c9d4SSatish Balay facesTmp[17] = cone[3]; 4109371c9d4SSatish Balay facesTmp[18] = cone[6]; 4119371c9d4SSatish Balay facesTmp[19] = cone[7]; /* Back */ 4129371c9d4SSatish Balay facesTmp[20] = cone[3]; 4139371c9d4SSatish Balay facesTmp[21] = cone[0]; 4149371c9d4SSatish Balay facesTmp[22] = cone[7]; 4159371c9d4SSatish Balay facesTmp[23] = cone[4]; /* Left */ 416412e9a14SMatthew G. Knepley *faces = facesTmp; 417412e9a14SMatthew G. Knepley } 41899836e0eSStefano Zampini break; 419da9060c4SMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 420da9060c4SMatthew G. Knepley /* 421da9060c4SMatthew G. Knepley 4---- 422da9060c4SMatthew G. Knepley |\-\ \----- 423da9060c4SMatthew G. Knepley | \ -\ \ 424da9060c4SMatthew G. Knepley | 1--\-----2 425da9060c4SMatthew G. Knepley | / \ / 426da9060c4SMatthew G. Knepley |/ \ / 427da9060c4SMatthew G. Knepley 0--------3 428da9060c4SMatthew G. Knepley */ 429da9060c4SMatthew G. Knepley if (numFaces) *numFaces = 5; 430da9060c4SMatthew G. Knepley if (faceTypes) { 431da9060c4SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 4329371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 4339371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_TRIANGLE; 4349371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_TRIANGLE; 4359371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_TRIANGLE; 436da9060c4SMatthew G. Knepley *faceTypes = typesTmp; 437da9060c4SMatthew G. Knepley } 438da9060c4SMatthew G. Knepley if (faceSizes) { 439da9060c4SMatthew G. Knepley sizesTmp[0] = 4; 4409371c9d4SSatish Balay sizesTmp[1] = 3; 4419371c9d4SSatish Balay sizesTmp[2] = 3; 4429371c9d4SSatish Balay sizesTmp[3] = 3; 4439371c9d4SSatish Balay sizesTmp[4] = 3; 444da9060c4SMatthew G. Knepley *faceSizes = sizesTmp; 445da9060c4SMatthew G. Knepley } 446da9060c4SMatthew G. Knepley if (faces) { 4479371c9d4SSatish Balay facesTmp[0] = cone[0]; 4489371c9d4SSatish Balay facesTmp[1] = cone[1]; 4499371c9d4SSatish Balay facesTmp[2] = cone[2]; 4509371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 4519371c9d4SSatish Balay facesTmp[4] = cone[0]; 4529371c9d4SSatish Balay facesTmp[5] = cone[3]; 4539371c9d4SSatish Balay facesTmp[6] = cone[4]; /* Front */ 4549371c9d4SSatish Balay facesTmp[7] = cone[3]; 4559371c9d4SSatish Balay facesTmp[8] = cone[2]; 4569371c9d4SSatish Balay facesTmp[9] = cone[4]; /* Right */ 4579371c9d4SSatish Balay facesTmp[10] = cone[2]; 4589371c9d4SSatish Balay facesTmp[11] = cone[1]; 4599371c9d4SSatish Balay facesTmp[12] = cone[4]; /* Back */ 4609371c9d4SSatish Balay facesTmp[13] = cone[1]; 4619371c9d4SSatish Balay facesTmp[14] = cone[0]; 4629371c9d4SSatish Balay facesTmp[15] = cone[4]; /* Left */ 463da9060c4SMatthew G. Knepley *faces = facesTmp; 464da9060c4SMatthew G. Knepley } 465da9060c4SMatthew G. Knepley break; 46698921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]); 46799836e0eSStefano Zampini } 46899836e0eSStefano Zampini PetscFunctionReturn(0); 46999836e0eSStefano Zampini } 47099836e0eSStefano Zampini 4719371c9d4SSatish Balay PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) { 47299836e0eSStefano Zampini PetscFunctionBegin; 4739566063dSJacob Faibussowitsch if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes)); 4749566063dSJacob Faibussowitsch if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes)); 4759566063dSJacob Faibussowitsch if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces)); 47699836e0eSStefano Zampini PetscFunctionReturn(0); 47799836e0eSStefano Zampini } 47899836e0eSStefano Zampini 4799a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */ 4809371c9d4SSatish Balay static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm) { 481412e9a14SMatthew G. Knepley DMLabel ctLabel; 4829a5b13a2SMatthew G Knepley PetscHashIJKL faceTable; 483412e9a14SMatthew G. Knepley PetscInt faceTypeNum[DM_NUM_POLYTOPES]; 4849318fe57SMatthew G. Knepley PetscInt depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd; 4859f074e33SMatthew G Knepley 4869f074e33SMatthew G Knepley PetscFunctionBegin; 4879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4889566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLCreate(&faceTable)); 4899566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES)); 4909566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd)); 491412e9a14SMatthew G. Knepley /* Number new faces and save face vertices in hash table */ 4929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart)); 493412e9a14SMatthew G. Knepley fEnd = fStart; 494412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 495412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 496412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 497ba2698f1SMatthew G. Knepley DMPolytopeType ct; 498412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 49999836e0eSStefano Zampini 5009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5029566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 503412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 504412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 505412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 506412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 5079a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 508e8f14785SLisandro Dalcin PetscHashIter iter; 509e8f14785SLisandro Dalcin PetscBool missing; 5109f074e33SMatthew G Knepley 5115f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 512412e9a14SMatthew G. Knepley key.i = face[0]; 513412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 514412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 515412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 5169566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 5179566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 518e9fa77a1SMatthew G. Knepley if (missing) { 5199566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLIterSet(faceTable, iter, fEnd++)); 520412e9a14SMatthew G. Knepley ++faceTypeNum[faceType]; 521e9fa77a1SMatthew G. Knepley } 5229a5b13a2SMatthew G Knepley } 5239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 52499836e0eSStefano Zampini } 525412e9a14SMatthew G. Knepley /* We need to number faces contiguously among types */ 526412e9a14SMatthew G. Knepley { 527412e9a14SMatthew G. Knepley PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0; 52899836e0eSStefano Zampini 5299371c9d4SSatish Balay for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) { 5309371c9d4SSatish Balay if (faceTypeNum[ct]) ++numFT; 5319371c9d4SSatish Balay faceTypeStart[ct] = 0; 5329371c9d4SSatish Balay } 533412e9a14SMatthew G. Knepley if (numFT > 1) { 5349566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLClear(faceTable)); 535412e9a14SMatthew G. Knepley faceTypeStart[0] = fStart; 536412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1]; 537412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 538412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 539412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 540ba2698f1SMatthew G. Knepley DMPolytopeType ct; 541412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 54299836e0eSStefano Zampini 5439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5459566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 546412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 547412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 548412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 549412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 55099836e0eSStefano Zampini PetscHashIJKLKey key; 55199836e0eSStefano Zampini PetscHashIter iter; 55299836e0eSStefano Zampini PetscBool missing; 55399836e0eSStefano Zampini 5545f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 555412e9a14SMatthew G. Knepley key.i = face[0]; 556412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 557412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 558412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 5599566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 5609566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 5619566063dSJacob Faibussowitsch if (missing) PetscCall(PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++)); 56299836e0eSStefano Zampini } 5639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 56499836e0eSStefano Zampini } 565412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) { 5661dca8a05SBarry 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]); 5679a5b13a2SMatthew G Knepley } 5689a5b13a2SMatthew G Knepley } 569412e9a14SMatthew G. Knepley } 570412e9a14SMatthew G. Knepley /* Add new points, always at the end of the numbering */ 5719566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &Np)); 5729566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart))); 5739a5b13a2SMatthew G Knepley /* Set cone sizes */ 574412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 5759566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(idm, "celltype")); 5769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel)); 5779a5b13a2SMatthew G Knepley for (d = 0; d <= depth; ++d) { 578412e9a14SMatthew G. Knepley DMPolytopeType ct; 579412e9a14SMatthew G. Knepley PetscInt coneSize, pStart, pEnd, p; 5809f074e33SMatthew G Knepley 581412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 5829566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 583412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 5849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 5859566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, p, coneSize)); 5869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 5879566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, p, ct)); 5889f074e33SMatthew G Knepley } 5899f074e33SMatthew G Knepley } 590412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 591412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 592412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 593412e9a14SMatthew G. Knepley DMPolytopeType ct; 594412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 595412e9a14SMatthew G. Knepley 5969566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5989566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 5999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, c, ct)); 6009566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, c, numFaces)); 601412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 602412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 603412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 604412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 605412e9a14SMatthew G. Knepley PetscHashIJKLKey key; 606412e9a14SMatthew G. Knepley PetscHashIter iter; 607412e9a14SMatthew G. Knepley PetscBool missing; 608412e9a14SMatthew G. Knepley PetscInt f; 609412e9a14SMatthew G. Knepley 61063a3b9bcSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 611412e9a14SMatthew G. Knepley key.i = face[0]; 612412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 613412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 614412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 6159566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 6169566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 61763a3b9bcSJacob Faibussowitsch PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %" PetscInt_FMT ", lf %" PetscInt_FMT ")", c, cf); 6189566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f)); 6199566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, f, faceSize)); 6209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, f, faceType)); 621412e9a14SMatthew G. Knepley } 6229566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 6239f074e33SMatthew G Knepley } 6249566063dSJacob Faibussowitsch PetscCall(DMSetUp(idm)); 625412e9a14SMatthew G. Knepley /* Initialize cones so we do not need the bash table to tell us that a cone has been set */ 626412e9a14SMatthew G. Knepley { 627412e9a14SMatthew G. Knepley PetscSection cs; 628412e9a14SMatthew G. Knepley PetscInt *cones, csize; 6299a5b13a2SMatthew G Knepley 6309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(idm, &cs)); 6319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(idm, &cones)); 6329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cs, &csize)); 633412e9a14SMatthew G. Knepley for (c = 0; c < csize; ++c) cones[c] = -1; 634412e9a14SMatthew G. Knepley } 635412e9a14SMatthew G. Knepley /* Set cones */ 636412e9a14SMatthew G. Knepley for (d = 0; d <= depth; ++d) { 637412e9a14SMatthew G. Knepley const PetscInt *cone; 638412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 639412e9a14SMatthew G. Knepley 640412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 6419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 642412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 6439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 6449566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(idm, p, cone)); 6459566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &cone)); 6469566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(idm, p, cone)); 6479f074e33SMatthew G Knepley } 6489a5b13a2SMatthew G Knepley } 649412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 650412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 651412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 652ba2698f1SMatthew G. Knepley DMPolytopeType ct; 653412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 65499836e0eSStefano Zampini 6559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 6569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 6579566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 658412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 659412e9a14SMatthew G. Knepley DMPolytopeType faceType = faceTypes[cf]; 660412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 661412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 662412e9a14SMatthew G. Knepley const PetscInt *fcone; 6639a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 664e8f14785SLisandro Dalcin PetscHashIter iter; 665e8f14785SLisandro Dalcin PetscBool missing; 666412e9a14SMatthew G. Knepley PetscInt f; 6679f074e33SMatthew G Knepley 66863a3b9bcSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 669412e9a14SMatthew G. Knepley key.i = face[0]; 670412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 671412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 672412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 6739566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 6749566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 6759566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f)); 6769566063dSJacob Faibussowitsch PetscCall(DMPlexInsertCone(idm, c, cf, f)); 6779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(idm, f, &fcone)); 6789566063dSJacob Faibussowitsch if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face)); 679412e9a14SMatthew G. Knepley { 680412e9a14SMatthew G. Knepley const PetscInt *cone; 681412e9a14SMatthew G. Knepley PetscInt coneSize, ornt; 682a74221b0SStefano Zampini 6839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(idm, f, &coneSize)); 6849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(idm, f, &cone)); 68563a3b9bcSJacob 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); 686d89e6e46SMatthew G. Knepley /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */ 6879566063dSJacob Faibussowitsch PetscCall(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt)); 6889566063dSJacob Faibussowitsch PetscCall(DMPlexInsertConeOrientation(idm, c, cf, ornt)); 68999836e0eSStefano Zampini } 69099836e0eSStefano Zampini } 6919566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 69299836e0eSStefano Zampini } 6939566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLDestroy(&faceTable)); 6949566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(idm)); 6959566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(idm)); 6969f074e33SMatthew G Knepley PetscFunctionReturn(0); 6979f074e33SMatthew G Knepley } 6989f074e33SMatthew G Knepley 6999371c9d4SSatish Balay static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) { 700f80536cbSVaclav Hapla PetscInt nleaves; 701f80536cbSVaclav Hapla PetscInt nranks; 702a0d42dbcSVaclav Hapla const PetscMPIInt *ranks = NULL; 703a0d42dbcSVaclav Hapla const PetscInt *roffset = NULL, *rmine = NULL, *rremote = NULL; 704f80536cbSVaclav Hapla PetscInt n, o, r; 705f80536cbSVaclav Hapla 706f80536cbSVaclav Hapla PetscFunctionBegin; 7079566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote)); 708f80536cbSVaclav Hapla nleaves = roffset[nranks]; 7099566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1)); 710f80536cbSVaclav Hapla for (r = 0; r < nranks; r++) { 711f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 712f80536cbSVaclav Hapla - to unify order with the other side */ 713f80536cbSVaclav Hapla o = roffset[r]; 714f80536cbSVaclav Hapla n = roffset[r + 1] - o; 7159566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n)); 7169566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n)); 7179566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o])); 718f80536cbSVaclav Hapla } 719f80536cbSVaclav Hapla PetscFunctionReturn(0); 720f80536cbSVaclav Hapla } 721f80536cbSVaclav Hapla 7229371c9d4SSatish Balay PetscErrorCode DMPlexOrientInterface_Internal(DM dm) { 723d89e6e46SMatthew G. Knepley PetscSF sf; 724d89e6e46SMatthew G. Knepley const PetscInt *locals; 725d89e6e46SMatthew G. Knepley const PetscSFNode *remotes; 726d89e6e46SMatthew G. Knepley const PetscMPIInt *ranks; 727d89e6e46SMatthew G. Knepley const PetscInt *roffset; 728d89e6e46SMatthew G. Knepley PetscInt *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 729d89e6e46SMatthew G. Knepley PetscInt nroots, p, nleaves, nranks, r, maxConeSize = 0; 730d89e6e46SMatthew G. Knepley PetscInt(*roots)[4], (*leaves)[4], mainCone[4]; 731d89e6e46SMatthew G. Knepley PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4]; 7322e745bdaSMatthew G. Knepley MPI_Comm comm; 73327d0e99aSVaclav Hapla PetscMPIInt rank, size; 7342e745bdaSMatthew G. Knepley PetscInt debug = 0; 7352e745bdaSMatthew G. Knepley 7362e745bdaSMatthew G. Knepley PetscFunctionBegin; 7379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 7389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7409566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 7419566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view")); 742*d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE)); 7439566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes)); 744d89e6e46SMatthew G. Knepley if (nroots < 0) PetscFunctionReturn(0); 7459566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 7469566063dSJacob Faibussowitsch PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1)); 747d89e6e46SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 748d89e6e46SMatthew G. Knepley PetscInt coneSize; 7499566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize)); 750d89e6e46SMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 751d89e6e46SMatthew G. Knepley } 75263a3b9bcSJacob Faibussowitsch PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize); 7539566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks)); 7549e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 755d89e6e46SMatthew G. Knepley const PetscInt *cone; 756d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0; 757d89e6e46SMatthew G. Knepley 7589566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 7599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 760d89e6e46SMatthew G. Knepley /* Ignore vertices */ 76127d0e99aSVaclav Hapla if (coneSize < 2) { 762d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 76327d0e99aSVaclav Hapla roots[p][c] = -1; 76427d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 76527d0e99aSVaclav Hapla } 76627d0e99aSVaclav Hapla continue; 76727d0e99aSVaclav Hapla } 7682e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 769d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); c++) { 7709566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0)); 7718a650c75SVaclav Hapla if (ind0 < 0) { 7728a650c75SVaclav Hapla roots[p][c] = cone[c]; 7738a650c75SVaclav Hapla rootsRanks[p][c] = rank; 774c8148b97SVaclav Hapla } else { 7758a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 7768a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 7778a650c75SVaclav Hapla } 7782e745bdaSMatthew G. Knepley } 779d89e6e46SMatthew G. Knepley for (c = coneSize; c < 4; c++) { 780d89e6e46SMatthew G. Knepley roots[p][c] = -1; 781d89e6e46SMatthew G. Knepley rootsRanks[p][c] = -1; 782d89e6e46SMatthew G. Knepley } 7832e745bdaSMatthew G. Knepley } 7849e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 785d89e6e46SMatthew G. Knepley PetscInt c; 786d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 7878ccb905dSVaclav Hapla leaves[p][c] = -2; 7888ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 7898ccb905dSVaclav Hapla } 790c8148b97SVaclav Hapla } 7919566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 7929566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 7939566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 7949566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 795d89e6e46SMatthew G. Knepley if (debug) { 7969566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 797c5853193SPierre Jolivet if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n")); 798d89e6e46SMatthew G. Knepley } 7999566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL)); 8009e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 801d89e6e46SMatthew G. Knepley DMPolytopeType ct; 802d89e6e46SMatthew G. Knepley const PetscInt *cone; 803d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0, o; 804d89e6e46SMatthew G. Knepley 805d89e6e46SMatthew G. Knepley if (leaves[p][0] < 0) continue; /* Ignore vertices */ 8069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 8079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 8089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 809d89e6e46SMatthew G. Knepley if (debug) { 8109371c9d4SSatish 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])); 811d89e6e46SMatthew G. Knepley } 8129371c9d4SSatish 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]) { 813d89e6e46SMatthew G. Knepley /* Translate these leaves to my cone points; mainCone means desired order p's cone points */ 814d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); ++c) { 815d89e6e46SMatthew G. Knepley PetscInt rS, rN; 816d89e6e46SMatthew G. Knepley 81727d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 818d89e6e46SMatthew G. Knepley /* A local leaf is just taken as it is */ 8199dddd249SSatish Balay mainCone[c] = leaves[p][c]; 82027d0e99aSVaclav Hapla continue; 82127d0e99aSVaclav Hapla } 822f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 823f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 8249566063dSJacob Faibussowitsch PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r)); 82563a3b9bcSJacob 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]); 8261dca8a05SBarry Smith PetscCheck(ranks[r] >= 0 && ranks[r] < size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%" PetscInt_FMT " c=%" PetscInt_FMT " commsize=%d: ranks[%" PetscInt_FMT "] = %d makes no sense", p, c, size, r, ranks[r]); 827f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 828d89e6e46SMatthew G. Knepley rS = roffset[r]; 829d89e6e46SMatthew G. Knepley rN = roffset[r + 1] - rS; 8309566063dSJacob Faibussowitsch PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0)); 83163a3b9bcSJacob 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]); 832f80536cbSVaclav Hapla /* Get the corresponding local point */ 8335f80ce2aSJacob Faibussowitsch mainCone[c] = rmine1[rS + ind0]; 834f80536cbSVaclav Hapla } 83563a3b9bcSJacob 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])); 83627d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 8379566063dSJacob Faibussowitsch PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o)); 8389566063dSJacob Faibussowitsch PetscCall(DMPlexOrientPoint(dm, p, o)); 8399566063dSJacob Faibussowitsch } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n")); 84023aaf07bSVaclav Hapla } 84127d0e99aSVaclav Hapla if (debug) { 8429566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 8439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 8442e745bdaSMatthew G. Knepley } 8459566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view")); 8469566063dSJacob Faibussowitsch PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks)); 8479566063dSJacob Faibussowitsch PetscCall(PetscFree2(rmine1, rremote1)); 8482e745bdaSMatthew G. Knepley PetscFunctionReturn(0); 8492e745bdaSMatthew G. Knepley } 8502e745bdaSMatthew G. Knepley 8519371c9d4SSatish Balay static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[]) { 8522e72742cSMatthew G. Knepley PetscInt idx; 8532e72742cSMatthew G. Knepley PetscMPIInt rank; 8542e72742cSMatthew G. Knepley PetscBool flg; 8557bffde78SMichael Lange 8567bffde78SMichael Lange PetscFunctionBegin; 8579566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg)); 8582e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 8599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8609566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 86163a3b9bcSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx])); 8629566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 8632e72742cSMatthew G. Knepley PetscFunctionReturn(0); 8642e72742cSMatthew G. Knepley } 8652e72742cSMatthew G. Knepley 8669371c9d4SSatish Balay static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) { 8672e72742cSMatthew G. Knepley PetscInt idx; 8682e72742cSMatthew G. Knepley PetscMPIInt rank; 8692e72742cSMatthew G. Knepley PetscBool flg; 8702e72742cSMatthew G. Knepley 8712e72742cSMatthew G. Knepley PetscFunctionBegin; 8729566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg)); 8732e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 8749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8759566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 8762e72742cSMatthew G. Knepley if (idxname) { 87763a3b9bcSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " rank %" PetscInt_FMT " index %" PetscInt_FMT "\n", rank, idxname, idx, a[idx].rank, a[idx].index)); 8782e72742cSMatthew G. Knepley } else { 87963a3b9bcSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]rank %" PetscInt_FMT " index %" PetscInt_FMT "\n", rank, a[idx].rank, a[idx].index)); 8802e72742cSMatthew G. Knepley } 8819566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 8822e72742cSMatthew G. Knepley PetscFunctionReturn(0); 8832e72742cSMatthew G. Knepley } 8842e72742cSMatthew G. Knepley 8859371c9d4SSatish Balay static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed) { 8863be36e83SMatthew G. Knepley PetscSF sf; 8873be36e83SMatthew G. Knepley const PetscInt *locals; 8883be36e83SMatthew G. Knepley PetscMPIInt rank; 8892e72742cSMatthew G. Knepley 8902e72742cSMatthew G. Knepley PetscFunctionBegin; 8919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8929566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 8939566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL)); 8945f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 8952e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 8962e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 8972e72742cSMatthew G. Knepley } else { 8982e72742cSMatthew G. Knepley PetscHashIJKey key; 8993be36e83SMatthew G. Knepley PetscInt l; 9002e72742cSMatthew G. Knepley 9012e72742cSMatthew G. Knepley key.i = remotePoint.index; 9022e72742cSMatthew G. Knepley key.j = remotePoint.rank; 9039566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(remotehash, key, &l)); 9043be36e83SMatthew G. Knepley if (l >= 0) { 9053be36e83SMatthew G. Knepley *localPoint = locals[l]; 9065f80ce2aSJacob Faibussowitsch } else if (mapFailed) *mapFailed = PETSC_TRUE; 9072e72742cSMatthew G. Knepley } 9082e72742cSMatthew G. Knepley PetscFunctionReturn(0); 9092e72742cSMatthew G. Knepley } 9102e72742cSMatthew G. Knepley 9119371c9d4SSatish Balay static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed) { 9123be36e83SMatthew G. Knepley PetscSF sf; 9133be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 9143be36e83SMatthew G. Knepley const PetscSFNode *remotes; 9153be36e83SMatthew G. Knepley PetscInt Nl, l; 9163be36e83SMatthew G. Knepley PetscMPIInt rank; 9173be36e83SMatthew G. Knepley 9183be36e83SMatthew G. Knepley PetscFunctionBegin; 9195f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 9209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9219566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9229566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes)); 9233be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 9249566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 9259566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 9263be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 9279566063dSJacob Faibussowitsch PetscCall(PetscFindInt(localPoint, Nl, locals, &l)); 9289371c9d4SSatish Balay if (l < 0) { 9299371c9d4SSatish Balay if (mapFailed) *mapFailed = PETSC_TRUE; 9309371c9d4SSatish Balay } else *remotePoint = remotes[l]; 9313be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9323be36e83SMatthew G. Knepley owned: 9333be36e83SMatthew G. Knepley remotePoint->rank = rank; 9343be36e83SMatthew G. Knepley remotePoint->index = localPoint; 9353be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9363be36e83SMatthew G. Knepley } 9373be36e83SMatthew G. Knepley 9389371c9d4SSatish Balay static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) { 9393be36e83SMatthew G. Knepley PetscSF sf; 9403be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 9413be36e83SMatthew G. Knepley PetscInt Nl, idx; 9423be36e83SMatthew G. Knepley 9433be36e83SMatthew G. Knepley PetscFunctionBegin; 9443be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 9459566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9469566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL)); 9473be36e83SMatthew G. Knepley if (Nl < 0) PetscFunctionReturn(0); 9489566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, Nl, locals, &idx)); 9499371c9d4SSatish Balay if (idx >= 0) { 9509371c9d4SSatish Balay *isShared = PETSC_TRUE; 9519371c9d4SSatish Balay PetscFunctionReturn(0); 9529371c9d4SSatish Balay } 9539566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 9549566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 9553be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 9563be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9573be36e83SMatthew G. Knepley } 9583be36e83SMatthew G. Knepley 9599371c9d4SSatish Balay static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) { 9603be36e83SMatthew G. Knepley const PetscInt *cone; 9613be36e83SMatthew G. Knepley PetscInt coneSize, c; 9623be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 9633be36e83SMatthew G. Knepley 9643be36e83SMatthew G. Knepley PetscFunctionBegin; 9659566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 9669566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9673be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9683be36e83SMatthew G. Knepley PetscBool pointShared; 9693be36e83SMatthew G. Knepley 9709566063dSJacob Faibussowitsch PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared)); 9713be36e83SMatthew G. Knepley cShared = (PetscBool)(cShared && pointShared); 9723be36e83SMatthew G. Knepley } 9733be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 9743be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9753be36e83SMatthew G. Knepley } 9763be36e83SMatthew G. Knepley 9779371c9d4SSatish Balay static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) { 9783be36e83SMatthew G. Knepley const PetscInt *cone; 9793be36e83SMatthew G. Knepley PetscInt coneSize, c; 9803be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 9813be36e83SMatthew G. Knepley 9823be36e83SMatthew G. Knepley PetscFunctionBegin; 9839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 9849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9853be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9863be36e83SMatthew G. Knepley PetscSFNode rcp; 9875f80ce2aSJacob Faibussowitsch PetscBool mapFailed; 9883be36e83SMatthew G. Knepley 9899566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed)); 9905f80ce2aSJacob Faibussowitsch if (mapFailed) { 9913be36e83SMatthew G. Knepley cmin = missing; 9923be36e83SMatthew G. Knepley } else { 9933be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 9943be36e83SMatthew G. Knepley } 9953be36e83SMatthew G. Knepley } 9963be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 9973be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9983be36e83SMatthew G. Knepley } 9993be36e83SMatthew G. Knepley 10003be36e83SMatthew G. Knepley /* 10013be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 10023be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 10033be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 10043be36e83SMatthew G. Knepley */ 10059371c9d4SSatish Balay static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) { 10063be36e83SMatthew G. Knepley MPI_Comm comm; 10073be36e83SMatthew G. Knepley const PetscInt *support; 1008cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height; 10093be36e83SMatthew G. Knepley PetscMPIInt rank; 10103be36e83SMatthew G. Knepley 10113be36e83SMatthew G. Knepley PetscFunctionBegin; 10129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 10139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10149566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap)); 10159566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 10169566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointHeight(dm, p, &height)); 1017cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight + 1) { 1018cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */ 101963a3b9bcSJacob 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)); 1020cf4dc471SVaclav Hapla PetscFunctionReturn(0); 1021cf4dc471SVaclav Hapla } 10229566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 10239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 10249566063dSJacob Faibussowitsch if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off)); 10253be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 10263be36e83SMatthew G. Knepley const PetscInt face = support[s]; 10273be36e83SMatthew G. Knepley const PetscInt *cone; 10283be36e83SMatthew G. Knepley PetscSFNode cpmin = {-1, -1}, rp = {-1, -1}; 10293be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 10303be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 10313be36e83SMatthew G. Knepley PetscHashIJKey key; 10323be36e83SMatthew G. Knepley 10333be36e83SMatthew G. Knepley /* Only add point once */ 103463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Support face %" PetscInt_FMT "\n", rank, face)); 10353be36e83SMatthew G. Knepley key.i = p; 10363be36e83SMatthew G. Knepley key.j = face; 10379566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(faceHash, key, &f)); 10383be36e83SMatthew G. Knepley if (f >= 0) continue; 10399566063dSJacob Faibussowitsch PetscCall(DMPlexConeIsShared(dm, face, &isShared)); 10409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin)); 10419566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL)); 10423be36e83SMatthew G. Knepley if (debug) { 104363a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared)); 104463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Global point (%" PetscInt_FMT ", %" PetscInt_FMT ") Min Cone Point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index)); 10453be36e83SMatthew G. Knepley } 10463be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 10479566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p)); 10483be36e83SMatthew G. Knepley if (candidates) { 104963a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d] ", rank, face, idx, rank)); 10509566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize)); 10519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, face, &cone)); 10523be36e83SMatthew G. Knepley candidates[off + idx].rank = -1; 10533be36e83SMatthew G. Knepley candidates[off + idx++].index = coneSize - 1; 10543be36e83SMatthew G. Knepley candidates[off + idx].rank = rank; 10553be36e83SMatthew G. Knepley candidates[off + idx++].index = face; 10563be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10573be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 10583be36e83SMatthew G. Knepley 10593be36e83SMatthew G. Knepley if (cp == p) continue; 10609566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL)); 106163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index)); 10623be36e83SMatthew G. Knepley ++idx; 10633be36e83SMatthew G. Knepley } 10649566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n")); 10653be36e83SMatthew G. Knepley } else { 10663be36e83SMatthew G. Knepley /* Add cone size to section */ 106763a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %" PetscInt_FMT "\n", rank, face)); 10689566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize)); 10699566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p)); 10709566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1)); 10713be36e83SMatthew G. Knepley } 10723be36e83SMatthew G. Knepley } 10733be36e83SMatthew G. Knepley } 10743be36e83SMatthew G. Knepley PetscFunctionReturn(0); 10753be36e83SMatthew G. Knepley } 10763be36e83SMatthew G. Knepley 10772e72742cSMatthew G. Knepley /*@ 10782e72742cSMatthew G. Knepley DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation 10792e72742cSMatthew G. Knepley 1080d083f849SBarry Smith Collective on dm 10812e72742cSMatthew G. Knepley 10822e72742cSMatthew G. Knepley Input Parameters: 10832e72742cSMatthew G. Knepley + dm - The interpolated DM 10842e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points 10852e72742cSMatthew G. Knepley 10862e72742cSMatthew G. Knepley Output Parameter: 10872e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points 10882e72742cSMatthew G. Knepley 1089f0cfc026SVaclav Hapla Level: developer 10902e72742cSMatthew G. Knepley 10912e72742cSMatthew G. Knepley Note: All debugging for this process can be turned on with the options: -dm_interp_pre_view -petscsf_interp_pre_view -petscsection_interp_candidate_view -petscsection_interp_candidate_remote_view -petscsection_interp_claim_view -petscsf_interp_pre_view -dmplex_interp_debug 10922e72742cSMatthew G. Knepley 1093db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexUninterpolate()` 10942e72742cSMatthew G. Knepley @*/ 10959371c9d4SSatish Balay PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) { 10963be36e83SMatthew G. Knepley MPI_Comm comm; 10973be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 10983be36e83SMatthew G. Knepley PetscHMapI claimshash; 10993be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 11003be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 11012e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 11022e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 11033be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 11043be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 11053be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 1106f0cfc026SVaclav Hapla PetscMPIInt rank; 11072e72742cSMatthew G. Knepley 11082e72742cSMatthew G. Knepley PetscFunctionBegin; 1109f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1110064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 11119566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &flg)); 1112f0cfc026SVaclav Hapla if (!flg) PetscFunctionReturn(0); 11133be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 11149566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 11159566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11179566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &ov)); 111828b400f6SJacob Faibussowitsch PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 11199566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug)); 11209566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view")); 11219566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view")); 11229566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0)); 11233be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 11249566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints)); 112508401ef6SPierre Jolivet PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 11269566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&remoteHash)); 11273be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11283be36e83SMatthew G. Knepley PetscHashIJKey key; 11292e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 11302e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 11319566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(remoteHash, key, l)); 11327bffde78SMichael Lange } 113366aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 11349566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 11359566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 11369566063dSJacob Faibussowitsch PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree)); 11373be36e83SMatthew G. Knepley /* 11383be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 11393be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 11403be36e83SMatthew G. Knepley \begin{itemize} 11413be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 11423be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 11433be36e83SMatthew G. Knepley \end{itemize} 11443be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 11453be36e83SMatthew 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 11463be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 11473be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 11483be36e83SMatthew G. Knepley */ 11493be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 11503be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 11513be36e83SMatthew G. Knepley The array holds candidate shared faces, each face is refered to by the leaf point */ 11529566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateSection)); 11539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(candidateSection, 0, Nr)); 11547bffde78SMichael Lange { 11553be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 11562e72742cSMatthew G. Knepley 11579566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&faceHash)); 11583be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11593be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 11602e72742cSMatthew G. Knepley 116163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %" PetscInt_FMT "\n", rank, p)); 11629566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug)); 11632e72742cSMatthew G. Knepley } 11649566063dSJacob Faibussowitsch PetscCall(PetscHMapIJClear(faceHash)); 11659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(candidateSection)); 11669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize)); 11679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesSize, &candidates)); 11683be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11693be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 11702e72742cSMatthew G. Knepley 117163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %" PetscInt_FMT "\n", rank, p)); 11729566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug)); 11732e72742cSMatthew G. Knepley } 11749566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&faceHash)); 11759566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 11767bffde78SMichael Lange } 11779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section")); 11789566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view")); 11799566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates)); 11803be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 11812e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 11827bffde78SMichael Lange { 11837bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 11847bffde78SMichael Lange PetscInt *remoteOffsets; 11852e72742cSMatthew G. Knepley 11869566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti)); 11879566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse)); 11889566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateRemoteSection)); 11899566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection)); 11909566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates)); 11919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize)); 11929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote)); 11939566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE)); 11949566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE)); 11959566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfInverse)); 11969566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfCandidates)); 11979566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 11982e72742cSMatthew G. Knepley 11999566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section")); 12009566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view")); 12019566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote)); 12027bffde78SMichael Lange } 12033be36e83SMatthew 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 */ 12047bffde78SMichael Lange { 12053be36e83SMatthew G. Knepley PetscHashIJKLRemote faceTable; 12063be36e83SMatthew G. Knepley PetscInt idx, idx2; 12073be36e83SMatthew G. Knepley 12089566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteCreate(&faceTable)); 12092e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 12103be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 12112e72742cSMatthew G. Knepley PetscInt deg; 12123be36e83SMatthew G. Knepley 12132e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 12142e72742cSMatthew G. Knepley PetscInt offset, dof, d; 12152e72742cSMatthew G. Knepley 12169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof)); 12179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset)); 12183be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 12192e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12203be36e83SMatthew G. Knepley const PetscInt hidx = offset + d; 12213be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1; 12223be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx + 1]; 12233be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2]; 12243be36e83SMatthew G. Knepley PetscSFNode fcp0; 12253be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 12262e72742cSMatthew G. Knepley const PetscInt *join = NULL; 12273be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 12283be36e83SMatthew G. Knepley PetscHashIter iter; 12295f80ce2aSJacob Faibussowitsch PetscBool missing, mapToLocalPointFailed = PETSC_FALSE; 12302e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 12312e72742cSMatthew G. Knepley 12329371c9d4SSatish Balay if (debug) 12339371c9d4SSatish Balay PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Checking face (%" PetscInt_FMT ", %" PetscInt_FMT ") at (%" PetscInt_FMT ", %" PetscInt_FMT ", %" PetscInt_FMT ") with cone size %" PetscInt_FMT "\n", rank, rface.rank, 12349371c9d4SSatish Balay rface.index, r, idx, d, Np)); 123563a3b9bcSJacob Faibussowitsch PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle face (%" PetscInt_FMT ", %" PetscInt_FMT ") at (%" PetscInt_FMT ", %" PetscInt_FMT ", %" PetscInt_FMT ") with %" PetscInt_FMT " cone points", rface.rank, rface.index, r, idx, d, Np); 12363be36e83SMatthew G. Knepley fcp0.rank = rank; 12373be36e83SMatthew G. Knepley fcp0.index = r; 12383be36e83SMatthew G. Knepley d += Np; 12393be36e83SMatthew G. Knepley /* Put remote face in hash table */ 12403be36e83SMatthew G. Knepley key.i = fcp0; 12413be36e83SMatthew G. Knepley key.j = fcone[0]; 12423be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 12433be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 12449566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key)); 12459566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing)); 12463be36e83SMatthew G. Knepley if (missing) { 124763a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank)); 12489566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface)); 12493be36e83SMatthew G. Knepley } else { 12503be36e83SMatthew G. Knepley PetscSFNode oface; 12513be36e83SMatthew G. Knepley 12529566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface)); 12533be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 125463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank)); 12559566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface)); 12563be36e83SMatthew G. Knepley } 12573be36e83SMatthew G. Knepley } 12583be36e83SMatthew G. Knepley /* Check for local face */ 12592e72742cSMatthew G. Knepley points[0] = r; 12603be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 12619566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed)); 12625f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) break; /* We got a point not in our overlap */ 126363a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Checking local candidate %" PetscInt_FMT "\n", rank, points[p])); 12647bffde78SMichael Lange } 12655f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) continue; 12669566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join)); 12677bffde78SMichael Lange if (joinSize == 1) { 12683be36e83SMatthew G. Knepley PetscSFNode lface; 12693be36e83SMatthew G. Knepley PetscSFNode oface; 12703be36e83SMatthew G. Knepley 12713be36e83SMatthew G. Knepley /* Always replace with local face */ 12723be36e83SMatthew G. Knepley lface.rank = rank; 12733be36e83SMatthew G. Knepley lface.index = join[0]; 12749566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface)); 12759371c9d4SSatish Balay if (debug) 12769371c9d4SSatish Balay PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Replacing (%" PetscInt_FMT ", %" PetscInt_FMT ") with local face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, oface.index, oface.rank, lface.index, lface.rank)); 12779566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, lface)); 12787bffde78SMichael Lange } 12799566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join)); 12803be36e83SMatthew G. Knepley } 12813be36e83SMatthew G. Knepley } 12823be36e83SMatthew G. Knepley /* Put back faces for this root */ 12833be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 12843be36e83SMatthew G. Knepley PetscInt offset, dof, d; 12853be36e83SMatthew G. Knepley 12869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof)); 12879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset)); 12883be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 12893be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 12903be36e83SMatthew G. Knepley const PetscInt hidx = offset + d; 12913be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1; 12923be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2]; 12933be36e83SMatthew G. Knepley PetscSFNode fcp0; 12943be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 12953be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 12963be36e83SMatthew G. Knepley PetscHashIter iter; 12973be36e83SMatthew G. Knepley PetscBool missing; 12983be36e83SMatthew G. Knepley 129963a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx)); 130063a3b9bcSJacob Faibussowitsch PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np); 13013be36e83SMatthew G. Knepley fcp0.rank = rank; 13023be36e83SMatthew G. Knepley fcp0.index = r; 13033be36e83SMatthew G. Knepley d += Np; 13043be36e83SMatthew G. Knepley /* Find remote face in hash table */ 13053be36e83SMatthew G. Knepley key.i = fcp0; 13063be36e83SMatthew G. Knepley key.j = fcone[0]; 13073be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 13083be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 13099566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key)); 13109371c9d4SSatish Balay if (debug) 13119371c9d4SSatish Balay PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] key (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ") (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, 13129371c9d4SSatish Balay key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index)); 13139566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing)); 131463a3b9bcSJacob Faibussowitsch PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2); 1315f7d195e4SLawrence Mitchell PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx])); 13167bffde78SMichael Lange } 13177bffde78SMichael Lange } 13187bffde78SMichael Lange } 13199566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL)); 13209566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteDestroy(&faceTable)); 13217bffde78SMichael Lange } 13223be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 13237bffde78SMichael Lange { 13247bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 13257bffde78SMichael Lange PetscSFNode *remotePointsNew; 13262e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 13273be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 13282e72742cSMatthew G. Knepley 13293be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 13309566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti)); 13319566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &claimSection)); 13329566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection)); 13339566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims)); 13349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize)); 13359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(claimsSize, &claims)); 13363be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 13379566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE)); 13389566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE)); 13399566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfClaims)); 13409566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 13419566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section")); 13429566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view")); 13439566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims)); 13443be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 13453be36e83SMatthew 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 */ 13469566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&claimshash)); 13473be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 13483be36e83SMatthew G. Knepley PetscInt dof, off, d; 13492e72742cSMatthew G. Knepley 135063a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %" PetscInt_FMT "\n", rank, r)); 13519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateSection, r, &dof)); 13529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateSection, r, &off)); 13532e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 13543be36e83SMatthew G. Knepley if (claims[off + d].rank >= 0) { 13553be36e83SMatthew G. Knepley const PetscInt faceInd = off + d; 13563be36e83SMatthew G. Knepley const PetscInt Np = candidates[off + d].index; 13572e72742cSMatthew G. Knepley const PetscInt *join = NULL; 13582e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 13592e72742cSMatthew G. Knepley 136063a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index)); 13613be36e83SMatthew G. Knepley points[0] = r; 136263a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[0])); 13633be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 13649566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL)); 136563a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[c + 1])); 13662e72742cSMatthew G. Knepley } 13679566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join)); 13682e72742cSMatthew G. Knepley if (joinSize == 1) { 13693be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 137063a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0])); 13713be36e83SMatthew G. Knepley } else { 137263a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found local face %" PetscInt_FMT "\n", rank, join[0])); 13739566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(claimshash, join[0], faceInd)); 13742e72742cSMatthew G. Knepley } 13753be36e83SMatthew G. Knepley } else { 13769566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank)); 13773be36e83SMatthew G. Knepley } 13789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join)); 13793be36e83SMatthew G. Knepley } else { 138063a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] No claim for point %" PetscInt_FMT "\n", rank, r)); 13813be36e83SMatthew G. Knepley d += claims[off + d].index + 1; 13827bffde78SMichael Lange } 13837bffde78SMichael Lange } 13843be36e83SMatthew G. Knepley } 13859566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 13863be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 13879566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(claimshash, &NlNew)); 13889566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 13899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew)); 13909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew)); 13913be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 13923be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 13933be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 13943be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 13957bffde78SMichael Lange } 13963be36e83SMatthew G. Knepley p = Nl; 13979566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew)); 13983be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 13999566063dSJacob Faibussowitsch PetscCall(PetscSortInt(NlNew, &localPointsNew[Nl])); 14003be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 14013be36e83SMatthew G. Knepley PetscInt off; 14029566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off)); 14031dca8a05SBarry Smith PetscCheck(claims[off].rank >= 0 && claims[off].index >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %" PetscInt_FMT ", (%" PetscInt_FMT ", %" PetscInt_FMT ")", localPointsNew[p], claims[off].rank, claims[off].index); 14043be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 14057bffde78SMichael Lange } 14069566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfPointNew)); 14079566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 14089566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfPointNew)); 14099566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPointNew)); 14109566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view")); 1411*d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE)); 14129566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPointNew)); 14139566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&claimshash)); 14147bffde78SMichael Lange } 14159566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&remoteHash)); 14169566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateSection)); 14179566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateRemoteSection)); 14189566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&claimSection)); 14199566063dSJacob Faibussowitsch PetscCall(PetscFree(candidates)); 14209566063dSJacob Faibussowitsch PetscCall(PetscFree(candidatesRemote)); 14219566063dSJacob Faibussowitsch PetscCall(PetscFree(claims)); 14229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0)); 14237bffde78SMichael Lange PetscFunctionReturn(0); 14247bffde78SMichael Lange } 14257bffde78SMichael Lange 1426248eb259SVaclav Hapla /*@ 142780330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 142880330477SMatthew G. Knepley 1429d083f849SBarry Smith Collective on dm 143080330477SMatthew G. Knepley 1431e56d480eSMatthew G. Knepley Input Parameters: 1432e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices 143310a67516SMatthew G. Knepley - dmInt - The interpolated DM 143480330477SMatthew G. Knepley 143580330477SMatthew G. Knepley Output Parameter: 14364e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object 143780330477SMatthew G. Knepley 143880330477SMatthew G. Knepley Level: intermediate 143980330477SMatthew G. Knepley 144095452b02SPatrick Sanan Notes: 14417fb59074SVaclav Hapla Labels and coordinates are copied. 144243eeeb2dSStefano Zampini 14439ade3219SVaclav Hapla Developer Notes: 14449ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL. 14459ade3219SVaclav Hapla 1446db781477SPatrick Sanan .seealso: `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()` 144780330477SMatthew G. Knepley @*/ 14489371c9d4SSatish Balay PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) { 1449a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 14509a5b13a2SMatthew G Knepley DM idm, odm = dm; 14517bffde78SMichael Lange PetscSF sfPoint; 14522e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 145310a67516SMatthew G. Knepley const char *name; 1454b325530aSVaclav Hapla PetscBool flg = PETSC_TRUE; 14559f074e33SMatthew G Knepley 14569f074e33SMatthew G Knepley PetscFunctionBegin; 145710a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 145810a67516SMatthew G. Knepley PetscValidPointer(dmInt, 2); 14599566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0)); 14609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 14619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 14629566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 146308401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1464827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 14659566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 146676b791aaSMatthew G. Knepley idm = dm; 1467b21b8912SMatthew G. Knepley } else { 14689a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 14699a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 14709566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm)); 14719566063dSJacob Faibussowitsch PetscCall(DMSetType(idm, DMPLEX)); 14729566063dSJacob Faibussowitsch PetscCall(DMSetDimension(idm, dim)); 14737bffde78SMichael Lange if (depth > 0) { 14749566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm)); 14759566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(odm, &sfPoint)); 1476*d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE)); 147794488200SVaclav Hapla { 14783be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 147994488200SVaclav Hapla PetscInt nroots; 14809566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 14819566063dSJacob Faibussowitsch if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint)); 148294488200SVaclav Hapla } 14837bffde78SMichael Lange } 14849566063dSJacob Faibussowitsch if (odm != dm) PetscCall(DMDestroy(&odm)); 14859a5b13a2SMatthew G Knepley odm = idm; 14869f074e33SMatthew G Knepley } 14879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 14889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)idm, name)); 14899566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 14909566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL)); 14919566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL)); 14929566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexOrientInterface_Internal(idm)); 149384699f70SSatish Balay } 1494827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1495827c4036SVaclav Hapla { 1496d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)idm->data; 1497827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1498827c4036SVaclav Hapla } 14995de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm)); 15009a5b13a2SMatthew G Knepley *dmInt = idm; 15019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0)); 15029f074e33SMatthew G Knepley PetscFunctionReturn(0); 15039f074e33SMatthew G Knepley } 150407b0a1fcSMatthew G Knepley 150580330477SMatthew G. Knepley /*@ 150680330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 150780330477SMatthew G. Knepley 1508d083f849SBarry Smith Collective on dmA 150980330477SMatthew G. Knepley 151080330477SMatthew G. Knepley Input Parameter: 151180330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates 151280330477SMatthew G. Knepley 151380330477SMatthew G. Knepley Output Parameter: 151480330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates 151580330477SMatthew G. Knepley 151680330477SMatthew G. Knepley Level: intermediate 151780330477SMatthew G. Knepley 151880330477SMatthew G. Knepley Note: This is typically used when adding pieces other than vertices to a mesh 151980330477SMatthew G. Knepley 1520db781477SPatrick Sanan .seealso: `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()` 152180330477SMatthew G. Knepley @*/ 15229371c9d4SSatish Balay PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) { 152307b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 152443eeeb2dSStefano Zampini VecType vtype; 152507b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 152607b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 15270bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 152890a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 152943eeeb2dSStefano Zampini PetscBool lc = PETSC_FALSE; 153007b0a1fcSMatthew G Knepley 153107b0a1fcSMatthew G Knepley PetscFunctionBegin; 153243eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 153343eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 153476b791aaSMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 15359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &cdim)); 15369566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dmB, cdim)); 15379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA)); 15389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB)); 153963a3b9bcSJacob 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); 154061a622f3SMatthew G. Knepley /* Copy over discretization if it exists */ 154161a622f3SMatthew G. Knepley { 154261a622f3SMatthew G. Knepley DM cdmA, cdmB; 154361a622f3SMatthew G. Knepley PetscDS dsA, dsB; 154461a622f3SMatthew G. Knepley PetscObject objA, objB; 154561a622f3SMatthew G. Knepley PetscClassId idA, idB; 154661a622f3SMatthew G. Knepley const PetscScalar *constants; 154761a622f3SMatthew G. Knepley PetscInt cdim, Nc; 154861a622f3SMatthew G. Knepley 15499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &cdmA)); 15509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &cdmB)); 15519566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmA, 0, NULL, &objA)); 15529566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmB, 0, NULL, &objB)); 15539566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objA, &idA)); 15549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objB, &idB)); 155561a622f3SMatthew G. Knepley if ((idA == PETSCFE_CLASSID) && (idA != idB)) { 15569566063dSJacob Faibussowitsch PetscCall(DMSetField(cdmB, 0, NULL, objA)); 15579566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdmB)); 15589566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmA, &dsA)); 15599566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmB, &dsB)); 15609566063dSJacob Faibussowitsch PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim)); 15619566063dSJacob Faibussowitsch PetscCall(PetscDSSetCoordinateDimension(dsB, cdim)); 15629566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(dsA, &Nc, &constants)); 15639566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants)); 156461a622f3SMatthew G. Knepley } 156561a622f3SMatthew G. Knepley } 15669566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA)); 15679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB)); 15689566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmA, &coordSectionA)); 15699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmB, &coordSectionB)); 1570972bc18aSToby Isaac if (coordSectionA == coordSectionB) PetscFunctionReturn(0); 15719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf)); 15720bedd6beSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 157363a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf); 1574df26b574SMatthew G. Knepley if (!coordSectionB) { 1575df26b574SMatthew G. Knepley PetscInt dim; 1576df26b574SMatthew G. Knepley 15779566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB)); 15789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &dim)); 15799566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB)); 15809566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordSectionB)); 1581df26b574SMatthew G. Knepley } 15829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSectionB, 1)); 15839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim)); 15849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim)); 15859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE)); 158643eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 158763a3b9bcSJacob Faibussowitsch PetscCheck((cEndA - cStartA) == (cEndB - cStartB), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %" PetscInt_FMT " != %" PetscInt_FMT " in the second DM", cEndA - cStartA, cEndB - cStartB); 158843eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 158943eeeb2dSStefano Zampini cE = vEndB; 159043eeeb2dSStefano Zampini lc = PETSC_TRUE; 159143eeeb2dSStefano Zampini } else { 159243eeeb2dSStefano Zampini cS = vStartB; 159343eeeb2dSStefano Zampini cE = vEndB; 159443eeeb2dSStefano Zampini } 15959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSectionB, cS, cE)); 159607b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 15979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim)); 15989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim)); 159907b0a1fcSMatthew G Knepley } 160043eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 160143eeeb2dSStefano Zampini PetscInt c; 160243eeeb2dSStefano Zampini 160343eeeb2dSStefano Zampini for (c = cS - cStartB; c < cEndB - cStartB; c++) { 160443eeeb2dSStefano Zampini PetscInt dof; 160543eeeb2dSStefano Zampini 16069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof)); 16079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSectionB, c + cStartB, dof)); 16089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof)); 160943eeeb2dSStefano Zampini } 161043eeeb2dSStefano Zampini } 16119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSectionB)); 16129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB)); 16139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA)); 16149566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB)); 16159566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates")); 16169566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE)); 16179566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(coordinatesA, &d)); 16189566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinatesB, d)); 16199566063dSJacob Faibussowitsch PetscCall(VecGetType(coordinatesA, &vtype)); 16209566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinatesB, vtype)); 16219566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesA, &coordsA)); 16229566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesB, &coordsB)); 162307b0a1fcSMatthew G Knepley for (v = 0; v < vEndB - vStartB; ++v) { 162443eeeb2dSStefano Zampini PetscInt offA, offB; 162543eeeb2dSStefano Zampini 16269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA)); 16279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB)); 1628ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d]; 162943eeeb2dSStefano Zampini } 163043eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 163143eeeb2dSStefano Zampini PetscInt c; 163243eeeb2dSStefano Zampini 163343eeeb2dSStefano Zampini for (c = cS - cStartB; c < cEndB - cStartB; c++) { 163443eeeb2dSStefano Zampini PetscInt dof, offA, offB; 163543eeeb2dSStefano Zampini 16369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA)); 16379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB)); 16389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof)); 16399566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(coordsB + offB, coordsA + offA, dof)); 164007b0a1fcSMatthew G Knepley } 164107b0a1fcSMatthew G Knepley } 16429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesA, &coordsA)); 16439566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesB, &coordsB)); 16449566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB)); 16459566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinatesB)); 164607b0a1fcSMatthew G Knepley PetscFunctionReturn(0); 164707b0a1fcSMatthew G Knepley } 16485c386225SMatthew G. Knepley 16494e3744c5SMatthew G. Knepley /*@ 16504e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 16514e3744c5SMatthew G. Knepley 1652d083f849SBarry Smith Collective on dm 16534e3744c5SMatthew G. Knepley 16544e3744c5SMatthew G. Knepley Input Parameter: 16554e3744c5SMatthew G. Knepley . dm - The complete DMPlex object 16564e3744c5SMatthew G. Knepley 16574e3744c5SMatthew G. Knepley Output Parameter: 16584e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices 16594e3744c5SMatthew G. Knepley 16604e3744c5SMatthew G. Knepley Level: intermediate 16614e3744c5SMatthew G. Knepley 166295452b02SPatrick Sanan Notes: 166395452b02SPatrick Sanan It does not copy over the coordinates. 166443eeeb2dSStefano Zampini 16659ade3219SVaclav Hapla Developer Notes: 16669ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 16679ade3219SVaclav Hapla 1668db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()` 16694e3744c5SMatthew G. Knepley @*/ 16709371c9d4SSatish Balay PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) { 1671827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 16724e3744c5SMatthew G. Knepley DM udm; 1673412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; 16744e3744c5SMatthew G. Knepley 16754e3744c5SMatthew G. Knepley PetscFunctionBegin; 167643eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 167743eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 16789566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 16799566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 168008401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1681827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1682827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 16839566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 1684595d4abbSMatthew G. Knepley *dmUnint = dm; 1685595d4abbSMatthew G. Knepley PetscFunctionReturn(0); 16864e3744c5SMatthew G. Knepley } 16879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 16889566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 16899566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm)); 16909566063dSJacob Faibussowitsch PetscCall(DMSetType(udm, DMPLEX)); 16919566063dSJacob Faibussowitsch PetscCall(DMSetDimension(udm, dim)); 16929566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(udm, cStart, vEnd)); 16934e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1694595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 16954e3744c5SMatthew G. Knepley 16969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 16974e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 16984e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 16994e3744c5SMatthew G. Knepley 17004e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 17014e3744c5SMatthew G. Knepley } 17029566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 17039566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(udm, c, coneSize)); 1704595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 17054e3744c5SMatthew G. Knepley } 17069566063dSJacob Faibussowitsch PetscCall(DMSetUp(udm)); 17079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConeSize, &cone)); 17084e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1709595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 17104e3744c5SMatthew G. Knepley 17119566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 17124e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 17134e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 17144e3744c5SMatthew G. Knepley 17154e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 17164e3744c5SMatthew G. Knepley } 17179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 17189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(udm, c, cone)); 17194e3744c5SMatthew G. Knepley } 17209566063dSJacob Faibussowitsch PetscCall(PetscFree(cone)); 17219566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(udm)); 17229566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(udm)); 17235c7de58aSMatthew G. Knepley /* Reduce SF */ 17245c7de58aSMatthew G. Knepley { 17255c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 17265c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 17275c7de58aSMatthew G. Knepley const PetscInt *localPoints; 17285c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 17295c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 173022fd0ad9SVaclav Hapla PetscInt numRoots, numLeaves, l; 17315c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 17325c7de58aSMatthew G. Knepley 17335c7de58aSMatthew G. Knepley /* Get original SF information */ 17349566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 1735*d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE)); 17369566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(udm, &sfPointUn)); 17379566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 173822fd0ad9SVaclav Hapla if (numRoots >= 0) { 17395c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 174022fd0ad9SVaclav Hapla for (l = 0; l < numLeaves; ++l) { 174122fd0ad9SVaclav Hapla const PetscInt p = localPoints[l]; 174222fd0ad9SVaclav Hapla 174322fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++; 174422fd0ad9SVaclav Hapla } 17455c7de58aSMatthew G. Knepley /* Fill in leaves */ 17469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn)); 17479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn)); 17485c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 174922fd0ad9SVaclav Hapla const PetscInt p = localPoints[l]; 175022fd0ad9SVaclav Hapla 175122fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) { 175222fd0ad9SVaclav Hapla localPointsUn[n] = p; 17535c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 17545c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 17555c7de58aSMatthew G. Knepley ++n; 17565c7de58aSMatthew G. Knepley } 17575c7de58aSMatthew G. Knepley } 175863a3b9bcSJacob Faibussowitsch PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn); 175922fd0ad9SVaclav Hapla PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER)); 17605c7de58aSMatthew G. Knepley } 17615c7de58aSMatthew G. Knepley } 1762827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1763827c4036SVaclav Hapla { 1764d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)udm->data; 1765827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1766827c4036SVaclav Hapla } 17675de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm)); 1768*d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE)); 17694e3744c5SMatthew G. Knepley *dmUnint = udm; 17704e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 17714e3744c5SMatthew G. Knepley } 1772a7748839SVaclav Hapla 17739371c9d4SSatish Balay static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) { 1774a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1775a7748839SVaclav Hapla MPI_Comm comm; 1776a7748839SVaclav Hapla 1777a7748839SVaclav Hapla PetscFunctionBegin; 17789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 17799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 17809566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1781a7748839SVaclav Hapla 1782a7748839SVaclav Hapla if (depth == dim) { 1783a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1784a7748839SVaclav Hapla if (!dim) goto finish; 1785a7748839SVaclav Hapla 1786a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 17879566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd)); 1788a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) { 17899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1790a7748839SVaclav Hapla if (coneSize) { 1791a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1792a7748839SVaclav Hapla goto finish; 1793a7748839SVaclav Hapla } 1794a7748839SVaclav Hapla } 1795a7748839SVaclav Hapla 1796a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1797a7748839SVaclav Hapla for (h = 0; h < dim; h++) { 17989566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 1799a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) { 18009566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1801a7748839SVaclav Hapla if (!coneSize) { 1802a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1803a7748839SVaclav Hapla goto finish; 1804a7748839SVaclav Hapla } 1805a7748839SVaclav Hapla } 1806a7748839SVaclav Hapla } 1807a7748839SVaclav Hapla } else if (depth == 1) { 1808a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1809a7748839SVaclav Hapla } else { 1810a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1811a7748839SVaclav Hapla } 1812a7748839SVaclav Hapla finish: 1813a7748839SVaclav Hapla PetscFunctionReturn(0); 1814a7748839SVaclav Hapla } 1815a7748839SVaclav Hapla 1816a7748839SVaclav Hapla /*@ 18179ade3219SVaclav Hapla DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated. 1818a7748839SVaclav Hapla 1819a7748839SVaclav Hapla Not Collective 1820a7748839SVaclav Hapla 1821a7748839SVaclav Hapla Input Parameter: 1822a7748839SVaclav Hapla . dm - The DM object 1823a7748839SVaclav Hapla 1824a7748839SVaclav Hapla Output Parameter: 1825a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1826a7748839SVaclav Hapla 1827a7748839SVaclav Hapla Level: intermediate 1828a7748839SVaclav Hapla 1829a7748839SVaclav Hapla Notes: 18309ade3219SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this is NOT collective 18319ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1832a7748839SVaclav Hapla However, DMPlexInterpolate() guarantees the result is the same on all. 18339ade3219SVaclav Hapla 1834a7748839SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED. 1835a7748839SVaclav Hapla 18369ade3219SVaclav Hapla Developer Notes: 18379ade3219SVaclav Hapla Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID. 18389ade3219SVaclav Hapla 18399ade3219SVaclav Hapla If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called. 18409ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 18419ade3219SVaclav Hapla DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL. 18429ade3219SVaclav Hapla 18439ade3219SVaclav Hapla If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated. 18449ade3219SVaclav Hapla 18459ade3219SVaclav Hapla DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL, 18469ade3219SVaclav Hapla and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 18479ade3219SVaclav Hapla 1848db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()` 1849a7748839SVaclav Hapla @*/ 18509371c9d4SSatish Balay PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) { 1851a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data; 1852a7748839SVaclav Hapla 1853a7748839SVaclav Hapla PetscFunctionBegin; 1854a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1855a7748839SVaclav Hapla PetscValidPointer(interpolated, 2); 1856a7748839SVaclav Hapla if (plex->interpolated < 0) { 18579566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated)); 185876bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 1859a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1860a7748839SVaclav Hapla 18619566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &flg)); 186208401ef6SPierre Jolivet PetscCheck(flg == plex->interpolated, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]); 1863a7748839SVaclav Hapla } 1864a7748839SVaclav Hapla *interpolated = plex->interpolated; 1865a7748839SVaclav Hapla PetscFunctionReturn(0); 1866a7748839SVaclav Hapla } 1867a7748839SVaclav Hapla 1868a7748839SVaclav Hapla /*@ 18699ade3219SVaclav Hapla DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner). 1870a7748839SVaclav Hapla 18712666ff3cSVaclav Hapla Collective 1872a7748839SVaclav Hapla 1873a7748839SVaclav Hapla Input Parameter: 1874a7748839SVaclav Hapla . dm - The DM object 1875a7748839SVaclav Hapla 1876a7748839SVaclav Hapla Output Parameter: 1877a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1878a7748839SVaclav Hapla 1879a7748839SVaclav Hapla Level: intermediate 1880a7748839SVaclav Hapla 1881a7748839SVaclav Hapla Notes: 18829ade3219SVaclav Hapla Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks. 18839ade3219SVaclav Hapla 18849ade3219SVaclav Hapla This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks. 18859ade3219SVaclav Hapla 18869ade3219SVaclav Hapla Developer Notes: 18879ade3219SVaclav Hapla Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID. 18889ade3219SVaclav Hapla 18899ade3219SVaclav Hapla If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated. 18909ade3219SVaclav Hapla MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 18919ade3219SVaclav Hapla if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED, 18929ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 18939ade3219SVaclav Hapla 18949ade3219SVaclav Hapla If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective. 1895a7748839SVaclav Hapla 1896db781477SPatrick Sanan .seealso: `DMPlexInterpolate()`, `DMPlexIsInterpolated()` 1897a7748839SVaclav Hapla @*/ 18989371c9d4SSatish Balay PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) { 1899a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data; 1900a7748839SVaclav Hapla PetscBool debug = PETSC_FALSE; 1901a7748839SVaclav Hapla 1902a7748839SVaclav Hapla PetscFunctionBegin; 1903a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1904a7748839SVaclav Hapla PetscValidPointer(interpolated, 2); 19059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL)); 1906a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1907a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1908a7748839SVaclav Hapla MPI_Comm comm; 1909a7748839SVaclav Hapla 19109566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 19119566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective)); 19129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm)); 19139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm)); 1914a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1915a7748839SVaclav Hapla if (debug) { 1916a7748839SVaclav Hapla PetscMPIInt rank; 1917a7748839SVaclav Hapla 19189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 19199566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective])); 19209566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 1921a7748839SVaclav Hapla } 1922a7748839SVaclav Hapla } 1923a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 1924a7748839SVaclav Hapla PetscFunctionReturn(0); 1925a7748839SVaclav Hapla } 1926