1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2e8f14785SLisandro Dalcin #include <petsc/private/hashmapi.h> 3e8f14785SLisandro Dalcin #include <petsc/private/hashmapij.h> 4e8f14785SLisandro Dalcin 5ea78f98cSLisandro Dalcin const char *const DMPlexInterpolatedFlags[] = {"none", "partial", "mixed", "full", "DMPlexInterpolatedFlag", "DMPLEX_INTERPOLATED_", NULL}; 6a7748839SVaclav Hapla 7a03d55ffSStefano Zampini /* HMapIJKL */ 8e8f14785SLisandro Dalcin 9a03d55ffSStefano Zampini #include <petsc/private/hashmapijkl.h> 10e8f14785SLisandro Dalcin 113be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1}; 123be36e83SMatthew G. Knepley 13a03d55ffSStefano Zampini typedef struct _PetscHMapIJKLRemoteKey { 149371c9d4SSatish Balay PetscSFNode i, j, k, l; 15a03d55ffSStefano Zampini } PetscHMapIJKLRemoteKey; 163be36e83SMatthew G. Knepley 17a03d55ffSStefano Zampini #define PetscHMapIJKLRemoteKeyHash(key) \ 189371c9d4SSatish Balay PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index), PetscHashInt((key).j.rank + (key).j.index)), PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index), PetscHashInt((key).l.rank + (key).l.index))) 193be36e83SMatthew G. Knepley 20a03d55ffSStefano Zampini #define PetscHMapIJKLRemoteKeyEqual(k1, k2) \ 213be36e83SMatthew G. Knepley (((k1).i.rank == (k2).i.rank) ? ((k1).i.index == (k2).i.index) ? ((k1).j.rank == (k2).j.rank) ? ((k1).j.index == (k2).j.index) ? ((k1).k.rank == (k2).k.rank) ? ((k1).k.index == (k2).k.index) ? ((k1).l.rank == (k2).l.rank) ? ((k1).l.index == (k2).l.index) : 0 : 0 : 0 : 0 : 0 : 0 : 0) 223be36e83SMatthew G. Knepley 23a03d55ffSStefano Zampini PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HMapIJKLRemote, PetscHMapIJKLRemoteKey, PetscSFNode, PetscHMapIJKLRemoteKeyHash, PetscHMapIJKLRemoteKeyEqual, _PetscInvalidSFNode)) 243be36e83SMatthew G. Knepley 25d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[]) 26d71ae5a4SJacob Faibussowitsch { 273be36e83SMatthew G. Knepley PetscInt i; 283be36e83SMatthew G. Knepley 293be36e83SMatthew G. Knepley PetscFunctionBegin; 303be36e83SMatthew G. Knepley for (i = 1; i < n; ++i) { 313be36e83SMatthew G. Knepley PetscSFNode x = A[i]; 323be36e83SMatthew G. Knepley PetscInt j; 333be36e83SMatthew G. Knepley 343be36e83SMatthew G. Knepley for (j = i - 1; j >= 0; --j) { 353be36e83SMatthew G. Knepley if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break; 363be36e83SMatthew G. Knepley A[j + 1] = A[j]; 373be36e83SMatthew G. Knepley } 383be36e83SMatthew G. Knepley A[j + 1] = x; 393be36e83SMatthew G. Knepley } 403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 413be36e83SMatthew G. Knepley } 429f074e33SMatthew G Knepley 439f074e33SMatthew G Knepley /* 44439ece16SMatthew G. Knepley DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone 45439ece16SMatthew G. Knepley */ 46d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) 47d71ae5a4SJacob Faibussowitsch { 48442f3b32SStefano Zampini DMPolytopeType *typesTmp = NULL; 49442f3b32SStefano Zampini PetscInt *sizesTmp = NULL, *facesTmp = NULL; 50442f3b32SStefano Zampini PetscInt *tmp; 51442f3b32SStefano Zampini PetscInt maxConeSize, maxSupportSize, maxSize; 52442f3b32SStefano Zampini PetscInt getSize = 0; 53439ece16SMatthew G. Knepley 54439ece16SMatthew G. Knepley PetscFunctionBegin; 55439ece16SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 564f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 579566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 58442f3b32SStefano Zampini maxSize = PetscMax(maxConeSize, maxSupportSize); 59442f3b32SStefano Zampini if (faceTypes) getSize += maxSize; 60442f3b32SStefano Zampini if (faceSizes) getSize += maxSize; 61442f3b32SStefano Zampini if (faces) getSize += PetscSqr(maxSize); 62442f3b32SStefano Zampini PetscCall(DMGetWorkArray(dm, getSize, MPIU_INT, &tmp)); 63442f3b32SStefano Zampini if (faceTypes) { 64442f3b32SStefano Zampini typesTmp = (DMPolytopeType *)tmp; 65442f3b32SStefano Zampini tmp += maxSize; 66442f3b32SStefano Zampini } 67442f3b32SStefano Zampini if (faceSizes) { 68442f3b32SStefano Zampini sizesTmp = tmp; 69442f3b32SStefano Zampini tmp += maxSize; 70442f3b32SStefano Zampini } 71442f3b32SStefano Zampini if (faces) facesTmp = tmp; 72ba2698f1SMatthew G. Knepley switch (ct) { 73ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 74ba2698f1SMatthew G. Knepley if (numFaces) *numFaces = 0; 756f5c9017SMatthew G. Knepley if (faceTypes) *faceTypes = typesTmp; 766f5c9017SMatthew G. Knepley if (faceSizes) *faceSizes = sizesTmp; 776f5c9017SMatthew G. Knepley if (faces) *faces = facesTmp; 78ba2698f1SMatthew G. Knepley break; 79ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 80412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 2; 81412e9a14SMatthew G. Knepley if (faceTypes) { 829371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_POINT; 839371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_POINT; 84412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 85412e9a14SMatthew G. Knepley } 86412e9a14SMatthew G. Knepley if (faceSizes) { 879371c9d4SSatish Balay sizesTmp[0] = 1; 889371c9d4SSatish Balay sizesTmp[1] = 1; 89412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 90412e9a14SMatthew G. Knepley } 91c49d9212SMatthew G. Knepley if (faces) { 929371c9d4SSatish Balay facesTmp[0] = cone[0]; 939371c9d4SSatish Balay facesTmp[1] = cone[1]; 94c49d9212SMatthew G. Knepley *faces = facesTmp; 95c49d9212SMatthew G. Knepley } 96412e9a14SMatthew G. Knepley break; 97412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 98c49d9212SMatthew G. Knepley if (numFaces) *numFaces = 2; 99412e9a14SMatthew G. Knepley if (faceTypes) { 1009371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_POINT; 1019371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_POINT; 102412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 103412e9a14SMatthew G. Knepley } 104412e9a14SMatthew G. Knepley if (faceSizes) { 1059371c9d4SSatish Balay sizesTmp[0] = 1; 1069371c9d4SSatish Balay sizesTmp[1] = 1; 107412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 108412e9a14SMatthew G. Knepley } 109412e9a14SMatthew G. Knepley if (faces) { 1109371c9d4SSatish Balay facesTmp[0] = cone[0]; 1119371c9d4SSatish Balay facesTmp[1] = cone[1]; 112412e9a14SMatthew G. Knepley *faces = facesTmp; 113412e9a14SMatthew G. Knepley } 114c49d9212SMatthew G. Knepley break; 115ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 116412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 3; 117412e9a14SMatthew G. Knepley if (faceTypes) { 1189371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1199371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1209371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEGMENT; 121412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 122412e9a14SMatthew G. Knepley } 123412e9a14SMatthew G. Knepley if (faceSizes) { 1249371c9d4SSatish Balay sizesTmp[0] = 2; 1259371c9d4SSatish Balay sizesTmp[1] = 2; 1269371c9d4SSatish Balay sizesTmp[2] = 2; 127412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 128412e9a14SMatthew G. Knepley } 1299a5b13a2SMatthew G Knepley if (faces) { 1309371c9d4SSatish Balay facesTmp[0] = cone[0]; 1319371c9d4SSatish Balay facesTmp[1] = cone[1]; 1329371c9d4SSatish Balay facesTmp[2] = cone[1]; 1339371c9d4SSatish Balay facesTmp[3] = cone[2]; 1349371c9d4SSatish Balay facesTmp[4] = cone[2]; 1359371c9d4SSatish Balay facesTmp[5] = cone[0]; 1369a5b13a2SMatthew G Knepley *faces = facesTmp; 1379a5b13a2SMatthew G Knepley } 1389f074e33SMatthew G Knepley break; 139ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 1409a5b13a2SMatthew G Knepley /* Vertices follow right hand rule */ 141412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 142412e9a14SMatthew G. Knepley if (faceTypes) { 1439371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1449371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1459371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEGMENT; 1469371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEGMENT; 147412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 148412e9a14SMatthew G. Knepley } 149412e9a14SMatthew G. Knepley if (faceSizes) { 1509371c9d4SSatish Balay sizesTmp[0] = 2; 1519371c9d4SSatish Balay sizesTmp[1] = 2; 1529371c9d4SSatish Balay sizesTmp[2] = 2; 1539371c9d4SSatish Balay sizesTmp[3] = 2; 154412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 155412e9a14SMatthew G. Knepley } 1569a5b13a2SMatthew G Knepley if (faces) { 1579371c9d4SSatish Balay facesTmp[0] = cone[0]; 1589371c9d4SSatish Balay facesTmp[1] = cone[1]; 1599371c9d4SSatish Balay facesTmp[2] = cone[1]; 1609371c9d4SSatish Balay facesTmp[3] = cone[2]; 1619371c9d4SSatish Balay facesTmp[4] = cone[2]; 1629371c9d4SSatish Balay facesTmp[5] = cone[3]; 1639371c9d4SSatish Balay facesTmp[6] = cone[3]; 1649371c9d4SSatish Balay facesTmp[7] = cone[0]; 1659a5b13a2SMatthew G Knepley *faces = facesTmp; 1669a5b13a2SMatthew G Knepley } 167412e9a14SMatthew G. Knepley break; 168412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 1699a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 170412e9a14SMatthew G. Knepley if (faceTypes) { 1719371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1729371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1739371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1749371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR; 175412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 176412e9a14SMatthew G. Knepley } 177412e9a14SMatthew G. Knepley if (faceSizes) { 1789371c9d4SSatish Balay sizesTmp[0] = 2; 1799371c9d4SSatish Balay sizesTmp[1] = 2; 1809371c9d4SSatish Balay sizesTmp[2] = 2; 1819371c9d4SSatish Balay sizesTmp[3] = 2; 182412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 183412e9a14SMatthew G. Knepley } 184412e9a14SMatthew G. Knepley if (faces) { 1859371c9d4SSatish Balay facesTmp[0] = cone[0]; 1869371c9d4SSatish Balay facesTmp[1] = cone[1]; 1879371c9d4SSatish Balay facesTmp[2] = cone[2]; 1889371c9d4SSatish Balay facesTmp[3] = cone[3]; 1899371c9d4SSatish Balay facesTmp[4] = cone[0]; 1909371c9d4SSatish Balay facesTmp[5] = cone[2]; 1919371c9d4SSatish Balay facesTmp[6] = cone[1]; 1929371c9d4SSatish Balay facesTmp[7] = cone[3]; 193412e9a14SMatthew G. Knepley *faces = facesTmp; 194412e9a14SMatthew G. Knepley } 1959f074e33SMatthew G Knepley break; 196ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 1972e1b13c2SMatthew G. Knepley /* Vertices of first face follow right hand rule and normal points away from last vertex */ 198412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 199412e9a14SMatthew G. Knepley if (faceTypes) { 2009371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 2019371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 2029371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_TRIANGLE; 2039371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_TRIANGLE; 204412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 205412e9a14SMatthew G. Knepley } 206412e9a14SMatthew G. Knepley if (faceSizes) { 2079371c9d4SSatish Balay sizesTmp[0] = 3; 2089371c9d4SSatish Balay sizesTmp[1] = 3; 2099371c9d4SSatish Balay sizesTmp[2] = 3; 2109371c9d4SSatish Balay sizesTmp[3] = 3; 211412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 212412e9a14SMatthew G. Knepley } 2139a5b13a2SMatthew G Knepley if (faces) { 2149371c9d4SSatish Balay facesTmp[0] = cone[0]; 2159371c9d4SSatish Balay facesTmp[1] = cone[1]; 2169371c9d4SSatish Balay facesTmp[2] = cone[2]; 2179371c9d4SSatish Balay facesTmp[3] = cone[0]; 2189371c9d4SSatish Balay facesTmp[4] = cone[3]; 2199371c9d4SSatish Balay facesTmp[5] = cone[1]; 2209371c9d4SSatish Balay facesTmp[6] = cone[0]; 2219371c9d4SSatish Balay facesTmp[7] = cone[2]; 2229371c9d4SSatish Balay facesTmp[8] = cone[3]; 2239371c9d4SSatish Balay facesTmp[9] = cone[2]; 2249371c9d4SSatish Balay facesTmp[10] = cone[1]; 2259371c9d4SSatish Balay facesTmp[11] = cone[3]; 2269a5b13a2SMatthew G Knepley *faces = facesTmp; 2279a5b13a2SMatthew G Knepley } 2289a5b13a2SMatthew G Knepley break; 229ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 230e368ef20SMatthew G. Knepley /* 7--------6 231e368ef20SMatthew G. Knepley /| /| 232e368ef20SMatthew G. Knepley / | / | 233e368ef20SMatthew G. Knepley 4--------5 | 234e368ef20SMatthew G. Knepley | | | | 235e368ef20SMatthew G. Knepley | | | | 236e368ef20SMatthew G. Knepley | 1--------2 237e368ef20SMatthew G. Knepley | / | / 238e368ef20SMatthew G. Knepley |/ |/ 239e368ef20SMatthew G. Knepley 0--------3 240e368ef20SMatthew G. Knepley */ 241412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 242412e9a14SMatthew G. Knepley if (faceTypes) { 2439371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 2449371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; 2459371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; 2469371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; 2479371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; 2489371c9d4SSatish Balay typesTmp[5] = DM_POLYTOPE_QUADRILATERAL; 249412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 250412e9a14SMatthew G. Knepley } 251412e9a14SMatthew G. Knepley if (faceSizes) { 2529371c9d4SSatish Balay sizesTmp[0] = 4; 2539371c9d4SSatish Balay sizesTmp[1] = 4; 2549371c9d4SSatish Balay sizesTmp[2] = 4; 2559371c9d4SSatish Balay sizesTmp[3] = 4; 2569371c9d4SSatish Balay sizesTmp[4] = 4; 2579371c9d4SSatish Balay sizesTmp[5] = 4; 258412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 259412e9a14SMatthew G. Knepley } 2609a5b13a2SMatthew G Knepley if (faces) { 2619371c9d4SSatish Balay facesTmp[0] = cone[0]; 2629371c9d4SSatish Balay facesTmp[1] = cone[1]; 2639371c9d4SSatish Balay facesTmp[2] = cone[2]; 2649371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 2659371c9d4SSatish Balay facesTmp[4] = cone[4]; 2669371c9d4SSatish Balay facesTmp[5] = cone[5]; 2679371c9d4SSatish Balay facesTmp[6] = cone[6]; 2689371c9d4SSatish Balay facesTmp[7] = cone[7]; /* Top */ 2699371c9d4SSatish Balay facesTmp[8] = cone[0]; 2709371c9d4SSatish Balay facesTmp[9] = cone[3]; 2719371c9d4SSatish Balay facesTmp[10] = cone[5]; 2729371c9d4SSatish Balay facesTmp[11] = cone[4]; /* Front */ 2739371c9d4SSatish Balay facesTmp[12] = cone[2]; 2749371c9d4SSatish Balay facesTmp[13] = cone[1]; 2759371c9d4SSatish Balay facesTmp[14] = cone[7]; 2769371c9d4SSatish Balay facesTmp[15] = cone[6]; /* Back */ 2779371c9d4SSatish Balay facesTmp[16] = cone[3]; 2789371c9d4SSatish Balay facesTmp[17] = cone[2]; 2799371c9d4SSatish Balay facesTmp[18] = cone[6]; 2809371c9d4SSatish Balay facesTmp[19] = cone[5]; /* Right */ 2819371c9d4SSatish Balay facesTmp[20] = cone[0]; 2829371c9d4SSatish Balay facesTmp[21] = cone[4]; 2839371c9d4SSatish Balay facesTmp[22] = cone[7]; 2849371c9d4SSatish Balay facesTmp[23] = cone[1]; /* Left */ 2859a5b13a2SMatthew G Knepley *faces = facesTmp; 2869a5b13a2SMatthew G Knepley } 28799836e0eSStefano Zampini break; 288ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 289412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 290412e9a14SMatthew G. Knepley if (faceTypes) { 2919371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 2929371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 2939371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; 2949371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; 2959371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; 296412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 297412e9a14SMatthew G. Knepley } 298412e9a14SMatthew G. Knepley if (faceSizes) { 2999371c9d4SSatish Balay sizesTmp[0] = 3; 3009371c9d4SSatish Balay sizesTmp[1] = 3; 3019371c9d4SSatish Balay sizesTmp[2] = 4; 3029371c9d4SSatish Balay sizesTmp[3] = 4; 3039371c9d4SSatish Balay sizesTmp[4] = 4; 304412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 305412e9a14SMatthew G. Knepley } 306ba2698f1SMatthew G. Knepley if (faces) { 3079371c9d4SSatish Balay facesTmp[0] = cone[0]; 3089371c9d4SSatish Balay facesTmp[1] = cone[1]; 3099371c9d4SSatish Balay facesTmp[2] = cone[2]; /* Bottom */ 3109371c9d4SSatish Balay facesTmp[3] = cone[3]; 3119371c9d4SSatish Balay facesTmp[4] = cone[4]; 3129371c9d4SSatish Balay facesTmp[5] = cone[5]; /* Top */ 3139371c9d4SSatish Balay facesTmp[6] = cone[0]; 3149371c9d4SSatish Balay facesTmp[7] = cone[2]; 3159371c9d4SSatish Balay facesTmp[8] = cone[4]; 3169371c9d4SSatish Balay facesTmp[9] = cone[3]; /* Back left */ 3179371c9d4SSatish Balay facesTmp[10] = cone[2]; 3189371c9d4SSatish Balay facesTmp[11] = cone[1]; 3199371c9d4SSatish Balay facesTmp[12] = cone[5]; 3209371c9d4SSatish Balay facesTmp[13] = cone[4]; /* Front */ 3219371c9d4SSatish Balay facesTmp[14] = cone[1]; 3229371c9d4SSatish Balay facesTmp[15] = cone[0]; 3239371c9d4SSatish Balay facesTmp[16] = cone[3]; 3249371c9d4SSatish Balay facesTmp[17] = cone[5]; /* Back right */ 325ba2698f1SMatthew G. Knepley *faces = facesTmp; 32699836e0eSStefano Zampini } 32799836e0eSStefano Zampini break; 328ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 329412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 330412e9a14SMatthew G. Knepley if (faceTypes) { 3319371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 3329371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 3339371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3349371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3359371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; 336412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 337412e9a14SMatthew G. Knepley } 338412e9a14SMatthew G. Knepley if (faceSizes) { 3399371c9d4SSatish Balay sizesTmp[0] = 3; 3409371c9d4SSatish Balay sizesTmp[1] = 3; 3419371c9d4SSatish Balay sizesTmp[2] = 4; 3429371c9d4SSatish Balay sizesTmp[3] = 4; 3439371c9d4SSatish Balay sizesTmp[4] = 4; 344412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 345412e9a14SMatthew G. Knepley } 34699836e0eSStefano Zampini if (faces) { 3479371c9d4SSatish Balay facesTmp[0] = cone[0]; 3489371c9d4SSatish Balay facesTmp[1] = cone[1]; 3499371c9d4SSatish Balay facesTmp[2] = cone[2]; /* Bottom */ 3509371c9d4SSatish Balay facesTmp[3] = cone[3]; 3519371c9d4SSatish Balay facesTmp[4] = cone[4]; 3529371c9d4SSatish Balay facesTmp[5] = cone[5]; /* Top */ 3539371c9d4SSatish Balay facesTmp[6] = cone[0]; 3549371c9d4SSatish Balay facesTmp[7] = cone[1]; 3559371c9d4SSatish Balay facesTmp[8] = cone[3]; 3569371c9d4SSatish Balay facesTmp[9] = cone[4]; /* Back left */ 3579371c9d4SSatish Balay facesTmp[10] = cone[1]; 3589371c9d4SSatish Balay facesTmp[11] = cone[2]; 3599371c9d4SSatish Balay facesTmp[12] = cone[4]; 3609371c9d4SSatish Balay facesTmp[13] = cone[5]; /* Back right */ 3619371c9d4SSatish Balay facesTmp[14] = cone[2]; 3629371c9d4SSatish Balay facesTmp[15] = cone[0]; 3639371c9d4SSatish Balay facesTmp[16] = cone[5]; 3649371c9d4SSatish Balay facesTmp[17] = cone[3]; /* Front */ 36599836e0eSStefano Zampini *faces = facesTmp; 36699836e0eSStefano Zampini } 367412e9a14SMatthew G. Knepley break; 368412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 369412e9a14SMatthew G. Knepley /* 7--------6 370412e9a14SMatthew G. Knepley /| /| 371412e9a14SMatthew G. Knepley / | / | 372412e9a14SMatthew G. Knepley 4--------5 | 373412e9a14SMatthew G. Knepley | | | | 374412e9a14SMatthew G. Knepley | | | | 375412e9a14SMatthew G. Knepley | 3--------2 376412e9a14SMatthew G. Knepley | / | / 377412e9a14SMatthew G. Knepley |/ |/ 378412e9a14SMatthew G. Knepley 0--------1 379412e9a14SMatthew G. Knepley */ 380412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 381412e9a14SMatthew G. Knepley if (faceTypes) { 3829371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 3839371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; 3849371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3859371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3869371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3879371c9d4SSatish Balay typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR; 388412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 389412e9a14SMatthew G. Knepley } 390412e9a14SMatthew G. Knepley if (faceSizes) { 3919371c9d4SSatish Balay sizesTmp[0] = 4; 3929371c9d4SSatish Balay sizesTmp[1] = 4; 3939371c9d4SSatish Balay sizesTmp[2] = 4; 3949371c9d4SSatish Balay sizesTmp[3] = 4; 3959371c9d4SSatish Balay sizesTmp[4] = 4; 3969371c9d4SSatish Balay sizesTmp[5] = 4; 397412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 398412e9a14SMatthew G. Knepley } 399412e9a14SMatthew G. Knepley if (faces) { 4009371c9d4SSatish Balay facesTmp[0] = cone[0]; 4019371c9d4SSatish Balay facesTmp[1] = cone[1]; 4029371c9d4SSatish Balay facesTmp[2] = cone[2]; 4039371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 4049371c9d4SSatish Balay facesTmp[4] = cone[4]; 4059371c9d4SSatish Balay facesTmp[5] = cone[5]; 4069371c9d4SSatish Balay facesTmp[6] = cone[6]; 4079371c9d4SSatish Balay facesTmp[7] = cone[7]; /* Top */ 4089371c9d4SSatish Balay facesTmp[8] = cone[0]; 4099371c9d4SSatish Balay facesTmp[9] = cone[1]; 4109371c9d4SSatish Balay facesTmp[10] = cone[4]; 4119371c9d4SSatish Balay facesTmp[11] = cone[5]; /* Front */ 4129371c9d4SSatish Balay facesTmp[12] = cone[1]; 4139371c9d4SSatish Balay facesTmp[13] = cone[2]; 4149371c9d4SSatish Balay facesTmp[14] = cone[5]; 4159371c9d4SSatish Balay facesTmp[15] = cone[6]; /* Right */ 4169371c9d4SSatish Balay facesTmp[16] = cone[2]; 4179371c9d4SSatish Balay facesTmp[17] = cone[3]; 4189371c9d4SSatish Balay facesTmp[18] = cone[6]; 4199371c9d4SSatish Balay facesTmp[19] = cone[7]; /* Back */ 4209371c9d4SSatish Balay facesTmp[20] = cone[3]; 4219371c9d4SSatish Balay facesTmp[21] = cone[0]; 4229371c9d4SSatish Balay facesTmp[22] = cone[7]; 4239371c9d4SSatish Balay facesTmp[23] = cone[4]; /* Left */ 424412e9a14SMatthew G. Knepley *faces = facesTmp; 425412e9a14SMatthew G. Knepley } 42699836e0eSStefano Zampini break; 427da9060c4SMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 428da9060c4SMatthew G. Knepley /* 429da9060c4SMatthew G. Knepley 4---- 430da9060c4SMatthew G. Knepley |\-\ \----- 431da9060c4SMatthew G. Knepley | \ -\ \ 432da9060c4SMatthew G. Knepley | 1--\-----2 433da9060c4SMatthew G. Knepley | / \ / 434da9060c4SMatthew G. Knepley |/ \ / 435da9060c4SMatthew G. Knepley 0--------3 436da9060c4SMatthew G. Knepley */ 437da9060c4SMatthew G. Knepley if (numFaces) *numFaces = 5; 438da9060c4SMatthew G. Knepley if (faceTypes) { 439da9060c4SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 4409371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 4419371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_TRIANGLE; 4429371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_TRIANGLE; 4439371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_TRIANGLE; 444da9060c4SMatthew G. Knepley *faceTypes = typesTmp; 445da9060c4SMatthew G. Knepley } 446da9060c4SMatthew G. Knepley if (faceSizes) { 447da9060c4SMatthew G. Knepley sizesTmp[0] = 4; 4489371c9d4SSatish Balay sizesTmp[1] = 3; 4499371c9d4SSatish Balay sizesTmp[2] = 3; 4509371c9d4SSatish Balay sizesTmp[3] = 3; 4519371c9d4SSatish Balay sizesTmp[4] = 3; 452da9060c4SMatthew G. Knepley *faceSizes = sizesTmp; 453da9060c4SMatthew G. Knepley } 454da9060c4SMatthew G. Knepley if (faces) { 4559371c9d4SSatish Balay facesTmp[0] = cone[0]; 4569371c9d4SSatish Balay facesTmp[1] = cone[1]; 4579371c9d4SSatish Balay facesTmp[2] = cone[2]; 4589371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 4599371c9d4SSatish Balay facesTmp[4] = cone[0]; 4609371c9d4SSatish Balay facesTmp[5] = cone[3]; 4619371c9d4SSatish Balay facesTmp[6] = cone[4]; /* Front */ 4629371c9d4SSatish Balay facesTmp[7] = cone[3]; 4639371c9d4SSatish Balay facesTmp[8] = cone[2]; 4649371c9d4SSatish Balay facesTmp[9] = cone[4]; /* Right */ 4659371c9d4SSatish Balay facesTmp[10] = cone[2]; 4669371c9d4SSatish Balay facesTmp[11] = cone[1]; 4679371c9d4SSatish Balay facesTmp[12] = cone[4]; /* Back */ 4689371c9d4SSatish Balay facesTmp[13] = cone[1]; 4699371c9d4SSatish Balay facesTmp[14] = cone[0]; 4709371c9d4SSatish Balay facesTmp[15] = cone[4]; /* Left */ 471da9060c4SMatthew G. Knepley *faces = facesTmp; 472da9060c4SMatthew G. Knepley } 473da9060c4SMatthew G. Knepley break; 474d71ae5a4SJacob Faibussowitsch default: 475d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]); 47699836e0eSStefano Zampini } 4773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47899836e0eSStefano Zampini } 47999836e0eSStefano Zampini 480d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) 481d71ae5a4SJacob Faibussowitsch { 48299836e0eSStefano Zampini PetscFunctionBegin; 4839566063dSJacob Faibussowitsch if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes)); 484442f3b32SStefano Zampini else if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes)); 485442f3b32SStefano Zampini else if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces)); 486442f3b32SStefano Zampini if (faceTypes) *faceTypes = NULL; 487442f3b32SStefano Zampini if (faceSizes) *faceSizes = NULL; 488442f3b32SStefano Zampini if (faces) *faces = NULL; 4893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49099836e0eSStefano Zampini } 49199836e0eSStefano Zampini 4929a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */ 493d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm) 494d71ae5a4SJacob Faibussowitsch { 495412e9a14SMatthew G. Knepley DMLabel ctLabel; 496a03d55ffSStefano Zampini PetscHMapIJKL faceTable; 497412e9a14SMatthew G. Knepley PetscInt faceTypeNum[DM_NUM_POLYTOPES]; 498*1afe9b7dSMatthew G. Knepley PetscInt depth, pStart, Np, cStart, cEnd, fStart, fEnd, vStart, vEnd; 499a03d55ffSStefano Zampini PetscInt cntFaces, *facesId, minCone; 5009f074e33SMatthew G Knepley 5019f074e33SMatthew G Knepley PetscFunctionBegin; 5029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 503a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLCreate(&faceTable)); 5049566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES)); 505*1afe9b7dSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 5069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd)); 507*1afe9b7dSMatthew G. Knepley // If the range incorporates the vertices, it means we have a non-manifold topology, so choose just cells 508*1afe9b7dSMatthew G. Knepley if (cStart <= vStart && cEnd >= vEnd) cEnd = vStart; 5095c2c0cecSMatthew G. Knepley // Number new faces and save face vertices in hash table 510*1afe9b7dSMatthew G. Knepley // If depth > cellDepth, meaning we are interpolating faces, put the new (d-1)-faces after them 511*1afe9b7dSMatthew G. Knepley // otherwise, we are interpolating cells, so put the faces after the vertices 5129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart)); 513412e9a14SMatthew G. Knepley fEnd = fStart; 514591a860aSStefano Zampini 515a03d55ffSStefano Zampini minCone = PETSC_MAX_INT; 5165c2c0cecSMatthew G. Knepley cntFaces = 0; 5175c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 518591a860aSStefano Zampini const PetscInt *cone; 519591a860aSStefano Zampini DMPolytopeType ct; 520ed896b67SJose E. Roman PetscInt numFaces = 0, coneSize; 521591a860aSStefano Zampini 522591a860aSStefano Zampini PetscCall(DMPlexGetCellType(dm, c, &ct)); 523591a860aSStefano Zampini PetscCall(DMPlexGetCone(dm, c, &cone)); 524a03d55ffSStefano Zampini PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 525a03d55ffSStefano Zampini for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone); 5266f5c9017SMatthew G. Knepley // Ignore faces since they are interpolated 5276f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL)); 528591a860aSStefano Zampini cntFaces += numFaces; 529591a860aSStefano Zampini } 530a03d55ffSStefano Zampini // Encode so that we can use 0 as an excluded value, instead of PETSC_MAX_INT 531a03d55ffSStefano Zampini minCone = -(minCone - 1); 532591a860aSStefano Zampini 533591a860aSStefano Zampini PetscCall(PetscMalloc1(cntFaces, &facesId)); 534591a860aSStefano Zampini 5355c2c0cecSMatthew G. Knepley cntFaces = 0; 5365c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 537412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 538412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 539ba2698f1SMatthew G. Knepley DMPolytopeType ct; 5405c2c0cecSMatthew G. Knepley PetscInt numFaces, foff = 0; 54199836e0eSStefano Zampini 5429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5446f5c9017SMatthew G. Knepley // Ignore faces since they are interpolated 5456f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 5469566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 5476f5c9017SMatthew G. Knepley } else { 5486f5c9017SMatthew G. Knepley numFaces = 0; 5496f5c9017SMatthew G. Knepley } 5505c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 551412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 552412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 553412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 5549a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 555e8f14785SLisandro Dalcin PetscHashIter iter; 556e8f14785SLisandro Dalcin PetscBool missing; 5579f074e33SMatthew G Knepley 5585f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 559a03d55ffSStefano Zampini key.i = face[0] + minCone; 560a03d55ffSStefano Zampini key.j = faceSize > 1 ? face[1] + minCone : 0; 561a03d55ffSStefano Zampini key.k = faceSize > 2 ? face[2] + minCone : 0; 562a03d55ffSStefano Zampini key.l = faceSize > 3 ? face[3] + minCone : 0; 5639566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 564a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing)); 565e9fa77a1SMatthew G. Knepley if (missing) { 566591a860aSStefano Zampini facesId[cntFaces] = fEnd; 567a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++)); 568412e9a14SMatthew G. Knepley ++faceTypeNum[faceType]; 569a03d55ffSStefano Zampini } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces])); 570591a860aSStefano Zampini cntFaces++; 5719a5b13a2SMatthew G Knepley } 5726f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 57399836e0eSStefano Zampini } 574412e9a14SMatthew G. Knepley /* We need to number faces contiguously among types */ 575412e9a14SMatthew G. Knepley { 576412e9a14SMatthew G. Knepley PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0; 57799836e0eSStefano Zampini 5789371c9d4SSatish Balay for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) { 5799371c9d4SSatish Balay if (faceTypeNum[ct]) ++numFT; 5809371c9d4SSatish Balay faceTypeStart[ct] = 0; 5819371c9d4SSatish Balay } 582412e9a14SMatthew G. Knepley if (numFT > 1) { 583a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLClear(faceTable)); 584412e9a14SMatthew G. Knepley faceTypeStart[0] = fStart; 585412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1]; 5865c2c0cecSMatthew G. Knepley cntFaces = 0; 5875c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 588412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 589412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 590ba2698f1SMatthew G. Knepley DMPolytopeType ct; 5915c2c0cecSMatthew G. Knepley PetscInt numFaces, foff = 0; 59299836e0eSStefano Zampini 5939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5956f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 5969566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 5976f5c9017SMatthew G. Knepley } else { 5986f5c9017SMatthew G. Knepley numFaces = 0; 5996f5c9017SMatthew G. Knepley } 6005c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 601412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 602412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 603412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 60499836e0eSStefano Zampini PetscHashIJKLKey key; 60599836e0eSStefano Zampini PetscHashIter iter; 60699836e0eSStefano Zampini PetscBool missing; 60799836e0eSStefano Zampini 608a03d55ffSStefano Zampini key.i = face[0] + minCone; 609a03d55ffSStefano Zampini key.j = faceSize > 1 ? face[1] + minCone : 0; 610a03d55ffSStefano Zampini key.k = faceSize > 2 ? face[2] + minCone : 0; 611a03d55ffSStefano Zampini key.l = faceSize > 3 ? face[3] + minCone : 0; 6129566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 613a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing)); 614591a860aSStefano Zampini if (missing) { 615591a860aSStefano Zampini facesId[cntFaces] = faceTypeStart[faceType]; 616a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++)); 617a03d55ffSStefano Zampini } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces])); 618591a860aSStefano Zampini cntFaces++; 61999836e0eSStefano Zampini } 6206f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 62199836e0eSStefano Zampini } 622412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) { 6231dca8a05SBarry Smith PetscCheck(faceTypeStart[ct] == faceTypeStart[ct - 1] + faceTypeNum[ct], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent numbering for cell type %s, %" PetscInt_FMT " != %" PetscInt_FMT " + %" PetscInt_FMT, DMPolytopeTypes[ct], faceTypeStart[ct], faceTypeStart[ct - 1], faceTypeNum[ct]); 6249a5b13a2SMatthew G Knepley } 6259a5b13a2SMatthew G Knepley } 626412e9a14SMatthew G. Knepley } 627a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLDestroy(&faceTable)); 628591a860aSStefano Zampini 6295c2c0cecSMatthew G. Knepley // Add new points, perhaps inserting into the numbering 6309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &Np)); 6319566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart))); 6325c2c0cecSMatthew G. Knepley // Set cone sizes 6335c2c0cecSMatthew G. Knepley // Must create the celltype label here so that we do not automatically try to compute the types 6349566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(idm, "celltype")); 6359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel)); 6365c2c0cecSMatthew G. Knepley for (PetscInt d = 0; d <= depth; ++d) { 637412e9a14SMatthew G. Knepley DMPolytopeType ct; 6385c2c0cecSMatthew G. Knepley PetscInt coneSize, pStart, pEnd, poff = 0; 6399f074e33SMatthew G Knepley 6409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 641*1afe9b7dSMatthew G. Knepley // Check for non-manifold condition 642*1afe9b7dSMatthew G. Knepley if (d == cellDepth) { 643*1afe9b7dSMatthew G. Knepley if (pEnd == cEnd) continue; 644*1afe9b7dSMatthew G. Knepley else pStart = vEnd; 645*1afe9b7dSMatthew G. Knepley } 6465c2c0cecSMatthew G. Knepley // Account for insertion 6475c2c0cecSMatthew G. Knepley if (pStart >= fStart) poff = fEnd - fStart; 6485c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 6499566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 6505c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, p + poff, coneSize)); 6519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 6525c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, p + poff, ct)); 6539f074e33SMatthew G Knepley } 6549f074e33SMatthew G Knepley } 6555c2c0cecSMatthew G. Knepley cntFaces = 0; 6565c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 657591a860aSStefano Zampini const PetscInt *cone, *faceSizes; 658412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 659412e9a14SMatthew G. Knepley DMPolytopeType ct; 6605c2c0cecSMatthew G. Knepley PetscInt numFaces, poff = 0; 661412e9a14SMatthew G. Knepley 6629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 6639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 6645c2c0cecSMatthew G. Knepley if (c >= fStart) poff = fEnd - fStart; 6656f5c9017SMatthew G. Knepley if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 6665c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, c + poff, ct)); 6675c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, c + poff, 2)); 6686f5c9017SMatthew G. Knepley continue; 6696f5c9017SMatthew G. Knepley } 670591a860aSStefano Zampini PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL)); 6715c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, c + poff, ct)); 6725c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, c + poff, numFaces)); 6735c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; ++cf) { 674591a860aSStefano Zampini const PetscInt f = facesId[cntFaces]; 675591a860aSStefano Zampini DMPolytopeType faceType = faceTypes[cf]; 676412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 6779566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, f, faceSize)); 6789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, f, faceType)); 679591a860aSStefano Zampini cntFaces++; 680412e9a14SMatthew G. Knepley } 681591a860aSStefano Zampini PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL)); 6829f074e33SMatthew G Knepley } 6839566063dSJacob Faibussowitsch PetscCall(DMSetUp(idm)); 6845c2c0cecSMatthew G. Knepley // Initialize cones so we do not need the bash table to tell us that a cone has been set 685412e9a14SMatthew G. Knepley { 686412e9a14SMatthew G. Knepley PetscSection cs; 687412e9a14SMatthew G. Knepley PetscInt *cones, csize; 6889a5b13a2SMatthew G Knepley 6899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(idm, &cs)); 6909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(idm, &cones)); 6919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cs, &csize)); 6925c2c0cecSMatthew G. Knepley for (PetscInt c = 0; c < csize; ++c) cones[c] = -1; 693412e9a14SMatthew G. Knepley } 6945c2c0cecSMatthew G. Knepley // Set cones 6955c2c0cecSMatthew G. Knepley { 6965c2c0cecSMatthew G. Knepley PetscInt *icone; 6975c2c0cecSMatthew G. Knepley PetscInt maxConeSize; 6985c2c0cecSMatthew G. Knepley 6995c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL)); 7005c2c0cecSMatthew G. Knepley PetscCall(PetscMalloc1(maxConeSize, &icone)); 7015c2c0cecSMatthew G. Knepley for (PetscInt d = 0; d <= depth; ++d) { 702412e9a14SMatthew G. Knepley const PetscInt *cone; 7035c2c0cecSMatthew G. Knepley PetscInt pStart, pEnd, poff = 0, coneSize; 704412e9a14SMatthew G. Knepley 7059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 706*1afe9b7dSMatthew G. Knepley // Check for non-manifold condition 707*1afe9b7dSMatthew G. Knepley if (d == cellDepth) { 708*1afe9b7dSMatthew G. Knepley if (pEnd == cEnd) continue; 709*1afe9b7dSMatthew G. Knepley else pStart = vEnd; 710*1afe9b7dSMatthew G. Knepley } 7115c2c0cecSMatthew G. Knepley // Account for insertion 7125c2c0cecSMatthew G. Knepley if (pStart >= fStart) poff = fEnd - fStart; 7135c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 7149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 7155c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 7165c2c0cecSMatthew G. Knepley for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0); 7175c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCone(idm, p + poff, icone)); 7189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &cone)); 7195c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeOrientation(idm, p + poff, cone)); 7209f074e33SMatthew G Knepley } 7219a5b13a2SMatthew G Knepley } 7225c2c0cecSMatthew G. Knepley cntFaces = 0; 7235c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 724412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 725412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 726ba2698f1SMatthew G. Knepley DMPolytopeType ct; 7275c2c0cecSMatthew G. Knepley PetscInt coneSize, numFaces, foff = 0, poff = 0; 72899836e0eSStefano Zampini 7299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 7309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 7315c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 7325c2c0cecSMatthew G. Knepley if (c >= fStart) poff = fEnd - fStart; 7336f5c9017SMatthew G. Knepley if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 7345c2c0cecSMatthew G. Knepley for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0); 7355c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCone(idm, c + poff, icone)); 7366f5c9017SMatthew G. Knepley PetscCall(DMPlexGetConeOrientation(dm, c, &cone)); 7375c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeOrientation(idm, c + poff, cone)); 7386f5c9017SMatthew G. Knepley continue; 7396f5c9017SMatthew G. Knepley } 7409566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 7415c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 742412e9a14SMatthew G. Knepley DMPolytopeType faceType = faceTypes[cf]; 743412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 744591a860aSStefano Zampini const PetscInt f = facesId[cntFaces]; 745412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 746412e9a14SMatthew G. Knepley const PetscInt *fcone; 7479f074e33SMatthew G Knepley 7489566063dSJacob Faibussowitsch PetscCall(DMPlexInsertCone(idm, c, cf, f)); 7499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(idm, f, &fcone)); 7509566063dSJacob Faibussowitsch if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face)); 751412e9a14SMatthew G. Knepley { 752*1afe9b7dSMatthew G. Knepley const PetscInt *fcone2; 7535c2c0cecSMatthew G. Knepley PetscInt ornt; 754a74221b0SStefano Zampini 7559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(idm, f, &coneSize)); 756*1afe9b7dSMatthew G. Knepley PetscCall(DMPlexGetCone(idm, f, &fcone2)); 75763a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == faceSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %" PetscInt_FMT " for face %" PetscInt_FMT " should be %" PetscInt_FMT, coneSize, f, faceSize); 758d89e6e46SMatthew G. Knepley /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */ 759*1afe9b7dSMatthew G. Knepley PetscCall(DMPolytopeGetVertexOrientation(faceType, fcone2, face, &ornt)); 7605c2c0cecSMatthew G. Knepley PetscCall(DMPlexInsertConeOrientation(idm, c + poff, cf, ornt)); 76199836e0eSStefano Zampini } 762591a860aSStefano Zampini cntFaces++; 76399836e0eSStefano Zampini } 7649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 76599836e0eSStefano Zampini } 7665c2c0cecSMatthew G. Knepley PetscCall(PetscFree(icone)); 7675c2c0cecSMatthew G. Knepley } 768591a860aSStefano Zampini PetscCall(PetscFree(facesId)); 7699566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(idm)); 7709566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(idm)); 7713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7729f074e33SMatthew G Knepley } 7739f074e33SMatthew G Knepley 774d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) 775d71ae5a4SJacob Faibussowitsch { 776f80536cbSVaclav Hapla PetscInt nleaves; 777f80536cbSVaclav Hapla PetscInt nranks; 778a0d42dbcSVaclav Hapla const PetscMPIInt *ranks = NULL; 779a0d42dbcSVaclav Hapla const PetscInt *roffset = NULL, *rmine = NULL, *rremote = NULL; 780f80536cbSVaclav Hapla PetscInt n, o, r; 781f80536cbSVaclav Hapla 782f80536cbSVaclav Hapla PetscFunctionBegin; 7839566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote)); 784f80536cbSVaclav Hapla nleaves = roffset[nranks]; 7859566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1)); 786f80536cbSVaclav Hapla for (r = 0; r < nranks; r++) { 787f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 788f80536cbSVaclav Hapla - to unify order with the other side */ 789f80536cbSVaclav Hapla o = roffset[r]; 790f80536cbSVaclav Hapla n = roffset[r + 1] - o; 7919566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n)); 7929566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n)); 7939566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o])); 794f80536cbSVaclav Hapla } 7953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 796f80536cbSVaclav Hapla } 797f80536cbSVaclav Hapla 798d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm) 799d71ae5a4SJacob Faibussowitsch { 800d89e6e46SMatthew G. Knepley PetscSF sf; 801d89e6e46SMatthew G. Knepley const PetscInt *locals; 802d89e6e46SMatthew G. Knepley const PetscSFNode *remotes; 803d89e6e46SMatthew G. Knepley const PetscMPIInt *ranks; 804d89e6e46SMatthew G. Knepley const PetscInt *roffset; 805d89e6e46SMatthew G. Knepley PetscInt *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 806d89e6e46SMatthew G. Knepley PetscInt nroots, p, nleaves, nranks, r, maxConeSize = 0; 807d89e6e46SMatthew G. Knepley PetscInt(*roots)[4], (*leaves)[4], mainCone[4]; 808d89e6e46SMatthew G. Knepley PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4]; 8092e745bdaSMatthew G. Knepley MPI_Comm comm; 81027d0e99aSVaclav Hapla PetscMPIInt rank, size; 8112e745bdaSMatthew G. Knepley PetscInt debug = 0; 8122e745bdaSMatthew G. Knepley 8132e745bdaSMatthew G. Knepley PetscFunctionBegin; 8149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 8159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 8179566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 8189566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view")); 819d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE)); 8209566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes)); 8213ba16761SJacob Faibussowitsch if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS); 8229566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 8239566063dSJacob Faibussowitsch PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1)); 824d89e6e46SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 825d89e6e46SMatthew G. Knepley PetscInt coneSize; 8269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize)); 827d89e6e46SMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 828d89e6e46SMatthew G. Knepley } 82963a3b9bcSJacob Faibussowitsch PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize); 8309566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks)); 8319e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 832d89e6e46SMatthew G. Knepley const PetscInt *cone; 833d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0; 834d89e6e46SMatthew G. Knepley 8359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 8369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 837d89e6e46SMatthew G. Knepley /* Ignore vertices */ 83827d0e99aSVaclav Hapla if (coneSize < 2) { 839d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 84027d0e99aSVaclav Hapla roots[p][c] = -1; 84127d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 84227d0e99aSVaclav Hapla } 84327d0e99aSVaclav Hapla continue; 84427d0e99aSVaclav Hapla } 8452e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 846d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); c++) { 8479566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0)); 8488a650c75SVaclav Hapla if (ind0 < 0) { 8498a650c75SVaclav Hapla roots[p][c] = cone[c]; 8508a650c75SVaclav Hapla rootsRanks[p][c] = rank; 851c8148b97SVaclav Hapla } else { 8528a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 8538a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 8548a650c75SVaclav Hapla } 8552e745bdaSMatthew G. Knepley } 856d89e6e46SMatthew G. Knepley for (c = coneSize; c < 4; c++) { 857d89e6e46SMatthew G. Knepley roots[p][c] = -1; 858d89e6e46SMatthew G. Knepley rootsRanks[p][c] = -1; 859d89e6e46SMatthew G. Knepley } 8602e745bdaSMatthew G. Knepley } 8619e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 862d89e6e46SMatthew G. Knepley PetscInt c; 863d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 8648ccb905dSVaclav Hapla leaves[p][c] = -2; 8658ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 8668ccb905dSVaclav Hapla } 867c8148b97SVaclav Hapla } 8689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 8699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 8709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 8719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 872d89e6e46SMatthew G. Knepley if (debug) { 8739566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 874c5853193SPierre Jolivet if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n")); 875d89e6e46SMatthew G. Knepley } 8769566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL)); 8779e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 878d89e6e46SMatthew G. Knepley DMPolytopeType ct; 879d89e6e46SMatthew G. Knepley const PetscInt *cone; 880d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0, o; 881d89e6e46SMatthew G. Knepley 882d89e6e46SMatthew G. Knepley if (leaves[p][0] < 0) continue; /* Ignore vertices */ 8839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 8849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 8859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 886d89e6e46SMatthew G. Knepley if (debug) { 8879371c9d4SSatish 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])); 888d89e6e46SMatthew G. Knepley } 8899371c9d4SSatish 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]) { 890d89e6e46SMatthew G. Knepley /* Translate these leaves to my cone points; mainCone means desired order p's cone points */ 891d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); ++c) { 892d89e6e46SMatthew G. Knepley PetscInt rS, rN; 893d89e6e46SMatthew G. Knepley 89427d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 895d89e6e46SMatthew G. Knepley /* A local leaf is just taken as it is */ 8969dddd249SSatish Balay mainCone[c] = leaves[p][c]; 89727d0e99aSVaclav Hapla continue; 89827d0e99aSVaclav Hapla } 899f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 900f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 9019566063dSJacob Faibussowitsch PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r)); 90263a3b9bcSJacob 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]); 9031dca8a05SBarry 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]); 904f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 905d89e6e46SMatthew G. Knepley rS = roffset[r]; 906d89e6e46SMatthew G. Knepley rN = roffset[r + 1] - rS; 9079566063dSJacob Faibussowitsch PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0)); 90863a3b9bcSJacob 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]); 909f80536cbSVaclav Hapla /* Get the corresponding local point */ 9105f80ce2aSJacob Faibussowitsch mainCone[c] = rmine1[rS + ind0]; 911f80536cbSVaclav Hapla } 91263a3b9bcSJacob 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])); 91327d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 9149566063dSJacob Faibussowitsch PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o)); 9159566063dSJacob Faibussowitsch PetscCall(DMPlexOrientPoint(dm, p, o)); 9169566063dSJacob Faibussowitsch } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n")); 91723aaf07bSVaclav Hapla } 91827d0e99aSVaclav Hapla if (debug) { 9199566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 9209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 9212e745bdaSMatthew G. Knepley } 9229566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view")); 9239566063dSJacob Faibussowitsch PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks)); 9249566063dSJacob Faibussowitsch PetscCall(PetscFree2(rmine1, rremote1)); 9253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9262e745bdaSMatthew G. Knepley } 9272e745bdaSMatthew G. Knepley 928d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[]) 929d71ae5a4SJacob Faibussowitsch { 9302e72742cSMatthew G. Knepley PetscInt idx; 9312e72742cSMatthew G. Knepley PetscMPIInt rank; 9322e72742cSMatthew G. Knepley PetscBool flg; 9337bffde78SMichael Lange 9347bffde78SMichael Lange PetscFunctionBegin; 9359566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg)); 9363ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 9379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 9389566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 93963a3b9bcSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx])); 9409566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 9413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9422e72742cSMatthew G. Knepley } 9432e72742cSMatthew G. Knepley 944d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) 945d71ae5a4SJacob Faibussowitsch { 9462e72742cSMatthew G. Knepley PetscInt idx; 9472e72742cSMatthew G. Knepley PetscMPIInt rank; 9482e72742cSMatthew G. Knepley PetscBool flg; 9492e72742cSMatthew G. Knepley 9502e72742cSMatthew G. Knepley PetscFunctionBegin; 9519566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg)); 9523ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 9539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 9549566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 9552e72742cSMatthew G. Knepley if (idxname) { 95663a3b9bcSJacob 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)); 9572e72742cSMatthew G. Knepley } else { 95863a3b9bcSJacob 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)); 9592e72742cSMatthew G. Knepley } 9609566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 9613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9622e72742cSMatthew G. Knepley } 9632e72742cSMatthew G. Knepley 964d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed) 965d71ae5a4SJacob Faibussowitsch { 9663be36e83SMatthew G. Knepley PetscSF sf; 9673be36e83SMatthew G. Knepley const PetscInt *locals; 9683be36e83SMatthew G. Knepley PetscMPIInt rank; 9692e72742cSMatthew G. Knepley 9702e72742cSMatthew G. Knepley PetscFunctionBegin; 9719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9729566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9739566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL)); 9745f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 9752e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 9762e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 9772e72742cSMatthew G. Knepley } else { 9782e72742cSMatthew G. Knepley PetscHashIJKey key; 9793be36e83SMatthew G. Knepley PetscInt l; 9802e72742cSMatthew G. Knepley 9812e72742cSMatthew G. Knepley key.i = remotePoint.index; 9822e72742cSMatthew G. Knepley key.j = remotePoint.rank; 9839566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(remotehash, key, &l)); 9843be36e83SMatthew G. Knepley if (l >= 0) { 9853be36e83SMatthew G. Knepley *localPoint = locals[l]; 9865f80ce2aSJacob Faibussowitsch } else if (mapFailed) *mapFailed = PETSC_TRUE; 9872e72742cSMatthew G. Knepley } 9883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9892e72742cSMatthew G. Knepley } 9902e72742cSMatthew G. Knepley 991d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed) 992d71ae5a4SJacob Faibussowitsch { 9933be36e83SMatthew G. Knepley PetscSF sf; 9943be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 9953be36e83SMatthew G. Knepley const PetscSFNode *remotes; 9963be36e83SMatthew G. Knepley PetscInt Nl, l; 9973be36e83SMatthew G. Knepley PetscMPIInt rank; 9983be36e83SMatthew G. Knepley 9993be36e83SMatthew G. Knepley PetscFunctionBegin; 10005f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 10019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 10029566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10039566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes)); 10043be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 10059566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 10069566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 10073be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 10089566063dSJacob Faibussowitsch PetscCall(PetscFindInt(localPoint, Nl, locals, &l)); 10099371c9d4SSatish Balay if (l < 0) { 10109371c9d4SSatish Balay if (mapFailed) *mapFailed = PETSC_TRUE; 10119371c9d4SSatish Balay } else *remotePoint = remotes[l]; 10123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10133be36e83SMatthew G. Knepley owned: 10143be36e83SMatthew G. Knepley remotePoint->rank = rank; 10153be36e83SMatthew G. Knepley remotePoint->index = localPoint; 10163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10173be36e83SMatthew G. Knepley } 10183be36e83SMatthew G. Knepley 1019d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) 1020d71ae5a4SJacob Faibussowitsch { 10213be36e83SMatthew G. Knepley PetscSF sf; 10223be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 10233be36e83SMatthew G. Knepley PetscInt Nl, idx; 10243be36e83SMatthew G. Knepley 10253be36e83SMatthew G. Knepley PetscFunctionBegin; 10263be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 10279566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10289566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL)); 10293ba16761SJacob Faibussowitsch if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS); 10309566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, Nl, locals, &idx)); 10319371c9d4SSatish Balay if (idx >= 0) { 10329371c9d4SSatish Balay *isShared = PETSC_TRUE; 10333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10349371c9d4SSatish Balay } 10359566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 10369566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 10373be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 10383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10393be36e83SMatthew G. Knepley } 10403be36e83SMatthew G. Knepley 1041d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) 1042d71ae5a4SJacob Faibussowitsch { 10433be36e83SMatthew G. Knepley const PetscInt *cone; 10443be36e83SMatthew G. Knepley PetscInt coneSize, c; 10453be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 10463be36e83SMatthew G. Knepley 10473be36e83SMatthew G. Knepley PetscFunctionBegin; 10489566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 10499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 10503be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10513be36e83SMatthew G. Knepley PetscBool pointShared; 10523be36e83SMatthew G. Knepley 10539566063dSJacob Faibussowitsch PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared)); 10543be36e83SMatthew G. Knepley cShared = (PetscBool)(cShared && pointShared); 10553be36e83SMatthew G. Knepley } 10563be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 10573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10583be36e83SMatthew G. Knepley } 10593be36e83SMatthew G. Knepley 1060d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) 1061d71ae5a4SJacob Faibussowitsch { 10623be36e83SMatthew G. Knepley const PetscInt *cone; 10633be36e83SMatthew G. Knepley PetscInt coneSize, c; 10643be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 10653be36e83SMatthew G. Knepley 10663be36e83SMatthew G. Knepley PetscFunctionBegin; 10679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 10689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 10693be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10703be36e83SMatthew G. Knepley PetscSFNode rcp; 10715f80ce2aSJacob Faibussowitsch PetscBool mapFailed; 10723be36e83SMatthew G. Knepley 10739566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed)); 10745f80ce2aSJacob Faibussowitsch if (mapFailed) { 10753be36e83SMatthew G. Knepley cmin = missing; 10763be36e83SMatthew G. Knepley } else { 10773be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 10783be36e83SMatthew G. Knepley } 10793be36e83SMatthew G. Knepley } 10803be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 10813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10823be36e83SMatthew G. Knepley } 10833be36e83SMatthew G. Knepley 10843be36e83SMatthew G. Knepley /* 10853be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 10863be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 10873be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 10883be36e83SMatthew G. Knepley */ 1089d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) 1090d71ae5a4SJacob Faibussowitsch { 10913be36e83SMatthew G. Knepley MPI_Comm comm; 10923be36e83SMatthew G. Knepley const PetscInt *support; 1093cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height; 10943be36e83SMatthew G. Knepley PetscMPIInt rank; 10953be36e83SMatthew G. Knepley 10963be36e83SMatthew G. Knepley PetscFunctionBegin; 10979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 10989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10999566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap)); 11009566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 11019566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointHeight(dm, p, &height)); 1102cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight + 1) { 1103cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */ 110463a3b9bcSJacob 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)); 11053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1106cf4dc471SVaclav Hapla } 11079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 11089566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 11099566063dSJacob Faibussowitsch if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off)); 11103be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 11113be36e83SMatthew G. Knepley const PetscInt face = support[s]; 11123be36e83SMatthew G. Knepley const PetscInt *cone; 11133be36e83SMatthew G. Knepley PetscSFNode cpmin = {-1, -1}, rp = {-1, -1}; 11143be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 11153be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 11163be36e83SMatthew G. Knepley PetscHashIJKey key; 11173be36e83SMatthew G. Knepley 11183be36e83SMatthew G. Knepley /* Only add point once */ 111963a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Support face %" PetscInt_FMT "\n", rank, face)); 11203be36e83SMatthew G. Knepley key.i = p; 11213be36e83SMatthew G. Knepley key.j = face; 11229566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(faceHash, key, &f)); 11233be36e83SMatthew G. Knepley if (f >= 0) continue; 11249566063dSJacob Faibussowitsch PetscCall(DMPlexConeIsShared(dm, face, &isShared)); 11259566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin)); 11269566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL)); 11273be36e83SMatthew G. Knepley if (debug) { 112863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared)); 112963a3b9bcSJacob 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)); 11303be36e83SMatthew G. Knepley } 11313be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 11329566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p)); 11333be36e83SMatthew G. Knepley if (candidates) { 113463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d] ", rank, face, idx, rank)); 11359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize)); 11369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, face, &cone)); 11373be36e83SMatthew G. Knepley candidates[off + idx].rank = -1; 11383be36e83SMatthew G. Knepley candidates[off + idx++].index = coneSize - 1; 11393be36e83SMatthew G. Knepley candidates[off + idx].rank = rank; 11403be36e83SMatthew G. Knepley candidates[off + idx++].index = face; 11413be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 11423be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 11433be36e83SMatthew G. Knepley 11443be36e83SMatthew G. Knepley if (cp == p) continue; 11459566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL)); 114663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index)); 11473be36e83SMatthew G. Knepley ++idx; 11483be36e83SMatthew G. Knepley } 11499566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n")); 11503be36e83SMatthew G. Knepley } else { 11513be36e83SMatthew G. Knepley /* Add cone size to section */ 115263a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %" PetscInt_FMT "\n", rank, face)); 11539566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize)); 11549566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p)); 11559566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1)); 11563be36e83SMatthew G. Knepley } 11573be36e83SMatthew G. Knepley } 11583be36e83SMatthew G. Knepley } 11593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11603be36e83SMatthew G. Knepley } 11613be36e83SMatthew G. Knepley 11622e72742cSMatthew G. Knepley /*@ 116320f4b53cSBarry Smith DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation 11642e72742cSMatthew G. Knepley 116520f4b53cSBarry Smith Collective 11662e72742cSMatthew G. Knepley 11672e72742cSMatthew G. Knepley Input Parameters: 116820f4b53cSBarry Smith + dm - The interpolated `DMPLEX` 116920f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points 11702e72742cSMatthew G. Knepley 1171f0cfc026SVaclav Hapla Level: developer 11722e72742cSMatthew G. Knepley 117320f4b53cSBarry Smith Note: 117420f4b53cSBarry Smith Debugging for this process can be turned on with the options: `-dm_interp_pre_view` `-petscsf_interp_pre_view` `-petscsection_interp_candidate_view` `-petscsection_interp_candidate_remote_view` `-petscsection_interp_claim_view` `-petscsf_interp_pre_view` `-dmplex_interp_debug` 11752e72742cSMatthew G. Knepley 117620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()` 11772e72742cSMatthew G. Knepley @*/ 1178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 1179d71ae5a4SJacob Faibussowitsch { 11803be36e83SMatthew G. Knepley MPI_Comm comm; 11813be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 11823be36e83SMatthew G. Knepley PetscHMapI claimshash; 11833be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 11843be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 11852e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 11862e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 11873be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 11883be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 11893be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 1190f0cfc026SVaclav Hapla PetscMPIInt rank; 11912e72742cSMatthew G. Knepley 11922e72742cSMatthew G. Knepley PetscFunctionBegin; 1193f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1194064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 11959566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &flg)); 11963ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 11973be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 11989566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 11999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12019566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &ov)); 120228b400f6SJacob Faibussowitsch PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 12039566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug)); 12049566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view")); 12059566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view")); 12069566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0)); 12073be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 12089566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints)); 120908401ef6SPierre Jolivet PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 12109566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&remoteHash)); 12113be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 12123be36e83SMatthew G. Knepley PetscHashIJKey key; 12132e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 12142e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 12159566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(remoteHash, key, l)); 12167bffde78SMichael Lange } 121766aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 12189566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 12199566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 12209566063dSJacob Faibussowitsch PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree)); 12213be36e83SMatthew G. Knepley /* 12223be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 12233be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 12243be36e83SMatthew G. Knepley \begin{itemize} 12253be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 12263be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 12273be36e83SMatthew G. Knepley \end{itemize} 12283be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 12293be36e83SMatthew 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 12303be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 12313be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 12323be36e83SMatthew G. Knepley */ 12333be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 12343be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 1235da81f932SPierre Jolivet The array holds candidate shared faces, each face is referred to by the leaf point */ 12369566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateSection)); 12379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(candidateSection, 0, Nr)); 12387bffde78SMichael Lange { 12393be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 12402e72742cSMatthew G. Knepley 12419566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&faceHash)); 12423be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 12433be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 12442e72742cSMatthew G. Knepley 124563a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %" PetscInt_FMT "\n", rank, p)); 12469566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug)); 12472e72742cSMatthew G. Knepley } 12489566063dSJacob Faibussowitsch PetscCall(PetscHMapIJClear(faceHash)); 12499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(candidateSection)); 12509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize)); 12519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesSize, &candidates)); 12523be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 12533be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 12542e72742cSMatthew G. Knepley 125563a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %" PetscInt_FMT "\n", rank, p)); 12569566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug)); 12572e72742cSMatthew G. Knepley } 12589566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&faceHash)); 12599566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 12607bffde78SMichael Lange } 12619566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section")); 12629566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view")); 12639566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates)); 12643be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 12652e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 12667bffde78SMichael Lange { 12677bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 12687bffde78SMichael Lange PetscInt *remoteOffsets; 12692e72742cSMatthew G. Knepley 12709566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti)); 12719566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse)); 12729566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateRemoteSection)); 12739566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection)); 12749566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates)); 12759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize)); 12769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote)); 12779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE)); 12789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE)); 12799566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfInverse)); 12809566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfCandidates)); 12819566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 12822e72742cSMatthew G. Knepley 12839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section")); 12849566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view")); 12859566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote)); 12867bffde78SMichael Lange } 12873be36e83SMatthew 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 */ 12887bffde78SMichael Lange { 1289a03d55ffSStefano Zampini PetscHMapIJKLRemote faceTable; 12903be36e83SMatthew G. Knepley PetscInt idx, idx2; 12913be36e83SMatthew G. Knepley 1292a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteCreate(&faceTable)); 12932e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 12943be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 12952e72742cSMatthew G. Knepley PetscInt deg; 12963be36e83SMatthew G. Knepley 12972e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 12982e72742cSMatthew G. Knepley PetscInt offset, dof, d; 12992e72742cSMatthew G. Knepley 13009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof)); 13019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset)); 13023be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 13032e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 13043be36e83SMatthew G. Knepley const PetscInt hidx = offset + d; 13053be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1; 13063be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx + 1]; 13073be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2]; 13083be36e83SMatthew G. Knepley PetscSFNode fcp0; 13093be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 13102e72742cSMatthew G. Knepley const PetscInt *join = NULL; 1311a03d55ffSStefano Zampini PetscHMapIJKLRemoteKey key; 13123be36e83SMatthew G. Knepley PetscHashIter iter; 13135f80ce2aSJacob Faibussowitsch PetscBool missing, mapToLocalPointFailed = PETSC_FALSE; 13142e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 13152e72742cSMatthew G. Knepley 13169371c9d4SSatish Balay if (debug) 13179371c9d4SSatish 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, 13189371c9d4SSatish Balay rface.index, r, idx, d, Np)); 131963a3b9bcSJacob 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); 13203be36e83SMatthew G. Knepley fcp0.rank = rank; 13213be36e83SMatthew G. Knepley fcp0.index = r; 13223be36e83SMatthew G. Knepley d += Np; 13233be36e83SMatthew G. Knepley /* Put remote face in hash table */ 13243be36e83SMatthew G. Knepley key.i = fcp0; 13253be36e83SMatthew G. Knepley key.j = fcone[0]; 13263be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 13273be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 13289566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key)); 1329a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing)); 13303be36e83SMatthew G. Knepley if (missing) { 133163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank)); 1332a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface)); 13333be36e83SMatthew G. Knepley } else { 13343be36e83SMatthew G. Knepley PetscSFNode oface; 13353be36e83SMatthew G. Knepley 1336a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface)); 13373be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 133863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank)); 1339a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface)); 13403be36e83SMatthew G. Knepley } 13413be36e83SMatthew G. Knepley } 13423be36e83SMatthew G. Knepley /* Check for local face */ 13432e72742cSMatthew G. Knepley points[0] = r; 13443be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 13459566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed)); 13465f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) break; /* We got a point not in our overlap */ 134763a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Checking local candidate %" PetscInt_FMT "\n", rank, points[p])); 13487bffde78SMichael Lange } 13495f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) continue; 13509566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join)); 13517bffde78SMichael Lange if (joinSize == 1) { 13523be36e83SMatthew G. Knepley PetscSFNode lface; 13533be36e83SMatthew G. Knepley PetscSFNode oface; 13543be36e83SMatthew G. Knepley 13553be36e83SMatthew G. Knepley /* Always replace with local face */ 13563be36e83SMatthew G. Knepley lface.rank = rank; 13573be36e83SMatthew G. Knepley lface.index = join[0]; 1358a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface)); 13599371c9d4SSatish Balay if (debug) 13609371c9d4SSatish 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)); 1361a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface)); 13627bffde78SMichael Lange } 13639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join)); 13643be36e83SMatthew G. Knepley } 13653be36e83SMatthew G. Knepley } 13663be36e83SMatthew G. Knepley /* Put back faces for this root */ 13673be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 13683be36e83SMatthew G. Knepley PetscInt offset, dof, d; 13693be36e83SMatthew G. Knepley 13709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof)); 13719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset)); 13723be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 13733be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 13743be36e83SMatthew G. Knepley const PetscInt hidx = offset + d; 13753be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1; 13763be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2]; 13773be36e83SMatthew G. Knepley PetscSFNode fcp0; 13783be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 1379a03d55ffSStefano Zampini PetscHMapIJKLRemoteKey key; 13803be36e83SMatthew G. Knepley PetscHashIter iter; 13813be36e83SMatthew G. Knepley PetscBool missing; 13823be36e83SMatthew G. Knepley 138363a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx)); 138463a3b9bcSJacob Faibussowitsch PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np); 13853be36e83SMatthew G. Knepley fcp0.rank = rank; 13863be36e83SMatthew G. Knepley fcp0.index = r; 13873be36e83SMatthew G. Knepley d += Np; 13883be36e83SMatthew G. Knepley /* Find remote face in hash table */ 13893be36e83SMatthew G. Knepley key.i = fcp0; 13903be36e83SMatthew G. Knepley key.j = fcone[0]; 13913be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 13923be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 13939566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key)); 13949371c9d4SSatish Balay if (debug) 13959371c9d4SSatish 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, 13969371c9d4SSatish 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)); 1397a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing)); 139863a3b9bcSJacob Faibussowitsch PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2); 1399a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx])); 14007bffde78SMichael Lange } 14017bffde78SMichael Lange } 14027bffde78SMichael Lange } 14039566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL)); 1404a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable)); 14057bffde78SMichael Lange } 14063be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 14077bffde78SMichael Lange { 14087bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 14097bffde78SMichael Lange PetscSFNode *remotePointsNew; 14102e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 14113be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 14122e72742cSMatthew G. Knepley 14133be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 14149566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti)); 14159566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &claimSection)); 14169566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection)); 14179566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims)); 14189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize)); 14199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(claimsSize, &claims)); 14203be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 14219566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE)); 14229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE)); 14239566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfClaims)); 14249566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 14259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section")); 14269566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view")); 14279566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims)); 14283be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 14293be36e83SMatthew 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 */ 14309566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&claimshash)); 14313be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 14323be36e83SMatthew G. Knepley PetscInt dof, off, d; 14332e72742cSMatthew G. Knepley 143463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %" PetscInt_FMT "\n", rank, r)); 14359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateSection, r, &dof)); 14369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateSection, r, &off)); 14372e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 14383be36e83SMatthew G. Knepley if (claims[off + d].rank >= 0) { 14393be36e83SMatthew G. Knepley const PetscInt faceInd = off + d; 14403be36e83SMatthew G. Knepley const PetscInt Np = candidates[off + d].index; 14412e72742cSMatthew G. Knepley const PetscInt *join = NULL; 14422e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 14432e72742cSMatthew G. Knepley 144463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index)); 14453be36e83SMatthew G. Knepley points[0] = r; 144663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[0])); 14473be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 14489566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL)); 144963a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[c + 1])); 14502e72742cSMatthew G. Knepley } 14519566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join)); 14522e72742cSMatthew G. Knepley if (joinSize == 1) { 14533be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 145463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0])); 14553be36e83SMatthew G. Knepley } else { 145663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found local face %" PetscInt_FMT "\n", rank, join[0])); 14579566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(claimshash, join[0], faceInd)); 14582e72742cSMatthew G. Knepley } 14593be36e83SMatthew G. Knepley } else { 14609566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank)); 14613be36e83SMatthew G. Knepley } 14629566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join)); 14633be36e83SMatthew G. Knepley } else { 146463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] No claim for point %" PetscInt_FMT "\n", rank, r)); 14653be36e83SMatthew G. Knepley d += claims[off + d].index + 1; 14667bffde78SMichael Lange } 14677bffde78SMichael Lange } 14683be36e83SMatthew G. Knepley } 14699566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 14703be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 14719566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(claimshash, &NlNew)); 14729566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew)); 14749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew)); 14753be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 14763be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 14773be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 14783be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 14797bffde78SMichael Lange } 14803be36e83SMatthew G. Knepley p = Nl; 14819566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew)); 14823be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 14838e3a54c0SPierre Jolivet PetscCall(PetscSortInt(NlNew, PetscSafePointerPlusOffset(localPointsNew, Nl))); 14843be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 14853be36e83SMatthew G. Knepley PetscInt off; 14869566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off)); 14871dca8a05SBarry 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); 14883be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 14897bffde78SMichael Lange } 14909566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfPointNew)); 14919566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 14929566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfPointNew)); 14939566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPointNew)); 14949566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view")); 1495d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE)); 14969566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPointNew)); 14979566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&claimshash)); 14987bffde78SMichael Lange } 14999566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&remoteHash)); 15009566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateSection)); 15019566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateRemoteSection)); 15029566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&claimSection)); 15039566063dSJacob Faibussowitsch PetscCall(PetscFree(candidates)); 15049566063dSJacob Faibussowitsch PetscCall(PetscFree(candidatesRemote)); 15059566063dSJacob Faibussowitsch PetscCall(PetscFree(claims)); 15069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0)); 15073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15087bffde78SMichael Lange } 15097bffde78SMichael Lange 1510248eb259SVaclav Hapla /*@ 151180330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 151280330477SMatthew G. Knepley 151320f4b53cSBarry Smith Collective 151480330477SMatthew G. Knepley 151520f4b53cSBarry Smith Input Parameter: 151620f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices 151780330477SMatthew G. Knepley 151880330477SMatthew G. Knepley Output Parameter: 151920f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object 152080330477SMatthew G. Knepley 152180330477SMatthew G. Knepley Level: intermediate 152280330477SMatthew G. Knepley 152320f4b53cSBarry Smith Note: 15247fb59074SVaclav Hapla Labels and coordinates are copied. 152543eeeb2dSStefano Zampini 152660225df5SJacob Faibussowitsch Developer Notes: 152720f4b53cSBarry Smith It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`. 15289ade3219SVaclav Hapla 152920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()` 153080330477SMatthew G. Knepley @*/ 1531d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 1532d71ae5a4SJacob Faibussowitsch { 1533a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 15349a5b13a2SMatthew G Knepley DM idm, odm = dm; 15357bffde78SMichael Lange PetscSF sfPoint; 15362e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 153710a67516SMatthew G. Knepley const char *name; 1538b325530aSVaclav Hapla PetscBool flg = PETSC_TRUE; 15399f074e33SMatthew G Knepley 15409f074e33SMatthew G Knepley PetscFunctionBegin; 154110a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15424f572ea9SToby Isaac PetscAssertPointer(dmInt, 2); 15439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0)); 15449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 15459566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15469566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 154708401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1548827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 15499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 155076b791aaSMatthew G. Knepley idm = dm; 1551b21b8912SMatthew G. Knepley } else { 15525c2c0cecSMatthew G. Knepley PetscBool nonmanifold = PETSC_FALSE; 15535c2c0cecSMatthew G. Knepley 15545c2c0cecSMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &nonmanifold, NULL)); 15555c2c0cecSMatthew G. Knepley if (nonmanifold) { 15565c2c0cecSMatthew G. Knepley do { 15575c2c0cecSMatthew G. Knepley const char *prefix; 15585c2c0cecSMatthew G. Knepley PetscInt pStart, pEnd, pdepth; 15595c2c0cecSMatthew G. Knepley PetscBool done = PETSC_TRUE; 15605c2c0cecSMatthew G. Knepley 15615c2c0cecSMatthew G. Knepley // Find a point which is not correctly interpolated 15625c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetChart(odm, &pStart, &pEnd)); 15635c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 15645c2c0cecSMatthew G. Knepley DMPolytopeType ct; 15655c2c0cecSMatthew G. Knepley const PetscInt *cone; 15665c2c0cecSMatthew G. Knepley PetscInt coneSize, cdepth; 15675c2c0cecSMatthew G. Knepley 15685c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(odm, p, &pdepth)); 15695c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetCellType(odm, p, &ct)); 15705c2c0cecSMatthew G. Knepley // Check against celltype 15715c2c0cecSMatthew G. Knepley if (pdepth != DMPolytopeTypeGetDim(ct)) { 15725c2c0cecSMatthew G. Knepley done = PETSC_FALSE; 15735c2c0cecSMatthew G. Knepley break; 15745c2c0cecSMatthew G. Knepley } 15755c2c0cecSMatthew G. Knepley // Check against boundary 15765c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetCone(odm, p, &cone)); 15775c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(odm, p, &coneSize)); 15785c2c0cecSMatthew G. Knepley for (PetscInt c = 0; c < coneSize; ++c) { 15795c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(odm, cone[c], &cdepth)); 15805c2c0cecSMatthew G. Knepley if (cdepth != pdepth - 1) { 15815c2c0cecSMatthew G. Knepley done = PETSC_FALSE; 15825c2c0cecSMatthew G. Knepley p = pEnd; 15835c2c0cecSMatthew G. Knepley break; 15845c2c0cecSMatthew G. Knepley } 15855c2c0cecSMatthew G. Knepley } 15865c2c0cecSMatthew G. Knepley } 15875c2c0cecSMatthew G. Knepley if (done) break; 15885c2c0cecSMatthew G. Knepley /* Create interpolated mesh */ 15895c2c0cecSMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm)); 15905c2c0cecSMatthew G. Knepley PetscCall(DMSetType(idm, DMPLEX)); 15915c2c0cecSMatthew G. Knepley PetscCall(DMSetDimension(idm, dim)); 15925c2c0cecSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 15935c2c0cecSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix)); 15945c2c0cecSMatthew G. Knepley if (depth > 0) { 15955c2c0cecSMatthew G. Knepley PetscCall(DMPlexInterpolateFaces_Internal(odm, pdepth, idm)); 15965c2c0cecSMatthew G. Knepley PetscCall(DMGetPointSF(odm, &sfPoint)); 15975c2c0cecSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE)); 15985c2c0cecSMatthew G. Knepley { 15995c2c0cecSMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 16005c2c0cecSMatthew G. Knepley PetscInt nroots; 16015c2c0cecSMatthew G. Knepley PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 16025c2c0cecSMatthew G. Knepley if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint)); 16035c2c0cecSMatthew G. Knepley } 16045c2c0cecSMatthew G. Knepley } 16055c2c0cecSMatthew G. Knepley if (odm != dm) PetscCall(DMDestroy(&odm)); 16065c2c0cecSMatthew G. Knepley odm = idm; 16075c2c0cecSMatthew G. Knepley } while (1); 16085c2c0cecSMatthew G. Knepley } else { 16099a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 16106f5c9017SMatthew G. Knepley const char *prefix; 16116f5c9017SMatthew G. Knepley 16129a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 16139566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm)); 16149566063dSJacob Faibussowitsch PetscCall(DMSetType(idm, DMPLEX)); 16159566063dSJacob Faibussowitsch PetscCall(DMSetDimension(idm, dim)); 16166f5c9017SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 16176f5c9017SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix)); 16187bffde78SMichael Lange if (depth > 0) { 16199566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm)); 16209566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(odm, &sfPoint)); 1621d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE)); 162294488200SVaclav Hapla { 16233be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 162494488200SVaclav Hapla PetscInt nroots; 16259566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 16269566063dSJacob Faibussowitsch if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint)); 162794488200SVaclav Hapla } 16287bffde78SMichael Lange } 16299566063dSJacob Faibussowitsch if (odm != dm) PetscCall(DMDestroy(&odm)); 16309a5b13a2SMatthew G Knepley odm = idm; 16319f074e33SMatthew G Knepley } 16325c2c0cecSMatthew G. Knepley } 16339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 16349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)idm, name)); 16359566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 16369566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL)); 16379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL)); 16389566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexOrientInterface_Internal(idm)); 163984699f70SSatish Balay } 1640827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1641827c4036SVaclav Hapla { 1642d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)idm->data; 1643827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1644827c4036SVaclav Hapla } 16455de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm)); 16469a5b13a2SMatthew G Knepley *dmInt = idm; 16479566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0)); 16483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16499f074e33SMatthew G Knepley } 165007b0a1fcSMatthew G Knepley 165180330477SMatthew G. Knepley /*@ 165280330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 165380330477SMatthew G. Knepley 165420f4b53cSBarry Smith Collective 165580330477SMatthew G. Knepley 165680330477SMatthew G. Knepley Input Parameter: 165720f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates 165880330477SMatthew G. Knepley 165980330477SMatthew G. Knepley Output Parameter: 166020f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates 166180330477SMatthew G. Knepley 166280330477SMatthew G. Knepley Level: intermediate 166380330477SMatthew G. Knepley 16646f5c9017SMatthew G. Knepley Notes: 166520f4b53cSBarry Smith This is typically used when adding pieces other than vertices to a mesh 166680330477SMatthew G. Knepley 16676f5c9017SMatthew G. Knepley This function does not copy localized coordinates. 16686f5c9017SMatthew G. Knepley 166920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()` 167080330477SMatthew G. Knepley @*/ 1671d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 1672d71ae5a4SJacob Faibussowitsch { 167307b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 167443eeeb2dSStefano Zampini VecType vtype; 167507b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 167607b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 16770bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 167890a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 167907b0a1fcSMatthew G Knepley 168007b0a1fcSMatthew G Knepley PetscFunctionBegin; 168143eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 168243eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 16833ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS); 16849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &cdim)); 16859566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dmB, cdim)); 16869566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA)); 16879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB)); 168863a3b9bcSJacob 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); 168961a622f3SMatthew G. Knepley /* Copy over discretization if it exists */ 169061a622f3SMatthew G. Knepley { 169161a622f3SMatthew G. Knepley DM cdmA, cdmB; 169261a622f3SMatthew G. Knepley PetscDS dsA, dsB; 169361a622f3SMatthew G. Knepley PetscObject objA, objB; 169461a622f3SMatthew G. Knepley PetscClassId idA, idB; 169561a622f3SMatthew G. Knepley const PetscScalar *constants; 169661a622f3SMatthew G. Knepley PetscInt cdim, Nc; 169761a622f3SMatthew G. Knepley 16989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &cdmA)); 16999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &cdmB)); 17009566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmA, 0, NULL, &objA)); 17019566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmB, 0, NULL, &objB)); 17029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objA, &idA)); 17039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objB, &idB)); 170461a622f3SMatthew G. Knepley if ((idA == PETSCFE_CLASSID) && (idA != idB)) { 17059566063dSJacob Faibussowitsch PetscCall(DMSetField(cdmB, 0, NULL, objA)); 17069566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdmB)); 17079566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmA, &dsA)); 17089566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmB, &dsB)); 17099566063dSJacob Faibussowitsch PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim)); 17109566063dSJacob Faibussowitsch PetscCall(PetscDSSetCoordinateDimension(dsB, cdim)); 17119566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(dsA, &Nc, &constants)); 17129566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants)); 171361a622f3SMatthew G. Knepley } 171461a622f3SMatthew G. Knepley } 17159566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA)); 17169566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB)); 17179566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmA, &coordSectionA)); 17189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmB, &coordSectionB)); 17193ba16761SJacob Faibussowitsch if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS); 17209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf)); 17213ba16761SJacob Faibussowitsch if (!Nf) PetscFunctionReturn(PETSC_SUCCESS); 172263a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf); 1723df26b574SMatthew G. Knepley if (!coordSectionB) { 1724df26b574SMatthew G. Knepley PetscInt dim; 1725df26b574SMatthew G. Knepley 17269566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB)); 17279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &dim)); 17289566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB)); 17299566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordSectionB)); 1730df26b574SMatthew G. Knepley } 17319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSectionB, 1)); 17329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim)); 17339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim)); 17349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE)); 173543eeeb2dSStefano Zampini cS = vStartB; 173643eeeb2dSStefano Zampini cE = vEndB; 17379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSectionB, cS, cE)); 173807b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 17399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim)); 17409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim)); 174107b0a1fcSMatthew G Knepley } 17429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSectionB)); 17439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB)); 17449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA)); 17459566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB)); 17469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates")); 17479566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE)); 17489566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(coordinatesA, &d)); 17499566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinatesB, d)); 17509566063dSJacob Faibussowitsch PetscCall(VecGetType(coordinatesA, &vtype)); 17519566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinatesB, vtype)); 17529566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesA, &coordsA)); 17539566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesB, &coordsB)); 175407b0a1fcSMatthew G Knepley for (v = 0; v < vEndB - vStartB; ++v) { 175543eeeb2dSStefano Zampini PetscInt offA, offB; 175643eeeb2dSStefano Zampini 17579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA)); 17589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB)); 1759ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d]; 176043eeeb2dSStefano Zampini } 17619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesA, &coordsA)); 17629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesB, &coordsB)); 17639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB)); 17649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinatesB)); 17653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 176607b0a1fcSMatthew G Knepley } 17675c386225SMatthew G. Knepley 17684e3744c5SMatthew G. Knepley /*@ 17694e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 17704e3744c5SMatthew G. Knepley 177120f4b53cSBarry Smith Collective 17724e3744c5SMatthew G. Knepley 17734e3744c5SMatthew G. Knepley Input Parameter: 177420f4b53cSBarry Smith . dm - The complete `DMPLEX` object 17754e3744c5SMatthew G. Knepley 17764e3744c5SMatthew G. Knepley Output Parameter: 177720f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices 17784e3744c5SMatthew G. Knepley 17794e3744c5SMatthew G. Knepley Level: intermediate 17804e3744c5SMatthew G. Knepley 178120f4b53cSBarry Smith Note: 178295452b02SPatrick Sanan It does not copy over the coordinates. 178343eeeb2dSStefano Zampini 178460225df5SJacob Faibussowitsch Developer Notes: 178520f4b53cSBarry Smith Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`. 17869ade3219SVaclav Hapla 178720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()` 17884e3744c5SMatthew G. Knepley @*/ 1789d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 1790d71ae5a4SJacob Faibussowitsch { 1791827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 17924e3744c5SMatthew G. Knepley DM udm; 1793412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; 17944e3744c5SMatthew G. Knepley 17954e3744c5SMatthew G. Knepley PetscFunctionBegin; 179643eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17974f572ea9SToby Isaac PetscAssertPointer(dmUnint, 2); 1798172ee266SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0)); 17999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 18009566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 180108401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1802827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1803827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 18049566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 1805595d4abbSMatthew G. Knepley *dmUnint = dm; 18063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18074e3744c5SMatthew G. Knepley } 18089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18099566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 18109566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm)); 18119566063dSJacob Faibussowitsch PetscCall(DMSetType(udm, DMPLEX)); 18129566063dSJacob Faibussowitsch PetscCall(DMSetDimension(udm, dim)); 18139566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(udm, cStart, vEnd)); 18144e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1815595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 18164e3744c5SMatthew G. Knepley 18179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 18184e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 18194e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 18204e3744c5SMatthew G. Knepley 18214e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 18224e3744c5SMatthew G. Knepley } 18239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 18249566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(udm, c, coneSize)); 1825595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 18264e3744c5SMatthew G. Knepley } 18279566063dSJacob Faibussowitsch PetscCall(DMSetUp(udm)); 18289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConeSize, &cone)); 18294e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1830595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 18314e3744c5SMatthew G. Knepley 18329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 18334e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 18344e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 18354e3744c5SMatthew G. Knepley 18364e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 18374e3744c5SMatthew G. Knepley } 18389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 18399566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(udm, c, cone)); 18404e3744c5SMatthew G. Knepley } 18419566063dSJacob Faibussowitsch PetscCall(PetscFree(cone)); 18429566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(udm)); 18439566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(udm)); 18445c7de58aSMatthew G. Knepley /* Reduce SF */ 18455c7de58aSMatthew G. Knepley { 18465c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 18475c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 18485c7de58aSMatthew G. Knepley const PetscInt *localPoints; 18495c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 18505c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 185122fd0ad9SVaclav Hapla PetscInt numRoots, numLeaves, l; 18525c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 18535c7de58aSMatthew G. Knepley 18545c7de58aSMatthew G. Knepley /* Get original SF information */ 18559566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 1856d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE)); 18579566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(udm, &sfPointUn)); 18589566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 185922fd0ad9SVaclav Hapla if (numRoots >= 0) { 18605c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 186122fd0ad9SVaclav Hapla for (l = 0; l < numLeaves; ++l) { 186222fd0ad9SVaclav Hapla const PetscInt p = localPoints[l]; 186322fd0ad9SVaclav Hapla 186422fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++; 186522fd0ad9SVaclav Hapla } 18665c7de58aSMatthew G. Knepley /* Fill in leaves */ 18679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn)); 18689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn)); 18695c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 187022fd0ad9SVaclav Hapla const PetscInt p = localPoints[l]; 187122fd0ad9SVaclav Hapla 187222fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) { 187322fd0ad9SVaclav Hapla localPointsUn[n] = p; 18745c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 18755c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 18765c7de58aSMatthew G. Knepley ++n; 18775c7de58aSMatthew G. Knepley } 18785c7de58aSMatthew G. Knepley } 187963a3b9bcSJacob Faibussowitsch PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn); 188022fd0ad9SVaclav Hapla PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER)); 18815c7de58aSMatthew G. Knepley } 18825c7de58aSMatthew G. Knepley } 1883827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1884827c4036SVaclav Hapla { 1885d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)udm->data; 1886827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1887827c4036SVaclav Hapla } 18885de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm)); 1889d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE)); 18904e3744c5SMatthew G. Knepley *dmUnint = udm; 1891172ee266SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0)); 18923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18934e3744c5SMatthew G. Knepley } 1894a7748839SVaclav Hapla 1895d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1896d71ae5a4SJacob Faibussowitsch { 1897a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1898a7748839SVaclav Hapla MPI_Comm comm; 1899a7748839SVaclav Hapla 1900a7748839SVaclav Hapla PetscFunctionBegin; 19019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 19029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 19039566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1904a7748839SVaclav Hapla 1905a7748839SVaclav Hapla if (depth == dim) { 1906a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1907a7748839SVaclav Hapla if (!dim) goto finish; 1908a7748839SVaclav Hapla 1909a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 19109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd)); 1911a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) { 19129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1913a7748839SVaclav Hapla if (coneSize) { 1914a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1915a7748839SVaclav Hapla goto finish; 1916a7748839SVaclav Hapla } 1917a7748839SVaclav Hapla } 1918a7748839SVaclav Hapla 1919a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1920a7748839SVaclav Hapla for (h = 0; h < dim; h++) { 19219566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 1922a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) { 19239566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1924a7748839SVaclav Hapla if (!coneSize) { 1925a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1926a7748839SVaclav Hapla goto finish; 1927a7748839SVaclav Hapla } 1928a7748839SVaclav Hapla } 1929a7748839SVaclav Hapla } 1930a7748839SVaclav Hapla } else if (depth == 1) { 1931a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1932a7748839SVaclav Hapla } else { 1933a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1934a7748839SVaclav Hapla } 1935a7748839SVaclav Hapla finish: 19363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1937a7748839SVaclav Hapla } 1938a7748839SVaclav Hapla 1939a7748839SVaclav Hapla /*@ 194020f4b53cSBarry Smith DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated. 1941a7748839SVaclav Hapla 1942a7748839SVaclav Hapla Not Collective 1943a7748839SVaclav Hapla 1944a7748839SVaclav Hapla Input Parameter: 194520f4b53cSBarry Smith . dm - The `DMPLEX` object 1946a7748839SVaclav Hapla 1947a7748839SVaclav Hapla Output Parameter: 194820f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated 1949a7748839SVaclav Hapla 1950a7748839SVaclav Hapla Level: intermediate 1951a7748839SVaclav Hapla 1952a7748839SVaclav Hapla Notes: 195320f4b53cSBarry Smith Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective 19549ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 195520f4b53cSBarry Smith However, `DMPlexInterpolate()` guarantees the result is the same on all. 19569ade3219SVaclav Hapla 195720f4b53cSBarry Smith Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`. 1958a7748839SVaclav Hapla 19599ade3219SVaclav Hapla Developer Notes: 196020f4b53cSBarry Smith Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`. 19619ade3219SVaclav Hapla 196220f4b53cSBarry Smith If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called. 19639ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 196420f4b53cSBarry Smith `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`. 19659ade3219SVaclav Hapla 196620f4b53cSBarry Smith If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated. 19679ade3219SVaclav Hapla 196820f4b53cSBarry Smith `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`, 196920f4b53cSBarry Smith and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`. 19709ade3219SVaclav Hapla 197120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()` 1972a7748839SVaclav Hapla @*/ 1973d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1974d71ae5a4SJacob Faibussowitsch { 1975a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data; 1976a7748839SVaclav Hapla 1977a7748839SVaclav Hapla PetscFunctionBegin; 1978a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19794f572ea9SToby Isaac PetscAssertPointer(interpolated, 2); 1980a7748839SVaclav Hapla if (plex->interpolated < 0) { 19819566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated)); 198276bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 1983a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1984a7748839SVaclav Hapla 19859566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &flg)); 1986c282ed06SStefano Zampini PetscCheck(plex->tr || flg == plex->interpolated, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]); 1987a7748839SVaclav Hapla } 1988a7748839SVaclav Hapla *interpolated = plex->interpolated; 19893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1990a7748839SVaclav Hapla } 1991a7748839SVaclav Hapla 1992a7748839SVaclav Hapla /*@ 199320f4b53cSBarry Smith DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner). 1994a7748839SVaclav Hapla 19952666ff3cSVaclav Hapla Collective 1996a7748839SVaclav Hapla 1997a7748839SVaclav Hapla Input Parameter: 199820f4b53cSBarry Smith . dm - The `DMPLEX` object 1999a7748839SVaclav Hapla 2000a7748839SVaclav Hapla Output Parameter: 200120f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated 2002a7748839SVaclav Hapla 2003a7748839SVaclav Hapla Level: intermediate 2004a7748839SVaclav Hapla 2005a7748839SVaclav Hapla Notes: 200620f4b53cSBarry Smith Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks. 20079ade3219SVaclav Hapla 200820f4b53cSBarry Smith This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks. 20099ade3219SVaclav Hapla 20109ade3219SVaclav Hapla Developer Notes: 201120f4b53cSBarry Smith Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`. 20129ade3219SVaclav Hapla 201320f4b53cSBarry Smith If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated. 201420f4b53cSBarry Smith `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 201520f4b53cSBarry Smith if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`, 20169ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 20179ade3219SVaclav Hapla 201820f4b53cSBarry Smith If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective. 2019a7748839SVaclav Hapla 202020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()` 2021a7748839SVaclav Hapla @*/ 2022d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 2023d71ae5a4SJacob Faibussowitsch { 2024a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data; 2025a7748839SVaclav Hapla PetscBool debug = PETSC_FALSE; 2026a7748839SVaclav Hapla 2027a7748839SVaclav Hapla PetscFunctionBegin; 2028a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20294f572ea9SToby Isaac PetscAssertPointer(interpolated, 2); 20309566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL)); 2031a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 2032a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 2033a7748839SVaclav Hapla MPI_Comm comm; 2034a7748839SVaclav Hapla 20359566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 20369566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective)); 2037712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm)); 2038712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm)); 2039a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 2040a7748839SVaclav Hapla if (debug) { 2041a7748839SVaclav Hapla PetscMPIInt rank; 2042a7748839SVaclav Hapla 20439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 20449566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective])); 20459566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 2046a7748839SVaclav Hapla } 2047a7748839SVaclav Hapla } 2048a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 20493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2050a7748839SVaclav Hapla } 2051