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*5c2c0cecSMatthew G. Knepley PetscInt depth, pStart, Np, cStart, cEnd, fStart, fEnd; 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)); 5059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd)); 506*5c2c0cecSMatthew G. Knepley // Number new faces and save face vertices in hash table 5079566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart)); 508412e9a14SMatthew G. Knepley fEnd = fStart; 509591a860aSStefano Zampini 510a03d55ffSStefano Zampini minCone = PETSC_MAX_INT; 511*5c2c0cecSMatthew G. Knepley cntFaces = 0; 512*5c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 513591a860aSStefano Zampini const PetscInt *cone; 514591a860aSStefano Zampini DMPolytopeType ct; 515ed896b67SJose E. Roman PetscInt numFaces = 0, coneSize; 516591a860aSStefano Zampini 517591a860aSStefano Zampini PetscCall(DMPlexGetCellType(dm, c, &ct)); 518591a860aSStefano Zampini PetscCall(DMPlexGetCone(dm, c, &cone)); 519a03d55ffSStefano Zampini PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 520a03d55ffSStefano Zampini for (PetscInt j = 0; j < coneSize; j++) minCone = PetscMin(cone[j], minCone); 5216f5c9017SMatthew G. Knepley // Ignore faces since they are interpolated 5226f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, NULL, NULL, NULL)); 523591a860aSStefano Zampini cntFaces += numFaces; 524591a860aSStefano Zampini } 525a03d55ffSStefano Zampini // Encode so that we can use 0 as an excluded value, instead of PETSC_MAX_INT 526a03d55ffSStefano Zampini minCone = -(minCone - 1); 527591a860aSStefano Zampini 528591a860aSStefano Zampini PetscCall(PetscMalloc1(cntFaces, &facesId)); 529591a860aSStefano Zampini 530*5c2c0cecSMatthew G. Knepley cntFaces = 0; 531*5c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 532412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 533412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 534ba2698f1SMatthew G. Knepley DMPolytopeType ct; 535*5c2c0cecSMatthew G. Knepley PetscInt numFaces, foff = 0; 53699836e0eSStefano Zampini 5379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5396f5c9017SMatthew G. Knepley // Ignore faces since they are interpolated 5406f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 5419566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 5426f5c9017SMatthew G. Knepley } else { 5436f5c9017SMatthew G. Knepley numFaces = 0; 5446f5c9017SMatthew G. Knepley } 545*5c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 546412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 547412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 548412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 5499a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 550e8f14785SLisandro Dalcin PetscHashIter iter; 551e8f14785SLisandro Dalcin PetscBool missing; 5529f074e33SMatthew G Knepley 5535f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 554a03d55ffSStefano Zampini key.i = face[0] + minCone; 555a03d55ffSStefano Zampini key.j = faceSize > 1 ? face[1] + minCone : 0; 556a03d55ffSStefano Zampini key.k = faceSize > 2 ? face[2] + minCone : 0; 557a03d55ffSStefano Zampini key.l = faceSize > 3 ? face[3] + minCone : 0; 5589566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 559a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing)); 560e9fa77a1SMatthew G. Knepley if (missing) { 561591a860aSStefano Zampini facesId[cntFaces] = fEnd; 562a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLIterSet(faceTable, iter, fEnd++)); 563412e9a14SMatthew G. Knepley ++faceTypeNum[faceType]; 564a03d55ffSStefano Zampini } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces])); 565591a860aSStefano Zampini cntFaces++; 5669a5b13a2SMatthew G Knepley } 5676f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 56899836e0eSStefano Zampini } 569412e9a14SMatthew G. Knepley /* We need to number faces contiguously among types */ 570412e9a14SMatthew G. Knepley { 571412e9a14SMatthew G. Knepley PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0; 57299836e0eSStefano Zampini 5739371c9d4SSatish Balay for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) { 5749371c9d4SSatish Balay if (faceTypeNum[ct]) ++numFT; 5759371c9d4SSatish Balay faceTypeStart[ct] = 0; 5769371c9d4SSatish Balay } 577412e9a14SMatthew G. Knepley if (numFT > 1) { 578a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLClear(faceTable)); 579412e9a14SMatthew G. Knepley faceTypeStart[0] = fStart; 580412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1]; 581*5c2c0cecSMatthew G. Knepley cntFaces = 0; 582*5c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 583412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 584412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 585ba2698f1SMatthew G. Knepley DMPolytopeType ct; 586*5c2c0cecSMatthew G. Knepley PetscInt numFaces, foff = 0; 58799836e0eSStefano Zampini 5889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5899566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5906f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 5919566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 5926f5c9017SMatthew G. Knepley } else { 5936f5c9017SMatthew G. Knepley numFaces = 0; 5946f5c9017SMatthew G. Knepley } 595*5c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 596412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 597412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 598412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 59999836e0eSStefano Zampini PetscHashIJKLKey key; 60099836e0eSStefano Zampini PetscHashIter iter; 60199836e0eSStefano Zampini PetscBool missing; 60299836e0eSStefano Zampini 603a03d55ffSStefano Zampini key.i = face[0] + minCone; 604a03d55ffSStefano Zampini key.j = faceSize > 1 ? face[1] + minCone : 0; 605a03d55ffSStefano Zampini key.k = faceSize > 2 ? face[2] + minCone : 0; 606a03d55ffSStefano Zampini key.l = faceSize > 3 ? face[3] + minCone : 0; 6079566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 608a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLPut(faceTable, key, &iter, &missing)); 609591a860aSStefano Zampini if (missing) { 610591a860aSStefano Zampini facesId[cntFaces] = faceTypeStart[faceType]; 611a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++)); 612a03d55ffSStefano Zampini } else PetscCall(PetscHMapIJKLIterGet(faceTable, iter, &facesId[cntFaces])); 613591a860aSStefano Zampini cntFaces++; 61499836e0eSStefano Zampini } 6156f5c9017SMatthew G. Knepley if (ct != DM_POLYTOPE_SEGMENT && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 61699836e0eSStefano Zampini } 617412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) { 6181dca8a05SBarry 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]); 6199a5b13a2SMatthew G Knepley } 6209a5b13a2SMatthew G Knepley } 621412e9a14SMatthew G. Knepley } 622a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLDestroy(&faceTable)); 623591a860aSStefano Zampini 624*5c2c0cecSMatthew G. Knepley // Add new points, perhaps inserting into the numbering 6259566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &Np)); 6269566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart))); 627*5c2c0cecSMatthew G. Knepley // Set cone sizes 628*5c2c0cecSMatthew G. Knepley // Must create the celltype label here so that we do not automatically try to compute the types 6299566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(idm, "celltype")); 6309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel)); 631*5c2c0cecSMatthew G. Knepley for (PetscInt d = 0; d <= depth; ++d) { 632412e9a14SMatthew G. Knepley DMPolytopeType ct; 633*5c2c0cecSMatthew G. Knepley PetscInt coneSize, pStart, pEnd, poff = 0; 6349f074e33SMatthew G Knepley 635412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 6369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 637*5c2c0cecSMatthew G. Knepley // Account for insertion 638*5c2c0cecSMatthew G. Knepley if (pStart >= fStart) poff = fEnd - fStart; 639*5c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 6409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 641*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, p + poff, coneSize)); 6429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 643*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, p + poff, ct)); 6449f074e33SMatthew G Knepley } 6459f074e33SMatthew G Knepley } 646*5c2c0cecSMatthew G. Knepley cntFaces = 0; 647*5c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 648591a860aSStefano Zampini const PetscInt *cone, *faceSizes; 649412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 650412e9a14SMatthew G. Knepley DMPolytopeType ct; 651*5c2c0cecSMatthew G. Knepley PetscInt numFaces, poff = 0; 652412e9a14SMatthew G. Knepley 6539566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 6549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 655*5c2c0cecSMatthew G. Knepley if (c >= fStart) poff = fEnd - fStart; 6566f5c9017SMatthew G. Knepley if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 657*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, c + poff, ct)); 658*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, c + poff, 2)); 6596f5c9017SMatthew G. Knepley continue; 6606f5c9017SMatthew G. Knepley } 661591a860aSStefano Zampini PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL)); 662*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCellType(idm, c + poff, ct)); 663*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeSize(idm, c + poff, numFaces)); 664*5c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; ++cf) { 665591a860aSStefano Zampini const PetscInt f = facesId[cntFaces]; 666591a860aSStefano Zampini DMPolytopeType faceType = faceTypes[cf]; 667412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 6689566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, f, faceSize)); 6699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, f, faceType)); 670591a860aSStefano Zampini cntFaces++; 671412e9a14SMatthew G. Knepley } 672591a860aSStefano Zampini PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, NULL)); 6739f074e33SMatthew G Knepley } 6749566063dSJacob Faibussowitsch PetscCall(DMSetUp(idm)); 675*5c2c0cecSMatthew G. Knepley // Initialize cones so we do not need the bash table to tell us that a cone has been set 676412e9a14SMatthew G. Knepley { 677412e9a14SMatthew G. Knepley PetscSection cs; 678412e9a14SMatthew G. Knepley PetscInt *cones, csize; 6799a5b13a2SMatthew G Knepley 6809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(idm, &cs)); 6819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(idm, &cones)); 6829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cs, &csize)); 683*5c2c0cecSMatthew G. Knepley for (PetscInt c = 0; c < csize; ++c) cones[c] = -1; 684412e9a14SMatthew G. Knepley } 685*5c2c0cecSMatthew G. Knepley // Set cones 686*5c2c0cecSMatthew G. Knepley { 687*5c2c0cecSMatthew G. Knepley PetscInt *icone; 688*5c2c0cecSMatthew G. Knepley PetscInt maxConeSize; 689*5c2c0cecSMatthew G. Knepley 690*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL)); 691*5c2c0cecSMatthew G. Knepley PetscCall(PetscMalloc1(maxConeSize, &icone)); 692*5c2c0cecSMatthew G. Knepley for (PetscInt d = 0; d <= depth; ++d) { 693412e9a14SMatthew G. Knepley const PetscInt *cone; 694*5c2c0cecSMatthew G. Knepley PetscInt pStart, pEnd, poff = 0, coneSize; 695412e9a14SMatthew G. Knepley 696412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 6979566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 698*5c2c0cecSMatthew G. Knepley // Account for insertion 699*5c2c0cecSMatthew G. Knepley if (pStart >= fStart) poff = fEnd - fStart; 700*5c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 7019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 702*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 703*5c2c0cecSMatthew G. Knepley for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0); 704*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCone(idm, p + poff, icone)); 7059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &cone)); 706*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeOrientation(idm, p + poff, cone)); 7079f074e33SMatthew G Knepley } 7089a5b13a2SMatthew G Knepley } 709*5c2c0cecSMatthew G. Knepley cntFaces = 0; 710*5c2c0cecSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 711412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 712412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 713ba2698f1SMatthew G. Knepley DMPolytopeType ct; 714*5c2c0cecSMatthew G. Knepley PetscInt coneSize, numFaces, foff = 0, poff = 0; 71599836e0eSStefano Zampini 7169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 7179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 718*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 719*5c2c0cecSMatthew G. Knepley if (c >= fStart) poff = fEnd - fStart; 7206f5c9017SMatthew G. Knepley if (ct == DM_POLYTOPE_SEGMENT || ct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 721*5c2c0cecSMatthew G. Knepley for (PetscInt cp = 0; cp < coneSize; ++cp) icone[cp] = cone[cp] + (cone[cp] >= fStart ? fEnd - fStart : 0); 722*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetCone(idm, c + poff, icone)); 7236f5c9017SMatthew G. Knepley PetscCall(DMPlexGetConeOrientation(dm, c, &cone)); 724*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexSetConeOrientation(idm, c + poff, cone)); 7256f5c9017SMatthew G. Knepley continue; 7266f5c9017SMatthew G. Knepley } 7279566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 728*5c2c0cecSMatthew G. Knepley for (PetscInt cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 729412e9a14SMatthew G. Knepley DMPolytopeType faceType = faceTypes[cf]; 730412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 731591a860aSStefano Zampini const PetscInt f = facesId[cntFaces]; 732412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 733412e9a14SMatthew G. Knepley const PetscInt *fcone; 7349f074e33SMatthew G Knepley 7359566063dSJacob Faibussowitsch PetscCall(DMPlexInsertCone(idm, c, cf, f)); 7369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(idm, f, &fcone)); 7379566063dSJacob Faibussowitsch if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face)); 738412e9a14SMatthew G. Knepley { 739*5c2c0cecSMatthew G. Knepley const PetscInt *fcone; 740*5c2c0cecSMatthew G. Knepley PetscInt ornt; 741a74221b0SStefano Zampini 7429566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(idm, f, &coneSize)); 743*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetCone(idm, f, &fcone)); 74463a3b9bcSJacob 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); 745d89e6e46SMatthew G. Knepley /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */ 746*5c2c0cecSMatthew G. Knepley PetscCall(DMPolytopeGetVertexOrientation(faceType, fcone, face, &ornt)); 747*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexInsertConeOrientation(idm, c + poff, cf, ornt)); 74899836e0eSStefano Zampini } 749591a860aSStefano Zampini cntFaces++; 75099836e0eSStefano Zampini } 7519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 75299836e0eSStefano Zampini } 753*5c2c0cecSMatthew G. Knepley PetscCall(PetscFree(icone)); 754*5c2c0cecSMatthew G. Knepley } 755591a860aSStefano Zampini PetscCall(PetscFree(facesId)); 7569566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(idm)); 7579566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(idm)); 7583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7599f074e33SMatthew G Knepley } 7609f074e33SMatthew G Knepley 761d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) 762d71ae5a4SJacob Faibussowitsch { 763f80536cbSVaclav Hapla PetscInt nleaves; 764f80536cbSVaclav Hapla PetscInt nranks; 765a0d42dbcSVaclav Hapla const PetscMPIInt *ranks = NULL; 766a0d42dbcSVaclav Hapla const PetscInt *roffset = NULL, *rmine = NULL, *rremote = NULL; 767f80536cbSVaclav Hapla PetscInt n, o, r; 768f80536cbSVaclav Hapla 769f80536cbSVaclav Hapla PetscFunctionBegin; 7709566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote)); 771f80536cbSVaclav Hapla nleaves = roffset[nranks]; 7729566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1)); 773f80536cbSVaclav Hapla for (r = 0; r < nranks; r++) { 774f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 775f80536cbSVaclav Hapla - to unify order with the other side */ 776f80536cbSVaclav Hapla o = roffset[r]; 777f80536cbSVaclav Hapla n = roffset[r + 1] - o; 7789566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n)); 7799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n)); 7809566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o])); 781f80536cbSVaclav Hapla } 7823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 783f80536cbSVaclav Hapla } 784f80536cbSVaclav Hapla 785d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm) 786d71ae5a4SJacob Faibussowitsch { 787d89e6e46SMatthew G. Knepley PetscSF sf; 788d89e6e46SMatthew G. Knepley const PetscInt *locals; 789d89e6e46SMatthew G. Knepley const PetscSFNode *remotes; 790d89e6e46SMatthew G. Knepley const PetscMPIInt *ranks; 791d89e6e46SMatthew G. Knepley const PetscInt *roffset; 792d89e6e46SMatthew G. Knepley PetscInt *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 793d89e6e46SMatthew G. Knepley PetscInt nroots, p, nleaves, nranks, r, maxConeSize = 0; 794d89e6e46SMatthew G. Knepley PetscInt(*roots)[4], (*leaves)[4], mainCone[4]; 795d89e6e46SMatthew G. Knepley PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4]; 7962e745bdaSMatthew G. Knepley MPI_Comm comm; 79727d0e99aSVaclav Hapla PetscMPIInt rank, size; 7982e745bdaSMatthew G. Knepley PetscInt debug = 0; 7992e745bdaSMatthew G. Knepley 8002e745bdaSMatthew G. Knepley PetscFunctionBegin; 8019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 8029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 8049566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 8059566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view")); 806d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE)); 8079566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes)); 8083ba16761SJacob Faibussowitsch if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS); 8099566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 8109566063dSJacob Faibussowitsch PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1)); 811d89e6e46SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 812d89e6e46SMatthew G. Knepley PetscInt coneSize; 8139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize)); 814d89e6e46SMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 815d89e6e46SMatthew G. Knepley } 81663a3b9bcSJacob Faibussowitsch PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize); 8179566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks)); 8189e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 819d89e6e46SMatthew G. Knepley const PetscInt *cone; 820d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0; 821d89e6e46SMatthew G. Knepley 8229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 8239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 824d89e6e46SMatthew G. Knepley /* Ignore vertices */ 82527d0e99aSVaclav Hapla if (coneSize < 2) { 826d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 82727d0e99aSVaclav Hapla roots[p][c] = -1; 82827d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 82927d0e99aSVaclav Hapla } 83027d0e99aSVaclav Hapla continue; 83127d0e99aSVaclav Hapla } 8322e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 833d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); c++) { 8349566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0)); 8358a650c75SVaclav Hapla if (ind0 < 0) { 8368a650c75SVaclav Hapla roots[p][c] = cone[c]; 8378a650c75SVaclav Hapla rootsRanks[p][c] = rank; 838c8148b97SVaclav Hapla } else { 8398a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 8408a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 8418a650c75SVaclav Hapla } 8422e745bdaSMatthew G. Knepley } 843d89e6e46SMatthew G. Knepley for (c = coneSize; c < 4; c++) { 844d89e6e46SMatthew G. Knepley roots[p][c] = -1; 845d89e6e46SMatthew G. Knepley rootsRanks[p][c] = -1; 846d89e6e46SMatthew G. Knepley } 8472e745bdaSMatthew G. Knepley } 8489e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 849d89e6e46SMatthew G. Knepley PetscInt c; 850d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 8518ccb905dSVaclav Hapla leaves[p][c] = -2; 8528ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 8538ccb905dSVaclav Hapla } 854c8148b97SVaclav Hapla } 8559566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 8569566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 8579566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 8589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 859d89e6e46SMatthew G. Knepley if (debug) { 8609566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 861c5853193SPierre Jolivet if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n")); 862d89e6e46SMatthew G. Knepley } 8639566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL)); 8649e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 865d89e6e46SMatthew G. Knepley DMPolytopeType ct; 866d89e6e46SMatthew G. Knepley const PetscInt *cone; 867d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0, o; 868d89e6e46SMatthew G. Knepley 869d89e6e46SMatthew G. Knepley if (leaves[p][0] < 0) continue; /* Ignore vertices */ 8709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 8719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 8729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 873d89e6e46SMatthew G. Knepley if (debug) { 8749371c9d4SSatish 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])); 875d89e6e46SMatthew G. Knepley } 8769371c9d4SSatish 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]) { 877d89e6e46SMatthew G. Knepley /* Translate these leaves to my cone points; mainCone means desired order p's cone points */ 878d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); ++c) { 879d89e6e46SMatthew G. Knepley PetscInt rS, rN; 880d89e6e46SMatthew G. Knepley 88127d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 882d89e6e46SMatthew G. Knepley /* A local leaf is just taken as it is */ 8839dddd249SSatish Balay mainCone[c] = leaves[p][c]; 88427d0e99aSVaclav Hapla continue; 88527d0e99aSVaclav Hapla } 886f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 887f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 8889566063dSJacob Faibussowitsch PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r)); 88963a3b9bcSJacob 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]); 8901dca8a05SBarry 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]); 891f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 892d89e6e46SMatthew G. Knepley rS = roffset[r]; 893d89e6e46SMatthew G. Knepley rN = roffset[r + 1] - rS; 8949566063dSJacob Faibussowitsch PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0)); 89563a3b9bcSJacob 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]); 896f80536cbSVaclav Hapla /* Get the corresponding local point */ 8975f80ce2aSJacob Faibussowitsch mainCone[c] = rmine1[rS + ind0]; 898f80536cbSVaclav Hapla } 89963a3b9bcSJacob 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])); 90027d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 9019566063dSJacob Faibussowitsch PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o)); 9029566063dSJacob Faibussowitsch PetscCall(DMPlexOrientPoint(dm, p, o)); 9039566063dSJacob Faibussowitsch } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n")); 90423aaf07bSVaclav Hapla } 90527d0e99aSVaclav Hapla if (debug) { 9069566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 9079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 9082e745bdaSMatthew G. Knepley } 9099566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view")); 9109566063dSJacob Faibussowitsch PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks)); 9119566063dSJacob Faibussowitsch PetscCall(PetscFree2(rmine1, rremote1)); 9123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9132e745bdaSMatthew G. Knepley } 9142e745bdaSMatthew G. Knepley 915d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[]) 916d71ae5a4SJacob Faibussowitsch { 9172e72742cSMatthew G. Knepley PetscInt idx; 9182e72742cSMatthew G. Knepley PetscMPIInt rank; 9192e72742cSMatthew G. Knepley PetscBool flg; 9207bffde78SMichael Lange 9217bffde78SMichael Lange PetscFunctionBegin; 9229566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg)); 9233ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 9249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 9259566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 92663a3b9bcSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx])); 9279566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 9283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9292e72742cSMatthew G. Knepley } 9302e72742cSMatthew G. Knepley 931d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) 932d71ae5a4SJacob Faibussowitsch { 9332e72742cSMatthew G. Knepley PetscInt idx; 9342e72742cSMatthew G. Knepley PetscMPIInt rank; 9352e72742cSMatthew G. Knepley PetscBool flg; 9362e72742cSMatthew G. Knepley 9372e72742cSMatthew G. Knepley PetscFunctionBegin; 9389566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg)); 9393ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 9409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 9419566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 9422e72742cSMatthew G. Knepley if (idxname) { 94363a3b9bcSJacob 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)); 9442e72742cSMatthew G. Knepley } else { 94563a3b9bcSJacob 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)); 9462e72742cSMatthew G. Knepley } 9479566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 9483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9492e72742cSMatthew G. Knepley } 9502e72742cSMatthew G. Knepley 951d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed) 952d71ae5a4SJacob Faibussowitsch { 9533be36e83SMatthew G. Knepley PetscSF sf; 9543be36e83SMatthew G. Knepley const PetscInt *locals; 9553be36e83SMatthew G. Knepley PetscMPIInt rank; 9562e72742cSMatthew G. Knepley 9572e72742cSMatthew G. Knepley PetscFunctionBegin; 9589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9599566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9609566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL)); 9615f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 9622e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 9632e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 9642e72742cSMatthew G. Knepley } else { 9652e72742cSMatthew G. Knepley PetscHashIJKey key; 9663be36e83SMatthew G. Knepley PetscInt l; 9672e72742cSMatthew G. Knepley 9682e72742cSMatthew G. Knepley key.i = remotePoint.index; 9692e72742cSMatthew G. Knepley key.j = remotePoint.rank; 9709566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(remotehash, key, &l)); 9713be36e83SMatthew G. Knepley if (l >= 0) { 9723be36e83SMatthew G. Knepley *localPoint = locals[l]; 9735f80ce2aSJacob Faibussowitsch } else if (mapFailed) *mapFailed = PETSC_TRUE; 9742e72742cSMatthew G. Knepley } 9753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9762e72742cSMatthew G. Knepley } 9772e72742cSMatthew G. Knepley 978d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed) 979d71ae5a4SJacob Faibussowitsch { 9803be36e83SMatthew G. Knepley PetscSF sf; 9813be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 9823be36e83SMatthew G. Knepley const PetscSFNode *remotes; 9833be36e83SMatthew G. Knepley PetscInt Nl, l; 9843be36e83SMatthew G. Knepley PetscMPIInt rank; 9853be36e83SMatthew G. Knepley 9863be36e83SMatthew G. Knepley PetscFunctionBegin; 9875f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 9889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9899566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9909566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes)); 9913be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 9929566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 9939566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 9943be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 9959566063dSJacob Faibussowitsch PetscCall(PetscFindInt(localPoint, Nl, locals, &l)); 9969371c9d4SSatish Balay if (l < 0) { 9979371c9d4SSatish Balay if (mapFailed) *mapFailed = PETSC_TRUE; 9989371c9d4SSatish Balay } else *remotePoint = remotes[l]; 9993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10003be36e83SMatthew G. Knepley owned: 10013be36e83SMatthew G. Knepley remotePoint->rank = rank; 10023be36e83SMatthew G. Knepley remotePoint->index = localPoint; 10033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10043be36e83SMatthew G. Knepley } 10053be36e83SMatthew G. Knepley 1006d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) 1007d71ae5a4SJacob Faibussowitsch { 10083be36e83SMatthew G. Knepley PetscSF sf; 10093be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 10103be36e83SMatthew G. Knepley PetscInt Nl, idx; 10113be36e83SMatthew G. Knepley 10123be36e83SMatthew G. Knepley PetscFunctionBegin; 10133be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 10149566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10159566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL)); 10163ba16761SJacob Faibussowitsch if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS); 10179566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, Nl, locals, &idx)); 10189371c9d4SSatish Balay if (idx >= 0) { 10199371c9d4SSatish Balay *isShared = PETSC_TRUE; 10203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10219371c9d4SSatish Balay } 10229566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 10239566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 10243be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 10253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10263be36e83SMatthew G. Knepley } 10273be36e83SMatthew G. Knepley 1028d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) 1029d71ae5a4SJacob Faibussowitsch { 10303be36e83SMatthew G. Knepley const PetscInt *cone; 10313be36e83SMatthew G. Knepley PetscInt coneSize, c; 10323be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 10333be36e83SMatthew G. Knepley 10343be36e83SMatthew G. Knepley PetscFunctionBegin; 10359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 10369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 10373be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10383be36e83SMatthew G. Knepley PetscBool pointShared; 10393be36e83SMatthew G. Knepley 10409566063dSJacob Faibussowitsch PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared)); 10413be36e83SMatthew G. Knepley cShared = (PetscBool)(cShared && pointShared); 10423be36e83SMatthew G. Knepley } 10433be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 10443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10453be36e83SMatthew G. Knepley } 10463be36e83SMatthew G. Knepley 1047d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) 1048d71ae5a4SJacob Faibussowitsch { 10493be36e83SMatthew G. Knepley const PetscInt *cone; 10503be36e83SMatthew G. Knepley PetscInt coneSize, c; 10513be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 10523be36e83SMatthew G. Knepley 10533be36e83SMatthew G. Knepley PetscFunctionBegin; 10549566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 10559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 10563be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10573be36e83SMatthew G. Knepley PetscSFNode rcp; 10585f80ce2aSJacob Faibussowitsch PetscBool mapFailed; 10593be36e83SMatthew G. Knepley 10609566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed)); 10615f80ce2aSJacob Faibussowitsch if (mapFailed) { 10623be36e83SMatthew G. Knepley cmin = missing; 10633be36e83SMatthew G. Knepley } else { 10643be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 10653be36e83SMatthew G. Knepley } 10663be36e83SMatthew G. Knepley } 10673be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 10683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10693be36e83SMatthew G. Knepley } 10703be36e83SMatthew G. Knepley 10713be36e83SMatthew G. Knepley /* 10723be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 10733be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 10743be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 10753be36e83SMatthew G. Knepley */ 1076d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) 1077d71ae5a4SJacob Faibussowitsch { 10783be36e83SMatthew G. Knepley MPI_Comm comm; 10793be36e83SMatthew G. Knepley const PetscInt *support; 1080cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height; 10813be36e83SMatthew G. Knepley PetscMPIInt rank; 10823be36e83SMatthew G. Knepley 10833be36e83SMatthew G. Knepley PetscFunctionBegin; 10849566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 10859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10869566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap)); 10879566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 10889566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointHeight(dm, p, &height)); 1089cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight + 1) { 1090cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */ 109163a3b9bcSJacob 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)); 10923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1093cf4dc471SVaclav Hapla } 10949566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 10959566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 10969566063dSJacob Faibussowitsch if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off)); 10973be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 10983be36e83SMatthew G. Knepley const PetscInt face = support[s]; 10993be36e83SMatthew G. Knepley const PetscInt *cone; 11003be36e83SMatthew G. Knepley PetscSFNode cpmin = {-1, -1}, rp = {-1, -1}; 11013be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 11023be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 11033be36e83SMatthew G. Knepley PetscHashIJKey key; 11043be36e83SMatthew G. Knepley 11053be36e83SMatthew G. Knepley /* Only add point once */ 110663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Support face %" PetscInt_FMT "\n", rank, face)); 11073be36e83SMatthew G. Knepley key.i = p; 11083be36e83SMatthew G. Knepley key.j = face; 11099566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(faceHash, key, &f)); 11103be36e83SMatthew G. Knepley if (f >= 0) continue; 11119566063dSJacob Faibussowitsch PetscCall(DMPlexConeIsShared(dm, face, &isShared)); 11129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin)); 11139566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL)); 11143be36e83SMatthew G. Knepley if (debug) { 111563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared)); 111663a3b9bcSJacob 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)); 11173be36e83SMatthew G. Knepley } 11183be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 11199566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p)); 11203be36e83SMatthew G. Knepley if (candidates) { 112163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d] ", rank, face, idx, rank)); 11229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize)); 11239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, face, &cone)); 11243be36e83SMatthew G. Knepley candidates[off + idx].rank = -1; 11253be36e83SMatthew G. Knepley candidates[off + idx++].index = coneSize - 1; 11263be36e83SMatthew G. Knepley candidates[off + idx].rank = rank; 11273be36e83SMatthew G. Knepley candidates[off + idx++].index = face; 11283be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 11293be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 11303be36e83SMatthew G. Knepley 11313be36e83SMatthew G. Knepley if (cp == p) continue; 11329566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL)); 113363a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index)); 11343be36e83SMatthew G. Knepley ++idx; 11353be36e83SMatthew G. Knepley } 11369566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n")); 11373be36e83SMatthew G. Knepley } else { 11383be36e83SMatthew G. Knepley /* Add cone size to section */ 113963a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %" PetscInt_FMT "\n", rank, face)); 11409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize)); 11419566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p)); 11429566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1)); 11433be36e83SMatthew G. Knepley } 11443be36e83SMatthew G. Knepley } 11453be36e83SMatthew G. Knepley } 11463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11473be36e83SMatthew G. Knepley } 11483be36e83SMatthew G. Knepley 11492e72742cSMatthew G. Knepley /*@ 115020f4b53cSBarry Smith DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation 11512e72742cSMatthew G. Knepley 115220f4b53cSBarry Smith Collective 11532e72742cSMatthew G. Knepley 11542e72742cSMatthew G. Knepley Input Parameters: 115520f4b53cSBarry Smith + dm - The interpolated `DMPLEX` 115620f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points 11572e72742cSMatthew G. Knepley 1158f0cfc026SVaclav Hapla Level: developer 11592e72742cSMatthew G. Knepley 116020f4b53cSBarry Smith Note: 116120f4b53cSBarry 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` 11622e72742cSMatthew G. Knepley 116320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()` 11642e72742cSMatthew G. Knepley @*/ 1165d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 1166d71ae5a4SJacob Faibussowitsch { 11673be36e83SMatthew G. Knepley MPI_Comm comm; 11683be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 11693be36e83SMatthew G. Knepley PetscHMapI claimshash; 11703be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 11713be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 11722e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 11732e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 11743be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 11753be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 11763be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 1177f0cfc026SVaclav Hapla PetscMPIInt rank; 11782e72742cSMatthew G. Knepley 11792e72742cSMatthew G. Knepley PetscFunctionBegin; 1180f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1181064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 11829566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &flg)); 11833ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 11843be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 11859566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 11869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11889566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &ov)); 118928b400f6SJacob Faibussowitsch PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 11909566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug)); 11919566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view")); 11929566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view")); 11939566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0)); 11943be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 11959566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints)); 119608401ef6SPierre Jolivet PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 11979566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&remoteHash)); 11983be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11993be36e83SMatthew G. Knepley PetscHashIJKey key; 12002e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 12012e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 12029566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(remoteHash, key, l)); 12037bffde78SMichael Lange } 120466aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 12059566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 12069566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 12079566063dSJacob Faibussowitsch PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree)); 12083be36e83SMatthew G. Knepley /* 12093be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 12103be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 12113be36e83SMatthew G. Knepley \begin{itemize} 12123be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 12133be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 12143be36e83SMatthew G. Knepley \end{itemize} 12153be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 12163be36e83SMatthew 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 12173be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 12183be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 12193be36e83SMatthew G. Knepley */ 12203be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 12213be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 1222da81f932SPierre Jolivet The array holds candidate shared faces, each face is referred to by the leaf point */ 12239566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateSection)); 12249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(candidateSection, 0, Nr)); 12257bffde78SMichael Lange { 12263be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 12272e72742cSMatthew G. Knepley 12289566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&faceHash)); 12293be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 12303be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 12312e72742cSMatthew G. Knepley 123263a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %" PetscInt_FMT "\n", rank, p)); 12339566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug)); 12342e72742cSMatthew G. Knepley } 12359566063dSJacob Faibussowitsch PetscCall(PetscHMapIJClear(faceHash)); 12369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(candidateSection)); 12379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize)); 12389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesSize, &candidates)); 12393be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 12403be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 12412e72742cSMatthew G. Knepley 124263a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %" PetscInt_FMT "\n", rank, p)); 12439566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug)); 12442e72742cSMatthew G. Knepley } 12459566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&faceHash)); 12469566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 12477bffde78SMichael Lange } 12489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section")); 12499566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view")); 12509566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates)); 12513be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 12522e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 12537bffde78SMichael Lange { 12547bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 12557bffde78SMichael Lange PetscInt *remoteOffsets; 12562e72742cSMatthew G. Knepley 12579566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti)); 12589566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse)); 12599566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateRemoteSection)); 12609566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection)); 12619566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates)); 12629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize)); 12639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote)); 12649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE)); 12659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE)); 12669566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfInverse)); 12679566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfCandidates)); 12689566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 12692e72742cSMatthew G. Knepley 12709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section")); 12719566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view")); 12729566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote)); 12737bffde78SMichael Lange } 12743be36e83SMatthew 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 */ 12757bffde78SMichael Lange { 1276a03d55ffSStefano Zampini PetscHMapIJKLRemote faceTable; 12773be36e83SMatthew G. Knepley PetscInt idx, idx2; 12783be36e83SMatthew G. Knepley 1279a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteCreate(&faceTable)); 12802e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 12813be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 12822e72742cSMatthew G. Knepley PetscInt deg; 12833be36e83SMatthew G. Knepley 12842e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 12852e72742cSMatthew G. Knepley PetscInt offset, dof, d; 12862e72742cSMatthew G. Knepley 12879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof)); 12889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset)); 12893be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 12902e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12913be36e83SMatthew G. Knepley const PetscInt hidx = offset + d; 12923be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1; 12933be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx + 1]; 12943be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2]; 12953be36e83SMatthew G. Knepley PetscSFNode fcp0; 12963be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 12972e72742cSMatthew G. Knepley const PetscInt *join = NULL; 1298a03d55ffSStefano Zampini PetscHMapIJKLRemoteKey key; 12993be36e83SMatthew G. Knepley PetscHashIter iter; 13005f80ce2aSJacob Faibussowitsch PetscBool missing, mapToLocalPointFailed = PETSC_FALSE; 13012e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 13022e72742cSMatthew G. Knepley 13039371c9d4SSatish Balay if (debug) 13049371c9d4SSatish 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, 13059371c9d4SSatish Balay rface.index, r, idx, d, Np)); 130663a3b9bcSJacob 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); 13073be36e83SMatthew G. Knepley fcp0.rank = rank; 13083be36e83SMatthew G. Knepley fcp0.index = r; 13093be36e83SMatthew G. Knepley d += Np; 13103be36e83SMatthew G. Knepley /* Put remote face in hash table */ 13113be36e83SMatthew G. Knepley key.i = fcp0; 13123be36e83SMatthew G. Knepley key.j = fcone[0]; 13133be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 13143be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 13159566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key)); 1316a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing)); 13173be36e83SMatthew G. Knepley if (missing) { 131863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank)); 1319a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface)); 13203be36e83SMatthew G. Knepley } else { 13213be36e83SMatthew G. Knepley PetscSFNode oface; 13223be36e83SMatthew G. Knepley 1323a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface)); 13243be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 132563a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank)); 1326a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, rface)); 13273be36e83SMatthew G. Knepley } 13283be36e83SMatthew G. Knepley } 13293be36e83SMatthew G. Knepley /* Check for local face */ 13302e72742cSMatthew G. Knepley points[0] = r; 13313be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 13329566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed)); 13335f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) break; /* We got a point not in our overlap */ 133463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Checking local candidate %" PetscInt_FMT "\n", rank, points[p])); 13357bffde78SMichael Lange } 13365f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) continue; 13379566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join)); 13387bffde78SMichael Lange if (joinSize == 1) { 13393be36e83SMatthew G. Knepley PetscSFNode lface; 13403be36e83SMatthew G. Knepley PetscSFNode oface; 13413be36e83SMatthew G. Knepley 13423be36e83SMatthew G. Knepley /* Always replace with local face */ 13433be36e83SMatthew G. Knepley lface.rank = rank; 13443be36e83SMatthew G. Knepley lface.index = join[0]; 1345a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &oface)); 13469371c9d4SSatish Balay if (debug) 13479371c9d4SSatish 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)); 1348a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterSet(faceTable, iter, lface)); 13497bffde78SMichael Lange } 13509566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join)); 13513be36e83SMatthew G. Knepley } 13523be36e83SMatthew G. Knepley } 13533be36e83SMatthew G. Knepley /* Put back faces for this root */ 13543be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 13553be36e83SMatthew G. Knepley PetscInt offset, dof, d; 13563be36e83SMatthew G. Knepley 13579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof)); 13589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset)); 13593be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 13603be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 13613be36e83SMatthew G. Knepley const PetscInt hidx = offset + d; 13623be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1; 13633be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2]; 13643be36e83SMatthew G. Knepley PetscSFNode fcp0; 13653be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 1366a03d55ffSStefano Zampini PetscHMapIJKLRemoteKey key; 13673be36e83SMatthew G. Knepley PetscHashIter iter; 13683be36e83SMatthew G. Knepley PetscBool missing; 13693be36e83SMatthew G. Knepley 137063a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx)); 137163a3b9bcSJacob Faibussowitsch PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np); 13723be36e83SMatthew G. Knepley fcp0.rank = rank; 13733be36e83SMatthew G. Knepley fcp0.index = r; 13743be36e83SMatthew G. Knepley d += Np; 13753be36e83SMatthew G. Knepley /* Find remote face in hash table */ 13763be36e83SMatthew G. Knepley key.i = fcp0; 13773be36e83SMatthew G. Knepley key.j = fcone[0]; 13783be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 13793be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 13809566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key)); 13819371c9d4SSatish Balay if (debug) 13829371c9d4SSatish 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, 13839371c9d4SSatish 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)); 1384a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemotePut(faceTable, key, &iter, &missing)); 138563a3b9bcSJacob Faibussowitsch PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2); 1386a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx])); 13877bffde78SMichael Lange } 13887bffde78SMichael Lange } 13897bffde78SMichael Lange } 13909566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL)); 1391a03d55ffSStefano Zampini PetscCall(PetscHMapIJKLRemoteDestroy(&faceTable)); 13927bffde78SMichael Lange } 13933be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 13947bffde78SMichael Lange { 13957bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 13967bffde78SMichael Lange PetscSFNode *remotePointsNew; 13972e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 13983be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 13992e72742cSMatthew G. Knepley 14003be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 14019566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti)); 14029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &claimSection)); 14039566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection)); 14049566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims)); 14059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize)); 14069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(claimsSize, &claims)); 14073be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 14089566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE)); 14099566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE)); 14109566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfClaims)); 14119566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 14129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section")); 14139566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view")); 14149566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims)); 14153be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 14163be36e83SMatthew 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 */ 14179566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&claimshash)); 14183be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 14193be36e83SMatthew G. Knepley PetscInt dof, off, d; 14202e72742cSMatthew G. Knepley 142163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %" PetscInt_FMT "\n", rank, r)); 14229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateSection, r, &dof)); 14239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateSection, r, &off)); 14242e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 14253be36e83SMatthew G. Knepley if (claims[off + d].rank >= 0) { 14263be36e83SMatthew G. Knepley const PetscInt faceInd = off + d; 14273be36e83SMatthew G. Knepley const PetscInt Np = candidates[off + d].index; 14282e72742cSMatthew G. Knepley const PetscInt *join = NULL; 14292e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 14302e72742cSMatthew G. Knepley 143163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index)); 14323be36e83SMatthew G. Knepley points[0] = r; 143363a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[0])); 14343be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 14359566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL)); 143663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[c + 1])); 14372e72742cSMatthew G. Knepley } 14389566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join)); 14392e72742cSMatthew G. Knepley if (joinSize == 1) { 14403be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 144163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0])); 14423be36e83SMatthew G. Knepley } else { 144363a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found local face %" PetscInt_FMT "\n", rank, join[0])); 14449566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(claimshash, join[0], faceInd)); 14452e72742cSMatthew G. Knepley } 14463be36e83SMatthew G. Knepley } else { 14479566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank)); 14483be36e83SMatthew G. Knepley } 14499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join)); 14503be36e83SMatthew G. Knepley } else { 145163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] No claim for point %" PetscInt_FMT "\n", rank, r)); 14523be36e83SMatthew G. Knepley d += claims[off + d].index + 1; 14537bffde78SMichael Lange } 14547bffde78SMichael Lange } 14553be36e83SMatthew G. Knepley } 14569566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 14573be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 14589566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(claimshash, &NlNew)); 14599566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew)); 14619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew)); 14623be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 14633be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 14643be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 14653be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 14667bffde78SMichael Lange } 14673be36e83SMatthew G. Knepley p = Nl; 14689566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew)); 14693be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 14708e3a54c0SPierre Jolivet PetscCall(PetscSortInt(NlNew, PetscSafePointerPlusOffset(localPointsNew, Nl))); 14713be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 14723be36e83SMatthew G. Knepley PetscInt off; 14739566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off)); 14741dca8a05SBarry 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); 14753be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 14767bffde78SMichael Lange } 14779566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfPointNew)); 14789566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 14799566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfPointNew)); 14809566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPointNew)); 14819566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view")); 1482d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE)); 14839566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPointNew)); 14849566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&claimshash)); 14857bffde78SMichael Lange } 14869566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&remoteHash)); 14879566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateSection)); 14889566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateRemoteSection)); 14899566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&claimSection)); 14909566063dSJacob Faibussowitsch PetscCall(PetscFree(candidates)); 14919566063dSJacob Faibussowitsch PetscCall(PetscFree(candidatesRemote)); 14929566063dSJacob Faibussowitsch PetscCall(PetscFree(claims)); 14939566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0)); 14943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14957bffde78SMichael Lange } 14967bffde78SMichael Lange 1497248eb259SVaclav Hapla /*@ 149880330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 149980330477SMatthew G. Knepley 150020f4b53cSBarry Smith Collective 150180330477SMatthew G. Knepley 150220f4b53cSBarry Smith Input Parameter: 150320f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices 150480330477SMatthew G. Knepley 150580330477SMatthew G. Knepley Output Parameter: 150620f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object 150780330477SMatthew G. Knepley 150880330477SMatthew G. Knepley Level: intermediate 150980330477SMatthew G. Knepley 151020f4b53cSBarry Smith Note: 15117fb59074SVaclav Hapla Labels and coordinates are copied. 151243eeeb2dSStefano Zampini 151360225df5SJacob Faibussowitsch Developer Notes: 151420f4b53cSBarry Smith It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`. 15159ade3219SVaclav Hapla 151620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()` 151780330477SMatthew G. Knepley @*/ 1518d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 1519d71ae5a4SJacob Faibussowitsch { 1520a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 15219a5b13a2SMatthew G Knepley DM idm, odm = dm; 15227bffde78SMichael Lange PetscSF sfPoint; 15232e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 152410a67516SMatthew G. Knepley const char *name; 1525b325530aSVaclav Hapla PetscBool flg = PETSC_TRUE; 15269f074e33SMatthew G Knepley 15279f074e33SMatthew G Knepley PetscFunctionBegin; 152810a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15294f572ea9SToby Isaac PetscAssertPointer(dmInt, 2); 15309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0)); 15319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 15329566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15339566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 153408401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1535827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 15369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 153776b791aaSMatthew G. Knepley idm = dm; 1538b21b8912SMatthew G. Knepley } else { 1539*5c2c0cecSMatthew G. Knepley PetscBool nonmanifold = PETSC_FALSE; 1540*5c2c0cecSMatthew G. Knepley 1541*5c2c0cecSMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &nonmanifold, NULL)); 1542*5c2c0cecSMatthew G. Knepley if (nonmanifold) { 1543*5c2c0cecSMatthew G. Knepley do { 1544*5c2c0cecSMatthew G. Knepley const char *prefix; 1545*5c2c0cecSMatthew G. Knepley PetscInt pStart, pEnd, pdepth; 1546*5c2c0cecSMatthew G. Knepley PetscBool done = PETSC_TRUE; 1547*5c2c0cecSMatthew G. Knepley 1548*5c2c0cecSMatthew G. Knepley // Find a point which is not correctly interpolated 1549*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetChart(odm, &pStart, &pEnd)); 1550*5c2c0cecSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 1551*5c2c0cecSMatthew G. Knepley DMPolytopeType ct; 1552*5c2c0cecSMatthew G. Knepley const PetscInt *cone; 1553*5c2c0cecSMatthew G. Knepley PetscInt coneSize, cdepth; 1554*5c2c0cecSMatthew G. Knepley 1555*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(odm, p, &pdepth)); 1556*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetCellType(odm, p, &ct)); 1557*5c2c0cecSMatthew G. Knepley // Check against celltype 1558*5c2c0cecSMatthew G. Knepley if (pdepth != DMPolytopeTypeGetDim(ct)) { 1559*5c2c0cecSMatthew G. Knepley done = PETSC_FALSE; 1560*5c2c0cecSMatthew G. Knepley break; 1561*5c2c0cecSMatthew G. Knepley } 1562*5c2c0cecSMatthew G. Knepley // Check against boundary 1563*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetCone(odm, p, &cone)); 1564*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetConeSize(odm, p, &coneSize)); 1565*5c2c0cecSMatthew G. Knepley for (PetscInt c = 0; c < coneSize; ++c) { 1566*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(odm, cone[c], &cdepth)); 1567*5c2c0cecSMatthew G. Knepley if (cdepth != pdepth - 1) { 1568*5c2c0cecSMatthew G. Knepley done = PETSC_FALSE; 1569*5c2c0cecSMatthew G. Knepley p = pEnd; 1570*5c2c0cecSMatthew G. Knepley break; 1571*5c2c0cecSMatthew G. Knepley } 1572*5c2c0cecSMatthew G. Knepley } 1573*5c2c0cecSMatthew G. Knepley } 1574*5c2c0cecSMatthew G. Knepley if (done) break; 1575*5c2c0cecSMatthew G. Knepley /* Create interpolated mesh */ 1576*5c2c0cecSMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm)); 1577*5c2c0cecSMatthew G. Knepley PetscCall(DMSetType(idm, DMPLEX)); 1578*5c2c0cecSMatthew G. Knepley PetscCall(DMSetDimension(idm, dim)); 1579*5c2c0cecSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 1580*5c2c0cecSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix)); 1581*5c2c0cecSMatthew G. Knepley if (depth > 0) { 1582*5c2c0cecSMatthew G. Knepley PetscCall(DMPlexInterpolateFaces_Internal(odm, pdepth, idm)); 1583*5c2c0cecSMatthew G. Knepley PetscCall(DMGetPointSF(odm, &sfPoint)); 1584*5c2c0cecSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE)); 1585*5c2c0cecSMatthew G. Knepley { 1586*5c2c0cecSMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 1587*5c2c0cecSMatthew G. Knepley PetscInt nroots; 1588*5c2c0cecSMatthew G. Knepley PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 1589*5c2c0cecSMatthew G. Knepley if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint)); 1590*5c2c0cecSMatthew G. Knepley } 1591*5c2c0cecSMatthew G. Knepley } 1592*5c2c0cecSMatthew G. Knepley if (odm != dm) PetscCall(DMDestroy(&odm)); 1593*5c2c0cecSMatthew G. Knepley odm = idm; 1594*5c2c0cecSMatthew G. Knepley } while (1); 1595*5c2c0cecSMatthew G. Knepley } else { 15969a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 15976f5c9017SMatthew G. Knepley const char *prefix; 15986f5c9017SMatthew G. Knepley 15999a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 16009566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm)); 16019566063dSJacob Faibussowitsch PetscCall(DMSetType(idm, DMPLEX)); 16029566063dSJacob Faibussowitsch PetscCall(DMSetDimension(idm, dim)); 16036f5c9017SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 16046f5c9017SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)idm, prefix)); 16057bffde78SMichael Lange if (depth > 0) { 16069566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm)); 16079566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(odm, &sfPoint)); 1608d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE)); 160994488200SVaclav Hapla { 16103be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 161194488200SVaclav Hapla PetscInt nroots; 16129566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 16139566063dSJacob Faibussowitsch if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint)); 161494488200SVaclav Hapla } 16157bffde78SMichael Lange } 16169566063dSJacob Faibussowitsch if (odm != dm) PetscCall(DMDestroy(&odm)); 16179a5b13a2SMatthew G Knepley odm = idm; 16189f074e33SMatthew G Knepley } 1619*5c2c0cecSMatthew G. Knepley } 16209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 16219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)idm, name)); 16229566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 16239566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL)); 16249566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL)); 16259566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexOrientInterface_Internal(idm)); 162684699f70SSatish Balay } 1627827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1628827c4036SVaclav Hapla { 1629d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)idm->data; 1630827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1631827c4036SVaclav Hapla } 16325de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm)); 16339a5b13a2SMatthew G Knepley *dmInt = idm; 16349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0)); 16353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16369f074e33SMatthew G Knepley } 163707b0a1fcSMatthew G Knepley 163880330477SMatthew G. Knepley /*@ 163980330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 164080330477SMatthew G. Knepley 164120f4b53cSBarry Smith Collective 164280330477SMatthew G. Knepley 164380330477SMatthew G. Knepley Input Parameter: 164420f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates 164580330477SMatthew G. Knepley 164680330477SMatthew G. Knepley Output Parameter: 164720f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates 164880330477SMatthew G. Knepley 164980330477SMatthew G. Knepley Level: intermediate 165080330477SMatthew G. Knepley 16516f5c9017SMatthew G. Knepley Notes: 165220f4b53cSBarry Smith This is typically used when adding pieces other than vertices to a mesh 165380330477SMatthew G. Knepley 16546f5c9017SMatthew G. Knepley This function does not copy localized coordinates. 16556f5c9017SMatthew G. Knepley 165620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()` 165780330477SMatthew G. Knepley @*/ 1658d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 1659d71ae5a4SJacob Faibussowitsch { 166007b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 166143eeeb2dSStefano Zampini VecType vtype; 166207b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 166307b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 16640bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 166590a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 166607b0a1fcSMatthew G Knepley 166707b0a1fcSMatthew G Knepley PetscFunctionBegin; 166843eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 166943eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 16703ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS); 16719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &cdim)); 16729566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dmB, cdim)); 16739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA)); 16749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB)); 167563a3b9bcSJacob 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); 167661a622f3SMatthew G. Knepley /* Copy over discretization if it exists */ 167761a622f3SMatthew G. Knepley { 167861a622f3SMatthew G. Knepley DM cdmA, cdmB; 167961a622f3SMatthew G. Knepley PetscDS dsA, dsB; 168061a622f3SMatthew G. Knepley PetscObject objA, objB; 168161a622f3SMatthew G. Knepley PetscClassId idA, idB; 168261a622f3SMatthew G. Knepley const PetscScalar *constants; 168361a622f3SMatthew G. Knepley PetscInt cdim, Nc; 168461a622f3SMatthew G. Knepley 16859566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &cdmA)); 16869566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &cdmB)); 16879566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmA, 0, NULL, &objA)); 16889566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmB, 0, NULL, &objB)); 16899566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objA, &idA)); 16909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objB, &idB)); 169161a622f3SMatthew G. Knepley if ((idA == PETSCFE_CLASSID) && (idA != idB)) { 16929566063dSJacob Faibussowitsch PetscCall(DMSetField(cdmB, 0, NULL, objA)); 16939566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdmB)); 16949566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmA, &dsA)); 16959566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmB, &dsB)); 16969566063dSJacob Faibussowitsch PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim)); 16979566063dSJacob Faibussowitsch PetscCall(PetscDSSetCoordinateDimension(dsB, cdim)); 16989566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(dsA, &Nc, &constants)); 16999566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants)); 170061a622f3SMatthew G. Knepley } 170161a622f3SMatthew G. Knepley } 17029566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA)); 17039566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB)); 17049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmA, &coordSectionA)); 17059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmB, &coordSectionB)); 17063ba16761SJacob Faibussowitsch if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS); 17079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf)); 17083ba16761SJacob Faibussowitsch if (!Nf) PetscFunctionReturn(PETSC_SUCCESS); 170963a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf); 1710df26b574SMatthew G. Knepley if (!coordSectionB) { 1711df26b574SMatthew G. Knepley PetscInt dim; 1712df26b574SMatthew G. Knepley 17139566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB)); 17149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &dim)); 17159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB)); 17169566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordSectionB)); 1717df26b574SMatthew G. Knepley } 17189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSectionB, 1)); 17199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim)); 17209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim)); 17219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE)); 172243eeeb2dSStefano Zampini cS = vStartB; 172343eeeb2dSStefano Zampini cE = vEndB; 17249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSectionB, cS, cE)); 172507b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 17269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim)); 17279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim)); 172807b0a1fcSMatthew G Knepley } 17299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSectionB)); 17309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB)); 17319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA)); 17329566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB)); 17339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates")); 17349566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE)); 17359566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(coordinatesA, &d)); 17369566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinatesB, d)); 17379566063dSJacob Faibussowitsch PetscCall(VecGetType(coordinatesA, &vtype)); 17389566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinatesB, vtype)); 17399566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesA, &coordsA)); 17409566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesB, &coordsB)); 174107b0a1fcSMatthew G Knepley for (v = 0; v < vEndB - vStartB; ++v) { 174243eeeb2dSStefano Zampini PetscInt offA, offB; 174343eeeb2dSStefano Zampini 17449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA)); 17459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB)); 1746ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d]; 174743eeeb2dSStefano Zampini } 17489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesA, &coordsA)); 17499566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesB, &coordsB)); 17509566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB)); 17519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinatesB)); 17523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 175307b0a1fcSMatthew G Knepley } 17545c386225SMatthew G. Knepley 17554e3744c5SMatthew G. Knepley /*@ 17564e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 17574e3744c5SMatthew G. Knepley 175820f4b53cSBarry Smith Collective 17594e3744c5SMatthew G. Knepley 17604e3744c5SMatthew G. Knepley Input Parameter: 176120f4b53cSBarry Smith . dm - The complete `DMPLEX` object 17624e3744c5SMatthew G. Knepley 17634e3744c5SMatthew G. Knepley Output Parameter: 176420f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices 17654e3744c5SMatthew G. Knepley 17664e3744c5SMatthew G. Knepley Level: intermediate 17674e3744c5SMatthew G. Knepley 176820f4b53cSBarry Smith Note: 176995452b02SPatrick Sanan It does not copy over the coordinates. 177043eeeb2dSStefano Zampini 177160225df5SJacob Faibussowitsch Developer Notes: 177220f4b53cSBarry Smith Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`. 17739ade3219SVaclav Hapla 177420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()` 17754e3744c5SMatthew G. Knepley @*/ 1776d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 1777d71ae5a4SJacob Faibussowitsch { 1778827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 17794e3744c5SMatthew G. Knepley DM udm; 1780412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; 17814e3744c5SMatthew G. Knepley 17824e3744c5SMatthew G. Knepley PetscFunctionBegin; 178343eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17844f572ea9SToby Isaac PetscAssertPointer(dmUnint, 2); 1785172ee266SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Uninterpolate, dm, 0, 0, 0)); 17869566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 17879566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 178808401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1789827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1790827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 17919566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 1792595d4abbSMatthew G. Knepley *dmUnint = dm; 17933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17944e3744c5SMatthew G. Knepley } 17959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 17969566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 17979566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm)); 17989566063dSJacob Faibussowitsch PetscCall(DMSetType(udm, DMPLEX)); 17999566063dSJacob Faibussowitsch PetscCall(DMSetDimension(udm, dim)); 18009566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(udm, cStart, vEnd)); 18014e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1802595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 18034e3744c5SMatthew G. Knepley 18049566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 18054e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 18064e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 18074e3744c5SMatthew G. Knepley 18084e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 18094e3744c5SMatthew G. Knepley } 18109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 18119566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(udm, c, coneSize)); 1812595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 18134e3744c5SMatthew G. Knepley } 18149566063dSJacob Faibussowitsch PetscCall(DMSetUp(udm)); 18159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConeSize, &cone)); 18164e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1817595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 18184e3744c5SMatthew G. Knepley 18199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 18204e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 18214e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 18224e3744c5SMatthew G. Knepley 18234e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 18244e3744c5SMatthew G. Knepley } 18259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 18269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(udm, c, cone)); 18274e3744c5SMatthew G. Knepley } 18289566063dSJacob Faibussowitsch PetscCall(PetscFree(cone)); 18299566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(udm)); 18309566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(udm)); 18315c7de58aSMatthew G. Knepley /* Reduce SF */ 18325c7de58aSMatthew G. Knepley { 18335c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 18345c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 18355c7de58aSMatthew G. Knepley const PetscInt *localPoints; 18365c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 18375c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 183822fd0ad9SVaclav Hapla PetscInt numRoots, numLeaves, l; 18395c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 18405c7de58aSMatthew G. Knepley 18415c7de58aSMatthew G. Knepley /* Get original SF information */ 18429566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 1843d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE)); 18449566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(udm, &sfPointUn)); 18459566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 184622fd0ad9SVaclav Hapla if (numRoots >= 0) { 18475c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 184822fd0ad9SVaclav Hapla for (l = 0; l < numLeaves; ++l) { 184922fd0ad9SVaclav Hapla const PetscInt p = localPoints[l]; 185022fd0ad9SVaclav Hapla 185122fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++; 185222fd0ad9SVaclav Hapla } 18535c7de58aSMatthew G. Knepley /* Fill in leaves */ 18549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn)); 18559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn)); 18565c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 185722fd0ad9SVaclav Hapla const PetscInt p = localPoints[l]; 185822fd0ad9SVaclav Hapla 185922fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) { 186022fd0ad9SVaclav Hapla localPointsUn[n] = p; 18615c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 18625c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 18635c7de58aSMatthew G. Knepley ++n; 18645c7de58aSMatthew G. Knepley } 18655c7de58aSMatthew G. Knepley } 186663a3b9bcSJacob Faibussowitsch PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn); 186722fd0ad9SVaclav Hapla PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER)); 18685c7de58aSMatthew G. Knepley } 18695c7de58aSMatthew G. Knepley } 1870827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1871827c4036SVaclav Hapla { 1872d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)udm->data; 1873827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1874827c4036SVaclav Hapla } 18755de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm)); 1876d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE)); 18774e3744c5SMatthew G. Knepley *dmUnint = udm; 1878172ee266SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Uninterpolate, dm, 0, 0, 0)); 18793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18804e3744c5SMatthew G. Knepley } 1881a7748839SVaclav Hapla 1882d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1883d71ae5a4SJacob Faibussowitsch { 1884a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1885a7748839SVaclav Hapla MPI_Comm comm; 1886a7748839SVaclav Hapla 1887a7748839SVaclav Hapla PetscFunctionBegin; 18889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 18899566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 18909566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1891a7748839SVaclav Hapla 1892a7748839SVaclav Hapla if (depth == dim) { 1893a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1894a7748839SVaclav Hapla if (!dim) goto finish; 1895a7748839SVaclav Hapla 1896a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 18979566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd)); 1898a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) { 18999566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1900a7748839SVaclav Hapla if (coneSize) { 1901a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1902a7748839SVaclav Hapla goto finish; 1903a7748839SVaclav Hapla } 1904a7748839SVaclav Hapla } 1905a7748839SVaclav Hapla 1906a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1907a7748839SVaclav Hapla for (h = 0; h < dim; h++) { 19089566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 1909a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) { 19109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1911a7748839SVaclav Hapla if (!coneSize) { 1912a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1913a7748839SVaclav Hapla goto finish; 1914a7748839SVaclav Hapla } 1915a7748839SVaclav Hapla } 1916a7748839SVaclav Hapla } 1917a7748839SVaclav Hapla } else if (depth == 1) { 1918a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1919a7748839SVaclav Hapla } else { 1920a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1921a7748839SVaclav Hapla } 1922a7748839SVaclav Hapla finish: 19233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1924a7748839SVaclav Hapla } 1925a7748839SVaclav Hapla 1926a7748839SVaclav Hapla /*@ 192720f4b53cSBarry Smith DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated. 1928a7748839SVaclav Hapla 1929a7748839SVaclav Hapla Not Collective 1930a7748839SVaclav Hapla 1931a7748839SVaclav Hapla Input Parameter: 193220f4b53cSBarry Smith . dm - The `DMPLEX` object 1933a7748839SVaclav Hapla 1934a7748839SVaclav Hapla Output Parameter: 193520f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated 1936a7748839SVaclav Hapla 1937a7748839SVaclav Hapla Level: intermediate 1938a7748839SVaclav Hapla 1939a7748839SVaclav Hapla Notes: 194020f4b53cSBarry Smith Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective 19419ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 194220f4b53cSBarry Smith However, `DMPlexInterpolate()` guarantees the result is the same on all. 19439ade3219SVaclav Hapla 194420f4b53cSBarry Smith Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`. 1945a7748839SVaclav Hapla 19469ade3219SVaclav Hapla Developer Notes: 194720f4b53cSBarry Smith Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`. 19489ade3219SVaclav Hapla 194920f4b53cSBarry Smith If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called. 19509ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 195120f4b53cSBarry Smith `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`. 19529ade3219SVaclav Hapla 195320f4b53cSBarry Smith If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated. 19549ade3219SVaclav Hapla 195520f4b53cSBarry Smith `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`, 195620f4b53cSBarry Smith and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`. 19579ade3219SVaclav Hapla 195820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()` 1959a7748839SVaclav Hapla @*/ 1960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1961d71ae5a4SJacob Faibussowitsch { 1962a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data; 1963a7748839SVaclav Hapla 1964a7748839SVaclav Hapla PetscFunctionBegin; 1965a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19664f572ea9SToby Isaac PetscAssertPointer(interpolated, 2); 1967a7748839SVaclav Hapla if (plex->interpolated < 0) { 19689566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated)); 196976bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 1970a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1971a7748839SVaclav Hapla 19729566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &flg)); 1973c282ed06SStefano 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]); 1974a7748839SVaclav Hapla } 1975a7748839SVaclav Hapla *interpolated = plex->interpolated; 19763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1977a7748839SVaclav Hapla } 1978a7748839SVaclav Hapla 1979a7748839SVaclav Hapla /*@ 198020f4b53cSBarry Smith DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner). 1981a7748839SVaclav Hapla 19822666ff3cSVaclav Hapla Collective 1983a7748839SVaclav Hapla 1984a7748839SVaclav Hapla Input Parameter: 198520f4b53cSBarry Smith . dm - The `DMPLEX` object 1986a7748839SVaclav Hapla 1987a7748839SVaclav Hapla Output Parameter: 198820f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated 1989a7748839SVaclav Hapla 1990a7748839SVaclav Hapla Level: intermediate 1991a7748839SVaclav Hapla 1992a7748839SVaclav Hapla Notes: 199320f4b53cSBarry Smith Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks. 19949ade3219SVaclav Hapla 199520f4b53cSBarry Smith This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks. 19969ade3219SVaclav Hapla 19979ade3219SVaclav Hapla Developer Notes: 199820f4b53cSBarry Smith Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`. 19999ade3219SVaclav Hapla 200020f4b53cSBarry Smith If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated. 200120f4b53cSBarry Smith `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 200220f4b53cSBarry Smith if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`, 20039ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 20049ade3219SVaclav Hapla 200520f4b53cSBarry Smith If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective. 2006a7748839SVaclav Hapla 200720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()` 2008a7748839SVaclav Hapla @*/ 2009d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 2010d71ae5a4SJacob Faibussowitsch { 2011a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data; 2012a7748839SVaclav Hapla PetscBool debug = PETSC_FALSE; 2013a7748839SVaclav Hapla 2014a7748839SVaclav Hapla PetscFunctionBegin; 2015a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20164f572ea9SToby Isaac PetscAssertPointer(interpolated, 2); 20179566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL)); 2018a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 2019a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 2020a7748839SVaclav Hapla MPI_Comm comm; 2021a7748839SVaclav Hapla 20229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 20239566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective)); 2024712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm)); 2025712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm)); 2026a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 2027a7748839SVaclav Hapla if (debug) { 2028a7748839SVaclav Hapla PetscMPIInt rank; 2029a7748839SVaclav Hapla 20309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 20319566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective])); 20329566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 2033a7748839SVaclav Hapla } 2034a7748839SVaclav Hapla } 2035a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 20363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2037a7748839SVaclav Hapla } 2038