1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2e8f14785SLisandro Dalcin #include <petsc/private/hashmapi.h> 3e8f14785SLisandro Dalcin #include <petsc/private/hashmapij.h> 4e8f14785SLisandro Dalcin 5ea78f98cSLisandro Dalcin const char *const DMPlexInterpolatedFlags[] = {"none", "partial", "mixed", "full", "DMPlexInterpolatedFlag", "DMPLEX_INTERPOLATED_", NULL}; 6a7748839SVaclav Hapla 7e8f14785SLisandro Dalcin /* HashIJKL */ 8e8f14785SLisandro Dalcin 9e8f14785SLisandro Dalcin #include <petsc/private/hashmap.h> 10e8f14785SLisandro Dalcin 119371c9d4SSatish Balay typedef struct _PetscHashIJKLKey { 129371c9d4SSatish Balay PetscInt i, j, k, l; 139371c9d4SSatish Balay } PetscHashIJKLKey; 14e8f14785SLisandro Dalcin 159371c9d4SSatish Balay #define PetscHashIJKLKeyHash(key) PetscHashCombine(PetscHashCombine(PetscHashInt((key).i), PetscHashInt((key).j)), PetscHashCombine(PetscHashInt((key).k), PetscHashInt((key).l))) 16e8f14785SLisandro Dalcin 179371c9d4SSatish Balay #define PetscHashIJKLKeyEqual(k1, k2) (((k1).i == (k2).i) ? ((k1).j == (k2).j) ? ((k1).k == (k2).k) ? ((k1).l == (k2).l) : 0 : 0 : 0) 18e8f14785SLisandro Dalcin 19999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKL, PetscHashIJKLKey, PetscInt, PetscHashIJKLKeyHash, PetscHashIJKLKeyEqual, -1)) 20e8f14785SLisandro Dalcin 213be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1}; 223be36e83SMatthew G. Knepley 239371c9d4SSatish Balay typedef struct _PetscHashIJKLRemoteKey { 249371c9d4SSatish Balay PetscSFNode i, j, k, l; 259371c9d4SSatish Balay } PetscHashIJKLRemoteKey; 263be36e83SMatthew G. Knepley 273be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \ 289371c9d4SSatish Balay PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index), PetscHashInt((key).j.rank + (key).j.index)), PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index), PetscHashInt((key).l.rank + (key).l.index))) 293be36e83SMatthew G. Knepley 303be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyEqual(k1, k2) \ 313be36e83SMatthew G. Knepley (((k1).i.rank == (k2).i.rank) ? ((k1).i.index == (k2).i.index) ? ((k1).j.rank == (k2).j.rank) ? ((k1).j.index == (k2).j.index) ? ((k1).k.rank == (k2).k.rank) ? ((k1).k.index == (k2).k.index) ? ((k1).l.rank == (k2).l.rank) ? ((k1).l.index == (k2).l.index) : 0 : 0 : 0 : 0 : 0 : 0 : 0) 323be36e83SMatthew G. Knepley 33999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode)) 343be36e83SMatthew G. Knepley 35d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[]) 36d71ae5a4SJacob Faibussowitsch { 373be36e83SMatthew G. Knepley PetscInt i; 383be36e83SMatthew G. Knepley 393be36e83SMatthew G. Knepley PetscFunctionBegin; 403be36e83SMatthew G. Knepley for (i = 1; i < n; ++i) { 413be36e83SMatthew G. Knepley PetscSFNode x = A[i]; 423be36e83SMatthew G. Knepley PetscInt j; 433be36e83SMatthew G. Knepley 443be36e83SMatthew G. Knepley for (j = i - 1; j >= 0; --j) { 453be36e83SMatthew G. Knepley if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break; 463be36e83SMatthew G. Knepley A[j + 1] = A[j]; 473be36e83SMatthew G. Knepley } 483be36e83SMatthew G. Knepley A[j + 1] = x; 493be36e83SMatthew G. Knepley } 503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 513be36e83SMatthew G. Knepley } 529f074e33SMatthew G Knepley 539f074e33SMatthew G Knepley /* 54439ece16SMatthew G. Knepley DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone 55439ece16SMatthew G. Knepley */ 56d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) 57d71ae5a4SJacob Faibussowitsch { 58412e9a14SMatthew G. Knepley DMPolytopeType *typesTmp; 59412e9a14SMatthew G. Knepley PetscInt *sizesTmp, *facesTmp; 60439ece16SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 61439ece16SMatthew G. Knepley 62439ece16SMatthew G. Knepley PetscFunctionBegin; 63439ece16SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64ba2698f1SMatthew G. Knepley if (cone) PetscValidIntPointer(cone, 3); 659566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 669566063dSJacob Faibussowitsch if (faceTypes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &typesTmp)); 679566063dSJacob Faibussowitsch if (faceSizes) PetscCall(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &sizesTmp)); 689566063dSJacob Faibussowitsch if (faces) PetscCall(DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp)); 69ba2698f1SMatthew G. Knepley switch (ct) { 70ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 71ba2698f1SMatthew G. Knepley if (numFaces) *numFaces = 0; 72ba2698f1SMatthew G. Knepley break; 73ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 74412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 2; 75412e9a14SMatthew G. Knepley if (faceTypes) { 769371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_POINT; 779371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_POINT; 78412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 79412e9a14SMatthew G. Knepley } 80412e9a14SMatthew G. Knepley if (faceSizes) { 819371c9d4SSatish Balay sizesTmp[0] = 1; 829371c9d4SSatish Balay sizesTmp[1] = 1; 83412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 84412e9a14SMatthew G. Knepley } 85c49d9212SMatthew G. Knepley if (faces) { 869371c9d4SSatish Balay facesTmp[0] = cone[0]; 879371c9d4SSatish Balay facesTmp[1] = cone[1]; 88c49d9212SMatthew G. Knepley *faces = facesTmp; 89c49d9212SMatthew G. Knepley } 90412e9a14SMatthew G. Knepley break; 91412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 92c49d9212SMatthew G. Knepley if (numFaces) *numFaces = 2; 93412e9a14SMatthew G. Knepley if (faceTypes) { 949371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_POINT; 959371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_POINT; 96412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 97412e9a14SMatthew G. Knepley } 98412e9a14SMatthew G. Knepley if (faceSizes) { 999371c9d4SSatish Balay sizesTmp[0] = 1; 1009371c9d4SSatish Balay sizesTmp[1] = 1; 101412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 102412e9a14SMatthew G. Knepley } 103412e9a14SMatthew G. Knepley if (faces) { 1049371c9d4SSatish Balay facesTmp[0] = cone[0]; 1059371c9d4SSatish Balay facesTmp[1] = cone[1]; 106412e9a14SMatthew G. Knepley *faces = facesTmp; 107412e9a14SMatthew G. Knepley } 108c49d9212SMatthew G. Knepley break; 109ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 110412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 3; 111412e9a14SMatthew G. Knepley if (faceTypes) { 1129371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1139371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1149371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEGMENT; 115412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 116412e9a14SMatthew G. Knepley } 117412e9a14SMatthew G. Knepley if (faceSizes) { 1189371c9d4SSatish Balay sizesTmp[0] = 2; 1199371c9d4SSatish Balay sizesTmp[1] = 2; 1209371c9d4SSatish Balay sizesTmp[2] = 2; 121412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 122412e9a14SMatthew G. Knepley } 1239a5b13a2SMatthew G Knepley if (faces) { 1249371c9d4SSatish Balay facesTmp[0] = cone[0]; 1259371c9d4SSatish Balay facesTmp[1] = cone[1]; 1269371c9d4SSatish Balay facesTmp[2] = cone[1]; 1279371c9d4SSatish Balay facesTmp[3] = cone[2]; 1289371c9d4SSatish Balay facesTmp[4] = cone[2]; 1299371c9d4SSatish Balay facesTmp[5] = cone[0]; 1309a5b13a2SMatthew G Knepley *faces = facesTmp; 1319a5b13a2SMatthew G Knepley } 1329f074e33SMatthew G Knepley break; 133ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 1349a5b13a2SMatthew G Knepley /* Vertices follow right hand rule */ 135412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 136412e9a14SMatthew G. Knepley if (faceTypes) { 1379371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1389371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1399371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEGMENT; 1409371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEGMENT; 141412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 142412e9a14SMatthew G. Knepley } 143412e9a14SMatthew G. Knepley if (faceSizes) { 1449371c9d4SSatish Balay sizesTmp[0] = 2; 1459371c9d4SSatish Balay sizesTmp[1] = 2; 1469371c9d4SSatish Balay sizesTmp[2] = 2; 1479371c9d4SSatish Balay sizesTmp[3] = 2; 148412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 149412e9a14SMatthew G. Knepley } 1509a5b13a2SMatthew G Knepley if (faces) { 1519371c9d4SSatish Balay facesTmp[0] = cone[0]; 1529371c9d4SSatish Balay facesTmp[1] = cone[1]; 1539371c9d4SSatish Balay facesTmp[2] = cone[1]; 1549371c9d4SSatish Balay facesTmp[3] = cone[2]; 1559371c9d4SSatish Balay facesTmp[4] = cone[2]; 1569371c9d4SSatish Balay facesTmp[5] = cone[3]; 1579371c9d4SSatish Balay facesTmp[6] = cone[3]; 1589371c9d4SSatish Balay facesTmp[7] = cone[0]; 1599a5b13a2SMatthew G Knepley *faces = facesTmp; 1609a5b13a2SMatthew G Knepley } 161412e9a14SMatthew G. Knepley break; 162412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 1639a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 164412e9a14SMatthew G. Knepley if (faceTypes) { 1659371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_SEGMENT; 1669371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_SEGMENT; 1679371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1689371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR; 169412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 170412e9a14SMatthew G. Knepley } 171412e9a14SMatthew G. Knepley if (faceSizes) { 1729371c9d4SSatish Balay sizesTmp[0] = 2; 1739371c9d4SSatish Balay sizesTmp[1] = 2; 1749371c9d4SSatish Balay sizesTmp[2] = 2; 1759371c9d4SSatish Balay sizesTmp[3] = 2; 176412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 177412e9a14SMatthew G. Knepley } 178412e9a14SMatthew G. Knepley if (faces) { 1799371c9d4SSatish Balay facesTmp[0] = cone[0]; 1809371c9d4SSatish Balay facesTmp[1] = cone[1]; 1819371c9d4SSatish Balay facesTmp[2] = cone[2]; 1829371c9d4SSatish Balay facesTmp[3] = cone[3]; 1839371c9d4SSatish Balay facesTmp[4] = cone[0]; 1849371c9d4SSatish Balay facesTmp[5] = cone[2]; 1859371c9d4SSatish Balay facesTmp[6] = cone[1]; 1869371c9d4SSatish Balay facesTmp[7] = cone[3]; 187412e9a14SMatthew G. Knepley *faces = facesTmp; 188412e9a14SMatthew G. Knepley } 1899f074e33SMatthew G Knepley break; 190ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 1912e1b13c2SMatthew G. Knepley /* Vertices of first face follow right hand rule and normal points away from last vertex */ 192412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 193412e9a14SMatthew G. Knepley if (faceTypes) { 1949371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 1959371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 1969371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_TRIANGLE; 1979371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_TRIANGLE; 198412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 199412e9a14SMatthew G. Knepley } 200412e9a14SMatthew G. Knepley if (faceSizes) { 2019371c9d4SSatish Balay sizesTmp[0] = 3; 2029371c9d4SSatish Balay sizesTmp[1] = 3; 2039371c9d4SSatish Balay sizesTmp[2] = 3; 2049371c9d4SSatish Balay sizesTmp[3] = 3; 205412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 206412e9a14SMatthew G. Knepley } 2079a5b13a2SMatthew G Knepley if (faces) { 2089371c9d4SSatish Balay facesTmp[0] = cone[0]; 2099371c9d4SSatish Balay facesTmp[1] = cone[1]; 2109371c9d4SSatish Balay facesTmp[2] = cone[2]; 2119371c9d4SSatish Balay facesTmp[3] = cone[0]; 2129371c9d4SSatish Balay facesTmp[4] = cone[3]; 2139371c9d4SSatish Balay facesTmp[5] = cone[1]; 2149371c9d4SSatish Balay facesTmp[6] = cone[0]; 2159371c9d4SSatish Balay facesTmp[7] = cone[2]; 2169371c9d4SSatish Balay facesTmp[8] = cone[3]; 2179371c9d4SSatish Balay facesTmp[9] = cone[2]; 2189371c9d4SSatish Balay facesTmp[10] = cone[1]; 2199371c9d4SSatish Balay facesTmp[11] = cone[3]; 2209a5b13a2SMatthew G Knepley *faces = facesTmp; 2219a5b13a2SMatthew G Knepley } 2229a5b13a2SMatthew G Knepley break; 223ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 224e368ef20SMatthew G. Knepley /* 7--------6 225e368ef20SMatthew G. Knepley /| /| 226e368ef20SMatthew G. Knepley / | / | 227e368ef20SMatthew G. Knepley 4--------5 | 228e368ef20SMatthew G. Knepley | | | | 229e368ef20SMatthew G. Knepley | | | | 230e368ef20SMatthew G. Knepley | 1--------2 231e368ef20SMatthew G. Knepley | / | / 232e368ef20SMatthew G. Knepley |/ |/ 233e368ef20SMatthew G. Knepley 0--------3 234e368ef20SMatthew G. Knepley */ 235412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 236412e9a14SMatthew G. Knepley if (faceTypes) { 2379371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 2389371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; 2399371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; 2409371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; 2419371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; 2429371c9d4SSatish Balay typesTmp[5] = DM_POLYTOPE_QUADRILATERAL; 243412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 244412e9a14SMatthew G. Knepley } 245412e9a14SMatthew G. Knepley if (faceSizes) { 2469371c9d4SSatish Balay sizesTmp[0] = 4; 2479371c9d4SSatish Balay sizesTmp[1] = 4; 2489371c9d4SSatish Balay sizesTmp[2] = 4; 2499371c9d4SSatish Balay sizesTmp[3] = 4; 2509371c9d4SSatish Balay sizesTmp[4] = 4; 2519371c9d4SSatish Balay sizesTmp[5] = 4; 252412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 253412e9a14SMatthew G. Knepley } 2549a5b13a2SMatthew G Knepley if (faces) { 2559371c9d4SSatish Balay facesTmp[0] = cone[0]; 2569371c9d4SSatish Balay facesTmp[1] = cone[1]; 2579371c9d4SSatish Balay facesTmp[2] = cone[2]; 2589371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 2599371c9d4SSatish Balay facesTmp[4] = cone[4]; 2609371c9d4SSatish Balay facesTmp[5] = cone[5]; 2619371c9d4SSatish Balay facesTmp[6] = cone[6]; 2629371c9d4SSatish Balay facesTmp[7] = cone[7]; /* Top */ 2639371c9d4SSatish Balay facesTmp[8] = cone[0]; 2649371c9d4SSatish Balay facesTmp[9] = cone[3]; 2659371c9d4SSatish Balay facesTmp[10] = cone[5]; 2669371c9d4SSatish Balay facesTmp[11] = cone[4]; /* Front */ 2679371c9d4SSatish Balay facesTmp[12] = cone[2]; 2689371c9d4SSatish Balay facesTmp[13] = cone[1]; 2699371c9d4SSatish Balay facesTmp[14] = cone[7]; 2709371c9d4SSatish Balay facesTmp[15] = cone[6]; /* Back */ 2719371c9d4SSatish Balay facesTmp[16] = cone[3]; 2729371c9d4SSatish Balay facesTmp[17] = cone[2]; 2739371c9d4SSatish Balay facesTmp[18] = cone[6]; 2749371c9d4SSatish Balay facesTmp[19] = cone[5]; /* Right */ 2759371c9d4SSatish Balay facesTmp[20] = cone[0]; 2769371c9d4SSatish Balay facesTmp[21] = cone[4]; 2779371c9d4SSatish Balay facesTmp[22] = cone[7]; 2789371c9d4SSatish Balay facesTmp[23] = cone[1]; /* Left */ 2799a5b13a2SMatthew G Knepley *faces = facesTmp; 2809a5b13a2SMatthew G Knepley } 28199836e0eSStefano Zampini break; 282ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 283412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 284412e9a14SMatthew G. Knepley if (faceTypes) { 2859371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 2869371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 2879371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; 2889371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; 2899371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; 290412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 291412e9a14SMatthew G. Knepley } 292412e9a14SMatthew G. Knepley if (faceSizes) { 2939371c9d4SSatish Balay sizesTmp[0] = 3; 2949371c9d4SSatish Balay sizesTmp[1] = 3; 2959371c9d4SSatish Balay sizesTmp[2] = 4; 2969371c9d4SSatish Balay sizesTmp[3] = 4; 2979371c9d4SSatish Balay sizesTmp[4] = 4; 298412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 299412e9a14SMatthew G. Knepley } 300ba2698f1SMatthew G. Knepley if (faces) { 3019371c9d4SSatish Balay facesTmp[0] = cone[0]; 3029371c9d4SSatish Balay facesTmp[1] = cone[1]; 3039371c9d4SSatish Balay facesTmp[2] = cone[2]; /* Bottom */ 3049371c9d4SSatish Balay facesTmp[3] = cone[3]; 3059371c9d4SSatish Balay facesTmp[4] = cone[4]; 3069371c9d4SSatish Balay facesTmp[5] = cone[5]; /* Top */ 3079371c9d4SSatish Balay facesTmp[6] = cone[0]; 3089371c9d4SSatish Balay facesTmp[7] = cone[2]; 3099371c9d4SSatish Balay facesTmp[8] = cone[4]; 3109371c9d4SSatish Balay facesTmp[9] = cone[3]; /* Back left */ 3119371c9d4SSatish Balay facesTmp[10] = cone[2]; 3129371c9d4SSatish Balay facesTmp[11] = cone[1]; 3139371c9d4SSatish Balay facesTmp[12] = cone[5]; 3149371c9d4SSatish Balay facesTmp[13] = cone[4]; /* Front */ 3159371c9d4SSatish Balay facesTmp[14] = cone[1]; 3169371c9d4SSatish Balay facesTmp[15] = cone[0]; 3179371c9d4SSatish Balay facesTmp[16] = cone[3]; 3189371c9d4SSatish Balay facesTmp[17] = cone[5]; /* Back right */ 319ba2698f1SMatthew G. Knepley *faces = facesTmp; 32099836e0eSStefano Zampini } 32199836e0eSStefano Zampini break; 322ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 323412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 324412e9a14SMatthew G. Knepley if (faceTypes) { 3259371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_TRIANGLE; 3269371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 3279371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3289371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3299371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; 330412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 331412e9a14SMatthew G. Knepley } 332412e9a14SMatthew G. Knepley if (faceSizes) { 3339371c9d4SSatish Balay sizesTmp[0] = 3; 3349371c9d4SSatish Balay sizesTmp[1] = 3; 3359371c9d4SSatish Balay sizesTmp[2] = 4; 3369371c9d4SSatish Balay sizesTmp[3] = 4; 3379371c9d4SSatish Balay sizesTmp[4] = 4; 338412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 339412e9a14SMatthew G. Knepley } 34099836e0eSStefano Zampini if (faces) { 3419371c9d4SSatish Balay facesTmp[0] = cone[0]; 3429371c9d4SSatish Balay facesTmp[1] = cone[1]; 3439371c9d4SSatish Balay facesTmp[2] = cone[2]; /* Bottom */ 3449371c9d4SSatish Balay facesTmp[3] = cone[3]; 3459371c9d4SSatish Balay facesTmp[4] = cone[4]; 3469371c9d4SSatish Balay facesTmp[5] = cone[5]; /* Top */ 3479371c9d4SSatish Balay facesTmp[6] = cone[0]; 3489371c9d4SSatish Balay facesTmp[7] = cone[1]; 3499371c9d4SSatish Balay facesTmp[8] = cone[3]; 3509371c9d4SSatish Balay facesTmp[9] = cone[4]; /* Back left */ 3519371c9d4SSatish Balay facesTmp[10] = cone[1]; 3529371c9d4SSatish Balay facesTmp[11] = cone[2]; 3539371c9d4SSatish Balay facesTmp[12] = cone[4]; 3549371c9d4SSatish Balay facesTmp[13] = cone[5]; /* Back right */ 3559371c9d4SSatish Balay facesTmp[14] = cone[2]; 3569371c9d4SSatish Balay facesTmp[15] = cone[0]; 3579371c9d4SSatish Balay facesTmp[16] = cone[5]; 3589371c9d4SSatish Balay facesTmp[17] = cone[3]; /* Front */ 35999836e0eSStefano Zampini *faces = facesTmp; 36099836e0eSStefano Zampini } 361412e9a14SMatthew G. Knepley break; 362412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 363412e9a14SMatthew G. Knepley /* 7--------6 364412e9a14SMatthew G. Knepley /| /| 365412e9a14SMatthew G. Knepley / | / | 366412e9a14SMatthew G. Knepley 4--------5 | 367412e9a14SMatthew G. Knepley | | | | 368412e9a14SMatthew G. Knepley | | | | 369412e9a14SMatthew G. Knepley | 3--------2 370412e9a14SMatthew G. Knepley | / | / 371412e9a14SMatthew G. Knepley |/ |/ 372412e9a14SMatthew G. Knepley 0--------1 373412e9a14SMatthew G. Knepley */ 374412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 375412e9a14SMatthew G. Knepley if (faceTypes) { 3769371c9d4SSatish Balay typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 3779371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; 3789371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3799371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3809371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; 3819371c9d4SSatish Balay typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR; 382412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 383412e9a14SMatthew G. Knepley } 384412e9a14SMatthew G. Knepley if (faceSizes) { 3859371c9d4SSatish Balay sizesTmp[0] = 4; 3869371c9d4SSatish Balay sizesTmp[1] = 4; 3879371c9d4SSatish Balay sizesTmp[2] = 4; 3889371c9d4SSatish Balay sizesTmp[3] = 4; 3899371c9d4SSatish Balay sizesTmp[4] = 4; 3909371c9d4SSatish Balay sizesTmp[5] = 4; 391412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 392412e9a14SMatthew G. Knepley } 393412e9a14SMatthew G. Knepley if (faces) { 3949371c9d4SSatish Balay facesTmp[0] = cone[0]; 3959371c9d4SSatish Balay facesTmp[1] = cone[1]; 3969371c9d4SSatish Balay facesTmp[2] = cone[2]; 3979371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 3989371c9d4SSatish Balay facesTmp[4] = cone[4]; 3999371c9d4SSatish Balay facesTmp[5] = cone[5]; 4009371c9d4SSatish Balay facesTmp[6] = cone[6]; 4019371c9d4SSatish Balay facesTmp[7] = cone[7]; /* Top */ 4029371c9d4SSatish Balay facesTmp[8] = cone[0]; 4039371c9d4SSatish Balay facesTmp[9] = cone[1]; 4049371c9d4SSatish Balay facesTmp[10] = cone[4]; 4059371c9d4SSatish Balay facesTmp[11] = cone[5]; /* Front */ 4069371c9d4SSatish Balay facesTmp[12] = cone[1]; 4079371c9d4SSatish Balay facesTmp[13] = cone[2]; 4089371c9d4SSatish Balay facesTmp[14] = cone[5]; 4099371c9d4SSatish Balay facesTmp[15] = cone[6]; /* Right */ 4109371c9d4SSatish Balay facesTmp[16] = cone[2]; 4119371c9d4SSatish Balay facesTmp[17] = cone[3]; 4129371c9d4SSatish Balay facesTmp[18] = cone[6]; 4139371c9d4SSatish Balay facesTmp[19] = cone[7]; /* Back */ 4149371c9d4SSatish Balay facesTmp[20] = cone[3]; 4159371c9d4SSatish Balay facesTmp[21] = cone[0]; 4169371c9d4SSatish Balay facesTmp[22] = cone[7]; 4179371c9d4SSatish Balay facesTmp[23] = cone[4]; /* Left */ 418412e9a14SMatthew G. Knepley *faces = facesTmp; 419412e9a14SMatthew G. Knepley } 42099836e0eSStefano Zampini break; 421da9060c4SMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 422da9060c4SMatthew G. Knepley /* 423da9060c4SMatthew G. Knepley 4---- 424da9060c4SMatthew G. Knepley |\-\ \----- 425da9060c4SMatthew G. Knepley | \ -\ \ 426da9060c4SMatthew G. Knepley | 1--\-----2 427da9060c4SMatthew G. Knepley | / \ / 428da9060c4SMatthew G. Knepley |/ \ / 429da9060c4SMatthew G. Knepley 0--------3 430da9060c4SMatthew G. Knepley */ 431da9060c4SMatthew G. Knepley if (numFaces) *numFaces = 5; 432da9060c4SMatthew G. Knepley if (faceTypes) { 433da9060c4SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 4349371c9d4SSatish Balay typesTmp[1] = DM_POLYTOPE_TRIANGLE; 4359371c9d4SSatish Balay typesTmp[2] = DM_POLYTOPE_TRIANGLE; 4369371c9d4SSatish Balay typesTmp[3] = DM_POLYTOPE_TRIANGLE; 4379371c9d4SSatish Balay typesTmp[4] = DM_POLYTOPE_TRIANGLE; 438da9060c4SMatthew G. Knepley *faceTypes = typesTmp; 439da9060c4SMatthew G. Knepley } 440da9060c4SMatthew G. Knepley if (faceSizes) { 441da9060c4SMatthew G. Knepley sizesTmp[0] = 4; 4429371c9d4SSatish Balay sizesTmp[1] = 3; 4439371c9d4SSatish Balay sizesTmp[2] = 3; 4449371c9d4SSatish Balay sizesTmp[3] = 3; 4459371c9d4SSatish Balay sizesTmp[4] = 3; 446da9060c4SMatthew G. Knepley *faceSizes = sizesTmp; 447da9060c4SMatthew G. Knepley } 448da9060c4SMatthew G. Knepley if (faces) { 4499371c9d4SSatish Balay facesTmp[0] = cone[0]; 4509371c9d4SSatish Balay facesTmp[1] = cone[1]; 4519371c9d4SSatish Balay facesTmp[2] = cone[2]; 4529371c9d4SSatish Balay facesTmp[3] = cone[3]; /* Bottom */ 4539371c9d4SSatish Balay facesTmp[4] = cone[0]; 4549371c9d4SSatish Balay facesTmp[5] = cone[3]; 4559371c9d4SSatish Balay facesTmp[6] = cone[4]; /* Front */ 4569371c9d4SSatish Balay facesTmp[7] = cone[3]; 4579371c9d4SSatish Balay facesTmp[8] = cone[2]; 4589371c9d4SSatish Balay facesTmp[9] = cone[4]; /* Right */ 4599371c9d4SSatish Balay facesTmp[10] = cone[2]; 4609371c9d4SSatish Balay facesTmp[11] = cone[1]; 4619371c9d4SSatish Balay facesTmp[12] = cone[4]; /* Back */ 4629371c9d4SSatish Balay facesTmp[13] = cone[1]; 4639371c9d4SSatish Balay facesTmp[14] = cone[0]; 4649371c9d4SSatish Balay facesTmp[15] = cone[4]; /* Left */ 465da9060c4SMatthew G. Knepley *faces = facesTmp; 466da9060c4SMatthew G. Knepley } 467da9060c4SMatthew G. Knepley break; 468d71ae5a4SJacob Faibussowitsch default: 469d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]); 47099836e0eSStefano Zampini } 4713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47299836e0eSStefano Zampini } 47399836e0eSStefano Zampini 474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) 475d71ae5a4SJacob Faibussowitsch { 47699836e0eSStefano Zampini PetscFunctionBegin; 4779566063dSJacob Faibussowitsch if (faceTypes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceTypes)); 4789566063dSJacob Faibussowitsch if (faceSizes) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faceSizes)); 4799566063dSJacob Faibussowitsch if (faces) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)faces)); 4803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48199836e0eSStefano Zampini } 48299836e0eSStefano Zampini 4839a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */ 484d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm) 485d71ae5a4SJacob Faibussowitsch { 486412e9a14SMatthew G. Knepley DMLabel ctLabel; 4879a5b13a2SMatthew G Knepley PetscHashIJKL faceTable; 488412e9a14SMatthew G. Knepley PetscInt faceTypeNum[DM_NUM_POLYTOPES]; 4899318fe57SMatthew G. Knepley PetscInt depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd; 4909f074e33SMatthew G Knepley 4919f074e33SMatthew G Knepley PetscFunctionBegin; 4929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4939566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLCreate(&faceTable)); 4949566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES)); 4959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd)); 496412e9a14SMatthew G. Knepley /* Number new faces and save face vertices in hash table */ 4979566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart)); 498412e9a14SMatthew G. Knepley fEnd = fStart; 499412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 500412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 501412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 502ba2698f1SMatthew G. Knepley DMPolytopeType ct; 503412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 50499836e0eSStefano Zampini 5059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5079566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 508412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 509412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 510412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 511412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 5129a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 513e8f14785SLisandro Dalcin PetscHashIter iter; 514e8f14785SLisandro Dalcin PetscBool missing; 5159f074e33SMatthew G Knepley 5165f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 517412e9a14SMatthew G. Knepley key.i = face[0]; 518412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 519412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 520412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 5219566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 5229566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 523e9fa77a1SMatthew G. Knepley if (missing) { 5249566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLIterSet(faceTable, iter, fEnd++)); 525412e9a14SMatthew G. Knepley ++faceTypeNum[faceType]; 526e9fa77a1SMatthew G. Knepley } 5279a5b13a2SMatthew G Knepley } 5289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 52999836e0eSStefano Zampini } 530412e9a14SMatthew G. Knepley /* We need to number faces contiguously among types */ 531412e9a14SMatthew G. Knepley { 532412e9a14SMatthew G. Knepley PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0; 53399836e0eSStefano Zampini 5349371c9d4SSatish Balay for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) { 5359371c9d4SSatish Balay if (faceTypeNum[ct]) ++numFT; 5369371c9d4SSatish Balay faceTypeStart[ct] = 0; 5379371c9d4SSatish Balay } 538412e9a14SMatthew G. Knepley if (numFT > 1) { 5399566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLClear(faceTable)); 540412e9a14SMatthew G. Knepley faceTypeStart[0] = fStart; 541412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct - 1] + faceTypeNum[ct - 1]; 542412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 543412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 544412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 545ba2698f1SMatthew G. Knepley DMPolytopeType ct; 546412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 54799836e0eSStefano Zampini 5489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 5499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 5509566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 551412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 552412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 553412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 554412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 55599836e0eSStefano Zampini PetscHashIJKLKey key; 55699836e0eSStefano Zampini PetscHashIter iter; 55799836e0eSStefano Zampini PetscBool missing; 55899836e0eSStefano Zampini 5595f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 560412e9a14SMatthew G. Knepley key.i = face[0]; 561412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 562412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 563412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 5649566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 5659566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 5669566063dSJacob Faibussowitsch if (missing) PetscCall(PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++)); 56799836e0eSStefano Zampini } 5689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 56999836e0eSStefano Zampini } 570412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) { 5711dca8a05SBarry 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]); 5729a5b13a2SMatthew G Knepley } 5739a5b13a2SMatthew G Knepley } 574412e9a14SMatthew G. Knepley } 575412e9a14SMatthew G. Knepley /* Add new points, always at the end of the numbering */ 5769566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &Np)); 5779566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart))); 5789a5b13a2SMatthew G Knepley /* Set cone sizes */ 579412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 5809566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(idm, "celltype")); 5819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(idm, &ctLabel)); 5829a5b13a2SMatthew G Knepley for (d = 0; d <= depth; ++d) { 583412e9a14SMatthew G. Knepley DMPolytopeType ct; 584412e9a14SMatthew G. Knepley PetscInt coneSize, pStart, pEnd, p; 5859f074e33SMatthew G Knepley 586412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 5879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 588412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 5899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 5909566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, p, coneSize)); 5919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 5929566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, p, ct)); 5939f074e33SMatthew G Knepley } 5949f074e33SMatthew G Knepley } 595412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 596412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 597412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 598412e9a14SMatthew G. Knepley DMPolytopeType ct; 599412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 600412e9a14SMatthew G. Knepley 6019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 6029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 6039566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 6049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, c, ct)); 6059566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, c, numFaces)); 606412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 607412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 608412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 609412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 610412e9a14SMatthew G. Knepley PetscHashIJKLKey key; 611412e9a14SMatthew G. Knepley PetscHashIter iter; 612412e9a14SMatthew G. Knepley PetscBool missing; 613412e9a14SMatthew G. Knepley PetscInt f; 614412e9a14SMatthew G. Knepley 61563a3b9bcSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 616412e9a14SMatthew G. Knepley key.i = face[0]; 617412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 618412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 619412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 6209566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 6219566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 62263a3b9bcSJacob Faibussowitsch PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %" PetscInt_FMT ", lf %" PetscInt_FMT ")", c, cf); 6239566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f)); 6249566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(idm, f, faceSize)); 6259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(idm, f, faceType)); 626412e9a14SMatthew G. Knepley } 6279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 6289f074e33SMatthew G Knepley } 6299566063dSJacob Faibussowitsch PetscCall(DMSetUp(idm)); 630412e9a14SMatthew G. Knepley /* Initialize cones so we do not need the bash table to tell us that a cone has been set */ 631412e9a14SMatthew G. Knepley { 632412e9a14SMatthew G. Knepley PetscSection cs; 633412e9a14SMatthew G. Knepley PetscInt *cones, csize; 6349a5b13a2SMatthew G Knepley 6359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(idm, &cs)); 6369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(idm, &cones)); 6379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cs, &csize)); 638412e9a14SMatthew G. Knepley for (c = 0; c < csize; ++c) cones[c] = -1; 639412e9a14SMatthew G. Knepley } 640412e9a14SMatthew G. Knepley /* Set cones */ 641412e9a14SMatthew G. Knepley for (d = 0; d <= depth; ++d) { 642412e9a14SMatthew G. Knepley const PetscInt *cone; 643412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 644412e9a14SMatthew G. Knepley 645412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 6469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 647412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 6489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 6499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(idm, p, cone)); 6509566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &cone)); 6519566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(idm, p, cone)); 6529f074e33SMatthew G Knepley } 6539a5b13a2SMatthew G Knepley } 654412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 655412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 656412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 657ba2698f1SMatthew G. Knepley DMPolytopeType ct; 658412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 65999836e0eSStefano Zampini 6609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 6619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 6629566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 663412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 664412e9a14SMatthew G. Knepley DMPolytopeType faceType = faceTypes[cf]; 665412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 666412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 667412e9a14SMatthew G. Knepley const PetscInt *fcone; 6689a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 669e8f14785SLisandro Dalcin PetscHashIter iter; 670e8f14785SLisandro Dalcin PetscBool missing; 671412e9a14SMatthew G. Knepley PetscInt f; 6729f074e33SMatthew G Knepley 67363a3b9bcSJacob Faibussowitsch PetscCheck(faceSize <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 674412e9a14SMatthew G. Knepley key.i = face[0]; 675412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 676412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 677412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 6789566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSize, (PetscInt *)&key)); 6799566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 6809566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLIterGet(faceTable, iter, &f)); 6819566063dSJacob Faibussowitsch PetscCall(DMPlexInsertCone(idm, c, cf, f)); 6829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(idm, f, &fcone)); 6839566063dSJacob Faibussowitsch if (fcone[0] < 0) PetscCall(DMPlexSetCone(idm, f, face)); 684412e9a14SMatthew G. Knepley { 685412e9a14SMatthew G. Knepley const PetscInt *cone; 686412e9a14SMatthew G. Knepley PetscInt coneSize, ornt; 687a74221b0SStefano Zampini 6889566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(idm, f, &coneSize)); 6899566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(idm, f, &cone)); 69063a3b9bcSJacob 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); 691d89e6e46SMatthew G. Knepley /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */ 6929566063dSJacob Faibussowitsch PetscCall(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt)); 6939566063dSJacob Faibussowitsch PetscCall(DMPlexInsertConeOrientation(idm, c, cf, ornt)); 69499836e0eSStefano Zampini } 69599836e0eSStefano Zampini } 6969566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 69799836e0eSStefano Zampini } 6989566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLDestroy(&faceTable)); 6999566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(idm)); 7009566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(idm)); 7013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7029f074e33SMatthew G Knepley } 7039f074e33SMatthew G Knepley 704d71ae5a4SJacob Faibussowitsch static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) 705d71ae5a4SJacob Faibussowitsch { 706f80536cbSVaclav Hapla PetscInt nleaves; 707f80536cbSVaclav Hapla PetscInt nranks; 708a0d42dbcSVaclav Hapla const PetscMPIInt *ranks = NULL; 709a0d42dbcSVaclav Hapla const PetscInt *roffset = NULL, *rmine = NULL, *rremote = NULL; 710f80536cbSVaclav Hapla PetscInt n, o, r; 711f80536cbSVaclav Hapla 712f80536cbSVaclav Hapla PetscFunctionBegin; 7139566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote)); 714f80536cbSVaclav Hapla nleaves = roffset[nranks]; 7159566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nleaves, rmine1, nleaves, rremote1)); 716f80536cbSVaclav Hapla for (r = 0; r < nranks; r++) { 717f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 718f80536cbSVaclav Hapla - to unify order with the other side */ 719f80536cbSVaclav Hapla o = roffset[r]; 720f80536cbSVaclav Hapla n = roffset[r + 1] - o; 7219566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rmine1)[o], &rmine[o], n)); 7229566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&(*rremote1)[o], &rremote[o], n)); 7239566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o])); 724f80536cbSVaclav Hapla } 7253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 726f80536cbSVaclav Hapla } 727f80536cbSVaclav Hapla 728d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexOrientInterface_Internal(DM dm) 729d71ae5a4SJacob Faibussowitsch { 730d89e6e46SMatthew G. Knepley PetscSF sf; 731d89e6e46SMatthew G. Knepley const PetscInt *locals; 732d89e6e46SMatthew G. Knepley const PetscSFNode *remotes; 733d89e6e46SMatthew G. Knepley const PetscMPIInt *ranks; 734d89e6e46SMatthew G. Knepley const PetscInt *roffset; 735d89e6e46SMatthew G. Knepley PetscInt *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 736d89e6e46SMatthew G. Knepley PetscInt nroots, p, nleaves, nranks, r, maxConeSize = 0; 737d89e6e46SMatthew G. Knepley PetscInt(*roots)[4], (*leaves)[4], mainCone[4]; 738d89e6e46SMatthew G. Knepley PetscMPIInt(*rootsRanks)[4], (*leavesRanks)[4]; 7392e745bdaSMatthew G. Knepley MPI_Comm comm; 74027d0e99aSVaclav Hapla PetscMPIInt rank, size; 7412e745bdaSMatthew G. Knepley PetscInt debug = 0; 7422e745bdaSMatthew G. Knepley 7432e745bdaSMatthew G. Knepley PetscFunctionBegin; 7449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 7459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7479566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 7489566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view")); 749d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_FALSE)); 7509566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes)); 7513ba16761SJacob Faibussowitsch if (nroots < 0) PetscFunctionReturn(PETSC_SUCCESS); 7529566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 7539566063dSJacob Faibussowitsch PetscCall(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1)); 754d89e6e46SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 755d89e6e46SMatthew G. Knepley PetscInt coneSize; 7569566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, locals[p], &coneSize)); 757d89e6e46SMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 758d89e6e46SMatthew G. Knepley } 75963a3b9bcSJacob Faibussowitsch PetscCheck(maxConeSize <= 4, comm, PETSC_ERR_SUP, "This method does not support cones of size %" PetscInt_FMT, maxConeSize); 7609566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks)); 7619e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 762d89e6e46SMatthew G. Knepley const PetscInt *cone; 763d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0; 764d89e6e46SMatthew G. Knepley 7659566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 7669566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 767d89e6e46SMatthew G. Knepley /* Ignore vertices */ 76827d0e99aSVaclav Hapla if (coneSize < 2) { 769d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 77027d0e99aSVaclav Hapla roots[p][c] = -1; 77127d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 77227d0e99aSVaclav Hapla } 77327d0e99aSVaclav Hapla continue; 77427d0e99aSVaclav Hapla } 7752e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 776d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); c++) { 7779566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &ind0)); 7788a650c75SVaclav Hapla if (ind0 < 0) { 7798a650c75SVaclav Hapla roots[p][c] = cone[c]; 7808a650c75SVaclav Hapla rootsRanks[p][c] = rank; 781c8148b97SVaclav Hapla } else { 7828a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 7838a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 7848a650c75SVaclav Hapla } 7852e745bdaSMatthew G. Knepley } 786d89e6e46SMatthew G. Knepley for (c = coneSize; c < 4; c++) { 787d89e6e46SMatthew G. Knepley roots[p][c] = -1; 788d89e6e46SMatthew G. Knepley rootsRanks[p][c] = -1; 789d89e6e46SMatthew G. Knepley } 7902e745bdaSMatthew G. Knepley } 7919e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 792d89e6e46SMatthew G. Knepley PetscInt c; 793d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 7948ccb905dSVaclav Hapla leaves[p][c] = -2; 7958ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 7968ccb905dSVaclav Hapla } 797c8148b97SVaclav Hapla } 7989566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 7999566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 8009566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 8019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 802d89e6e46SMatthew G. Knepley if (debug) { 8039566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 804c5853193SPierre Jolivet if (rank == 0) PetscCall(PetscSynchronizedPrintf(comm, "Referenced roots\n")); 805d89e6e46SMatthew G. Knepley } 8069566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL)); 8079e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 808d89e6e46SMatthew G. Knepley DMPolytopeType ct; 809d89e6e46SMatthew G. Knepley const PetscInt *cone; 810d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0, o; 811d89e6e46SMatthew G. Knepley 812d89e6e46SMatthew G. Knepley if (leaves[p][0] < 0) continue; /* Ignore vertices */ 8139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 8149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 8159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 816d89e6e46SMatthew G. Knepley if (debug) { 8179371c9d4SSatish 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])); 818d89e6e46SMatthew G. Knepley } 8199371c9d4SSatish 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]) { 820d89e6e46SMatthew G. Knepley /* Translate these leaves to my cone points; mainCone means desired order p's cone points */ 821d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); ++c) { 822d89e6e46SMatthew G. Knepley PetscInt rS, rN; 823d89e6e46SMatthew G. Knepley 82427d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 825d89e6e46SMatthew G. Knepley /* A local leaf is just taken as it is */ 8269dddd249SSatish Balay mainCone[c] = leaves[p][c]; 82727d0e99aSVaclav Hapla continue; 82827d0e99aSVaclav Hapla } 829f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 830f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 8319566063dSJacob Faibussowitsch PetscCall(PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r)); 83263a3b9bcSJacob 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]); 8331dca8a05SBarry 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]); 834f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 835d89e6e46SMatthew G. Knepley rS = roffset[r]; 836d89e6e46SMatthew G. Knepley rN = roffset[r + 1] - rS; 8379566063dSJacob Faibussowitsch PetscCall(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0)); 83863a3b9bcSJacob 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]); 839f80536cbSVaclav Hapla /* Get the corresponding local point */ 8405f80ce2aSJacob Faibussowitsch mainCone[c] = rmine1[rS + ind0]; 841f80536cbSVaclav Hapla } 84263a3b9bcSJacob 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])); 84327d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 8449566063dSJacob Faibussowitsch PetscCall(DMPolytopeGetOrientation(ct, cone, mainCone, &o)); 8459566063dSJacob Faibussowitsch PetscCall(DMPlexOrientPoint(dm, p, o)); 8469566063dSJacob Faibussowitsch } else if (debug) PetscCall(PetscSynchronizedPrintf(comm, " ==\n")); 84723aaf07bSVaclav Hapla } 84827d0e99aSVaclav Hapla if (debug) { 8499566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 8509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 8512e745bdaSMatthew G. Knepley } 8529566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view")); 8539566063dSJacob Faibussowitsch PetscCall(PetscFree4(roots, leaves, rootsRanks, leavesRanks)); 8549566063dSJacob Faibussowitsch PetscCall(PetscFree2(rmine1, rremote1)); 8553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8562e745bdaSMatthew G. Knepley } 8572e745bdaSMatthew G. Knepley 858d71ae5a4SJacob Faibussowitsch static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[]) 859d71ae5a4SJacob Faibussowitsch { 8602e72742cSMatthew G. Knepley PetscInt idx; 8612e72742cSMatthew G. Knepley PetscMPIInt rank; 8622e72742cSMatthew G. Knepley PetscBool flg; 8637bffde78SMichael Lange 8647bffde78SMichael Lange PetscFunctionBegin; 8659566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg)); 8663ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 8679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8689566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 86963a3b9bcSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s %" PetscInt_FMT " %s %" PetscInt_FMT "\n", rank, idxname, idx, valname, a[idx])); 8709566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 8713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8722e72742cSMatthew G. Knepley } 8732e72742cSMatthew G. Knepley 874d71ae5a4SJacob Faibussowitsch static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) 875d71ae5a4SJacob Faibussowitsch { 8762e72742cSMatthew G. Knepley PetscInt idx; 8772e72742cSMatthew G. Knepley PetscMPIInt rank; 8782e72742cSMatthew G. Knepley PetscBool flg; 8792e72742cSMatthew G. Knepley 8802e72742cSMatthew G. Knepley PetscFunctionBegin; 8819566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, opt, &flg)); 8823ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 8839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8849566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 8852e72742cSMatthew G. Knepley if (idxname) { 88663a3b9bcSJacob 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)); 8872e72742cSMatthew G. Knepley } else { 88863a3b9bcSJacob 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)); 8892e72742cSMatthew G. Knepley } 8909566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 8913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8922e72742cSMatthew G. Knepley } 8932e72742cSMatthew G. Knepley 894d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed) 895d71ae5a4SJacob Faibussowitsch { 8963be36e83SMatthew G. Knepley PetscSF sf; 8973be36e83SMatthew G. Knepley const PetscInt *locals; 8983be36e83SMatthew G. Knepley PetscMPIInt rank; 8992e72742cSMatthew G. Knepley 9002e72742cSMatthew G. Knepley PetscFunctionBegin; 9019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9029566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9039566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL)); 9045f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 9052e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 9062e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 9072e72742cSMatthew G. Knepley } else { 9082e72742cSMatthew G. Knepley PetscHashIJKey key; 9093be36e83SMatthew G. Knepley PetscInt l; 9102e72742cSMatthew G. Knepley 9112e72742cSMatthew G. Knepley key.i = remotePoint.index; 9122e72742cSMatthew G. Knepley key.j = remotePoint.rank; 9139566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(remotehash, key, &l)); 9143be36e83SMatthew G. Knepley if (l >= 0) { 9153be36e83SMatthew G. Knepley *localPoint = locals[l]; 9165f80ce2aSJacob Faibussowitsch } else if (mapFailed) *mapFailed = PETSC_TRUE; 9172e72742cSMatthew G. Knepley } 9183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9192e72742cSMatthew G. Knepley } 9202e72742cSMatthew G. Knepley 921d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed) 922d71ae5a4SJacob Faibussowitsch { 9233be36e83SMatthew G. Knepley PetscSF sf; 9243be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 9253be36e83SMatthew G. Knepley const PetscSFNode *remotes; 9263be36e83SMatthew G. Knepley PetscInt Nl, l; 9273be36e83SMatthew G. Knepley PetscMPIInt rank; 9283be36e83SMatthew G. Knepley 9293be36e83SMatthew G. Knepley PetscFunctionBegin; 9305f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 9319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9329566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9339566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes)); 9343be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 9359566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 9369566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 9373be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 9389566063dSJacob Faibussowitsch PetscCall(PetscFindInt(localPoint, Nl, locals, &l)); 9399371c9d4SSatish Balay if (l < 0) { 9409371c9d4SSatish Balay if (mapFailed) *mapFailed = PETSC_TRUE; 9419371c9d4SSatish Balay } else *remotePoint = remotes[l]; 9423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9433be36e83SMatthew G. Knepley owned: 9443be36e83SMatthew G. Knepley remotePoint->rank = rank; 9453be36e83SMatthew G. Knepley remotePoint->index = localPoint; 9463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9473be36e83SMatthew G. Knepley } 9483be36e83SMatthew G. Knepley 949d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) 950d71ae5a4SJacob Faibussowitsch { 9513be36e83SMatthew G. Knepley PetscSF sf; 9523be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 9533be36e83SMatthew G. Knepley PetscInt Nl, idx; 9543be36e83SMatthew G. Knepley 9553be36e83SMatthew G. Knepley PetscFunctionBegin; 9563be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 9579566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9589566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL)); 9593ba16761SJacob Faibussowitsch if (Nl < 0) PetscFunctionReturn(PETSC_SUCCESS); 9609566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, Nl, locals, &idx)); 9619371c9d4SSatish Balay if (idx >= 0) { 9629371c9d4SSatish Balay *isShared = PETSC_TRUE; 9633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9649371c9d4SSatish Balay } 9659566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 9669566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 9673be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 9683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9693be36e83SMatthew G. Knepley } 9703be36e83SMatthew G. Knepley 971d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) 972d71ae5a4SJacob Faibussowitsch { 9733be36e83SMatthew G. Knepley const PetscInt *cone; 9743be36e83SMatthew G. Knepley PetscInt coneSize, c; 9753be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 9763be36e83SMatthew G. Knepley 9773be36e83SMatthew G. Knepley PetscFunctionBegin; 9789566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 9799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9803be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9813be36e83SMatthew G. Knepley PetscBool pointShared; 9823be36e83SMatthew G. Knepley 9839566063dSJacob Faibussowitsch PetscCall(DMPlexPointIsShared(dm, cone[c], &pointShared)); 9843be36e83SMatthew G. Knepley cShared = (PetscBool)(cShared && pointShared); 9853be36e83SMatthew G. Knepley } 9863be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 9873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9883be36e83SMatthew G. Knepley } 9893be36e83SMatthew G. Knepley 990d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) 991d71ae5a4SJacob Faibussowitsch { 9923be36e83SMatthew G. Knepley const PetscInt *cone; 9933be36e83SMatthew G. Knepley PetscInt coneSize, c; 9943be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 9953be36e83SMatthew G. Knepley 9963be36e83SMatthew G. Knepley PetscFunctionBegin; 9979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 9989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9993be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10003be36e83SMatthew G. Knepley PetscSFNode rcp; 10015f80ce2aSJacob Faibussowitsch PetscBool mapFailed; 10023be36e83SMatthew G. Knepley 10039566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed)); 10045f80ce2aSJacob Faibussowitsch if (mapFailed) { 10053be36e83SMatthew G. Knepley cmin = missing; 10063be36e83SMatthew G. Knepley } else { 10073be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 10083be36e83SMatthew G. Knepley } 10093be36e83SMatthew G. Knepley } 10103be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 10113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10123be36e83SMatthew G. Knepley } 10133be36e83SMatthew G. Knepley 10143be36e83SMatthew G. Knepley /* 10153be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 10163be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 10173be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 10183be36e83SMatthew G. Knepley */ 1019d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) 1020d71ae5a4SJacob Faibussowitsch { 10213be36e83SMatthew G. Knepley MPI_Comm comm; 10223be36e83SMatthew G. Knepley const PetscInt *support; 1023cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height; 10243be36e83SMatthew G. Knepley PetscMPIInt rank; 10253be36e83SMatthew G. Knepley 10263be36e83SMatthew G. Knepley PetscFunctionBegin; 10279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 10289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10299566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap)); 10309566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 10319566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointHeight(dm, p, &height)); 1032cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight + 1) { 1033cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */ 103463a3b9bcSJacob 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)); 10353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1036cf4dc471SVaclav Hapla } 10379566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 10389566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 10399566063dSJacob Faibussowitsch if (candidates) PetscCall(PetscSectionGetOffset(candidateSection, p, &off)); 10403be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 10413be36e83SMatthew G. Knepley const PetscInt face = support[s]; 10423be36e83SMatthew G. Knepley const PetscInt *cone; 10433be36e83SMatthew G. Knepley PetscSFNode cpmin = {-1, -1}, rp = {-1, -1}; 10443be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 10453be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 10463be36e83SMatthew G. Knepley PetscHashIJKey key; 10473be36e83SMatthew G. Knepley 10483be36e83SMatthew G. Knepley /* Only add point once */ 104963a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Support face %" PetscInt_FMT "\n", rank, face)); 10503be36e83SMatthew G. Knepley key.i = p; 10513be36e83SMatthew G. Knepley key.j = face; 10529566063dSJacob Faibussowitsch PetscCall(PetscHMapIJGet(faceHash, key, &f)); 10533be36e83SMatthew G. Knepley if (f >= 0) continue; 10549566063dSJacob Faibussowitsch PetscCall(DMPlexConeIsShared(dm, face, &isShared)); 10559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeMinimum(dm, face, &cpmin)); 10569566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, p, &rp, NULL)); 10573be36e83SMatthew G. Knepley if (debug) { 105863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Face point %" PetscInt_FMT " is shared: %d\n", rank, face, (int)isShared)); 105963a3b9bcSJacob 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)); 10603be36e83SMatthew G. Knepley } 10613be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 10629566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p)); 10633be36e83SMatthew G. Knepley if (candidates) { 106463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Adding shared face %" PetscInt_FMT " at idx %" PetscInt_FMT "\n[%d] ", rank, face, idx, rank)); 10659566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize)); 10669566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, face, &cone)); 10673be36e83SMatthew G. Knepley candidates[off + idx].rank = -1; 10683be36e83SMatthew G. Knepley candidates[off + idx++].index = coneSize - 1; 10693be36e83SMatthew G. Knepley candidates[off + idx].rank = rank; 10703be36e83SMatthew G. Knepley candidates[off + idx++].index = face; 10713be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10723be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 10733be36e83SMatthew G. Knepley 10743be36e83SMatthew G. Knepley if (cp == p) continue; 10759566063dSJacob Faibussowitsch PetscCall(DMPlexMapToGlobalPoint(dm, cp, &candidates[off + idx], NULL)); 107663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, " (%" PetscInt_FMT ",%" PetscInt_FMT ")", candidates[off + idx].rank, candidates[off + idx].index)); 10773be36e83SMatthew G. Knepley ++idx; 10783be36e83SMatthew G. Knepley } 10799566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "\n")); 10803be36e83SMatthew G. Knepley } else { 10813be36e83SMatthew G. Knepley /* Add cone size to section */ 108263a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %" PetscInt_FMT "\n", rank, face)); 10839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, face, &coneSize)); 10849566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(faceHash, key, p)); 10859566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(candidateSection, p, coneSize + 1)); 10863be36e83SMatthew G. Knepley } 10873be36e83SMatthew G. Knepley } 10883be36e83SMatthew G. Knepley } 10893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10903be36e83SMatthew G. Knepley } 10913be36e83SMatthew G. Knepley 10922e72742cSMatthew G. Knepley /*@ 1093*20f4b53cSBarry Smith DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the `PointSF` in parallel, following local interpolation 10942e72742cSMatthew G. Knepley 1095*20f4b53cSBarry Smith Collective 10962e72742cSMatthew G. Knepley 10972e72742cSMatthew G. Knepley Input Parameters: 1098*20f4b53cSBarry Smith + dm - The interpolated `DMPLEX` 1099*20f4b53cSBarry Smith - pointSF - The initial `PetscSF` without interpolated points 11002e72742cSMatthew G. Knepley 1101f0cfc026SVaclav Hapla Level: developer 11022e72742cSMatthew G. Knepley 1103*20f4b53cSBarry Smith Note: 1104*20f4b53cSBarry 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` 11052e72742cSMatthew G. Knepley 1106*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexUninterpolate()` 11072e72742cSMatthew G. Knepley @*/ 1108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 1109d71ae5a4SJacob Faibussowitsch { 11103be36e83SMatthew G. Knepley MPI_Comm comm; 11113be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 11123be36e83SMatthew G. Knepley PetscHMapI claimshash; 11133be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 11143be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 11152e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 11162e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 11173be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 11183be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 11193be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 1120f0cfc026SVaclav Hapla PetscMPIInt rank; 11212e72742cSMatthew G. Knepley 11222e72742cSMatthew G. Knepley PetscFunctionBegin; 1123f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1124064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 11259566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &flg)); 11263ba16761SJacob Faibussowitsch if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 11273be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 11289566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 11299566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11319566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &ov)); 113228b400f6SJacob Faibussowitsch PetscCheck(!ov, comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 11339566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, ((PetscObject)dm)->prefix, "-dmplex_interp_debug", &debug)); 11349566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)dm, NULL, "-dm_interp_pre_view")); 11359566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)pointSF, NULL, "-petscsf_interp_pre_view")); 11369566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_InterpolateSF, dm, 0, 0, 0)); 11373be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 11389566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints)); 113908401ef6SPierre Jolivet PetscCheck(Nr >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 11409566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&remoteHash)); 11413be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11423be36e83SMatthew G. Knepley PetscHashIJKey key; 11432e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 11442e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 11459566063dSJacob Faibussowitsch PetscCall(PetscHMapIJSet(remoteHash, key, l)); 11467bffde78SMichael Lange } 114766aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 11489566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 11499566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 11509566063dSJacob Faibussowitsch PetscCall(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree)); 11513be36e83SMatthew G. Knepley /* 11523be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 11533be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 11543be36e83SMatthew G. Knepley \begin{itemize} 11553be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 11563be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 11573be36e83SMatthew G. Knepley \end{itemize} 11583be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 11593be36e83SMatthew 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 11603be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 11613be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 11623be36e83SMatthew G. Knepley */ 11633be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 11643be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 1165da81f932SPierre Jolivet The array holds candidate shared faces, each face is referred to by the leaf point */ 11669566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateSection)); 11679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(candidateSection, 0, Nr)); 11687bffde78SMichael Lange { 11693be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 11702e72742cSMatthew G. Knepley 11719566063dSJacob Faibussowitsch PetscCall(PetscHMapIJCreate(&faceHash)); 11723be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11733be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 11742e72742cSMatthew G. Knepley 117563a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %" PetscInt_FMT "\n", rank, p)); 11769566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug)); 11772e72742cSMatthew G. Knepley } 11789566063dSJacob Faibussowitsch PetscCall(PetscHMapIJClear(faceHash)); 11799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(candidateSection)); 11809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateSection, &candidatesSize)); 11819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesSize, &candidates)); 11823be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11833be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 11842e72742cSMatthew G. Knepley 118563a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %" PetscInt_FMT "\n", rank, p)); 11869566063dSJacob Faibussowitsch PetscCall(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug)); 11872e72742cSMatthew G. Knepley } 11889566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&faceHash)); 11899566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 11907bffde78SMichael Lange } 11919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateSection, "Candidate Section")); 11929566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateSection, NULL, "-petscsection_interp_candidate_view")); 11939566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates)); 11943be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 11952e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 11967bffde78SMichael Lange { 11977bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 11987bffde78SMichael Lange PetscInt *remoteOffsets; 11992e72742cSMatthew G. Knepley 12009566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti)); 12019566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(sfMulti, &sfInverse)); 12029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &candidateRemoteSection)); 12039566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection)); 12049566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates)); 12059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize)); 12069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(candidatesRemoteSize, &candidatesRemote)); 12079566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE)); 12089566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote, MPI_REPLACE)); 12099566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfInverse)); 12109566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfCandidates)); 12119566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 12122e72742cSMatthew G. Knepley 12139566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)candidateRemoteSection, "Remote Candidate Section")); 12149566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view")); 12159566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote)); 12167bffde78SMichael Lange } 12173be36e83SMatthew 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 */ 12187bffde78SMichael Lange { 12193be36e83SMatthew G. Knepley PetscHashIJKLRemote faceTable; 12203be36e83SMatthew G. Knepley PetscInt idx, idx2; 12213be36e83SMatthew G. Knepley 12229566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteCreate(&faceTable)); 12232e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 12243be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 12252e72742cSMatthew G. Knepley PetscInt deg; 12263be36e83SMatthew G. Knepley 12272e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 12282e72742cSMatthew G. Knepley PetscInt offset, dof, d; 12292e72742cSMatthew G. Knepley 12309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx, &dof)); 12319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx, &offset)); 12323be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 12332e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12343be36e83SMatthew G. Knepley const PetscInt hidx = offset + d; 12353be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1; 12363be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx + 1]; 12373be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2]; 12383be36e83SMatthew G. Knepley PetscSFNode fcp0; 12393be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 12402e72742cSMatthew G. Knepley const PetscInt *join = NULL; 12413be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 12423be36e83SMatthew G. Knepley PetscHashIter iter; 12435f80ce2aSJacob Faibussowitsch PetscBool missing, mapToLocalPointFailed = PETSC_FALSE; 12442e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 12452e72742cSMatthew G. Knepley 12469371c9d4SSatish Balay if (debug) 12479371c9d4SSatish 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, 12489371c9d4SSatish Balay rface.index, r, idx, d, Np)); 124963a3b9bcSJacob 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); 12503be36e83SMatthew G. Knepley fcp0.rank = rank; 12513be36e83SMatthew G. Knepley fcp0.index = r; 12523be36e83SMatthew G. Knepley d += Np; 12533be36e83SMatthew G. Knepley /* Put remote face in hash table */ 12543be36e83SMatthew G. Knepley key.i = fcp0; 12553be36e83SMatthew G. Knepley key.j = fcone[0]; 12563be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 12573be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 12589566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key)); 12599566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing)); 12603be36e83SMatthew G. Knepley if (missing) { 126163a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Setting remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank)); 12629566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface)); 12633be36e83SMatthew G. Knepley } else { 12643be36e83SMatthew G. Knepley PetscSFNode oface; 12653be36e83SMatthew G. Knepley 12669566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface)); 12673be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 126863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Replacing with remote face (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, rface.index, rface.rank)); 12699566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, rface)); 12703be36e83SMatthew G. Knepley } 12713be36e83SMatthew G. Knepley } 12723be36e83SMatthew G. Knepley /* Check for local face */ 12732e72742cSMatthew G. Knepley points[0] = r; 12743be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 12759566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p - 1], &points[p], &mapToLocalPointFailed)); 12765f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) break; /* We got a point not in our overlap */ 127763a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Checking local candidate %" PetscInt_FMT "\n", rank, points[p])); 12787bffde78SMichael Lange } 12795f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) continue; 12809566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np, points, &joinSize, &join)); 12817bffde78SMichael Lange if (joinSize == 1) { 12823be36e83SMatthew G. Knepley PetscSFNode lface; 12833be36e83SMatthew G. Knepley PetscSFNode oface; 12843be36e83SMatthew G. Knepley 12853be36e83SMatthew G. Knepley /* Always replace with local face */ 12863be36e83SMatthew G. Knepley lface.rank = rank; 12873be36e83SMatthew G. Knepley lface.index = join[0]; 12889566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface)); 12899371c9d4SSatish Balay if (debug) 12909371c9d4SSatish 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)); 12919566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteIterSet(faceTable, iter, lface)); 12927bffde78SMichael Lange } 12939566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join)); 12943be36e83SMatthew G. Knepley } 12953be36e83SMatthew G. Knepley } 12963be36e83SMatthew G. Knepley /* Put back faces for this root */ 12973be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 12983be36e83SMatthew G. Knepley PetscInt offset, dof, d; 12993be36e83SMatthew G. Knepley 13009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateRemoteSection, idx2, &dof)); 13019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset)); 13023be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 13033be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 13043be36e83SMatthew G. Knepley const PetscInt hidx = offset + d; 13053be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index + 1; 13063be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx + 2]; 13073be36e83SMatthew G. Knepley PetscSFNode fcp0; 13083be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 13093be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 13103be36e83SMatthew G. Knepley PetscHashIter iter; 13113be36e83SMatthew G. Knepley PetscBool missing; 13123be36e83SMatthew G. Knepley 131363a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Entering face at (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, r, idx)); 131463a3b9bcSJacob Faibussowitsch PetscCheck(Np <= 4, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %" PetscInt_FMT " cone points", Np); 13153be36e83SMatthew G. Knepley fcp0.rank = rank; 13163be36e83SMatthew G. Knepley fcp0.index = r; 13173be36e83SMatthew G. Knepley d += Np; 13183be36e83SMatthew G. Knepley /* Find remote face in hash table */ 13193be36e83SMatthew G. Knepley key.i = fcp0; 13203be36e83SMatthew G. Knepley key.j = fcone[0]; 13213be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 13223be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 13239566063dSJacob Faibussowitsch PetscCall(PetscSortSFNode(Np, (PetscSFNode *)&key)); 13249371c9d4SSatish Balay if (debug) 13259371c9d4SSatish 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, 13269371c9d4SSatish 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)); 13279566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing)); 132863a3b9bcSJacob Faibussowitsch PetscCheck(!missing, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %" PetscInt_FMT " Idx %" PetscInt_FMT " ought to have an associated face", r, idx2); 1329f7d195e4SLawrence Mitchell PetscCall(PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx])); 13307bffde78SMichael Lange } 13317bffde78SMichael Lange } 13327bffde78SMichael Lange } 13339566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), NULL)); 13349566063dSJacob Faibussowitsch PetscCall(PetscHashIJKLRemoteDestroy(&faceTable)); 13357bffde78SMichael Lange } 13363be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 13377bffde78SMichael Lange { 13387bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 13397bffde78SMichael Lange PetscSFNode *remotePointsNew; 13402e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 13413be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 13422e72742cSMatthew G. Knepley 13433be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 13449566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(pointSF, &sfMulti)); 13459566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &claimSection)); 13469566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection)); 13479566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims)); 13489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(claimSection, &claimsSize)); 13499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(claimsSize, &claims)); 13503be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 13519566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE)); 13529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims, MPI_REPLACE)); 13539566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfClaims)); 13549566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 13559566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)claimSection, "Claim Section")); 13569566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)claimSection, NULL, "-petscsection_interp_claim_view")); 13579566063dSJacob Faibussowitsch PetscCall(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims)); 13583be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 13593be36e83SMatthew 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 */ 13609566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&claimshash)); 13613be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 13623be36e83SMatthew G. Knepley PetscInt dof, off, d; 13632e72742cSMatthew G. Knepley 136463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %" PetscInt_FMT "\n", rank, r)); 13659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(candidateSection, r, &dof)); 13669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(candidateSection, r, &off)); 13672e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 13683be36e83SMatthew G. Knepley if (claims[off + d].rank >= 0) { 13693be36e83SMatthew G. Knepley const PetscInt faceInd = off + d; 13703be36e83SMatthew G. Knepley const PetscInt Np = candidates[off + d].index; 13712e72742cSMatthew G. Knepley const PetscInt *join = NULL; 13722e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 13732e72742cSMatthew G. Knepley 137463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found claim for remote point (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, claims[faceInd].rank, claims[faceInd].index)); 13753be36e83SMatthew G. Knepley points[0] = r; 137663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[0])); 13773be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 13789566063dSJacob Faibussowitsch PetscCall(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off + d], &points[c + 1], NULL)); 137963a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] point %" PetscInt_FMT "\n", rank, points[c + 1])); 13802e72742cSMatthew G. Knepley } 13819566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, Np + 1, points, &joinSize, &join)); 13822e72742cSMatthew G. Knepley if (joinSize == 1) { 13833be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 138463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %" PetscInt_FMT " for non-remote partner\n", rank, join[0])); 13853be36e83SMatthew G. Knepley } else { 138663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found local face %" PetscInt_FMT "\n", rank, join[0])); 13879566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(claimshash, join[0], faceInd)); 13882e72742cSMatthew G. Knepley } 13893be36e83SMatthew G. Knepley } else { 13909566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank)); 13913be36e83SMatthew G. Knepley } 13929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, Np + 1, points, &joinSize, &join)); 13933be36e83SMatthew G. Knepley } else { 139463a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedPrintf(comm, "[%d] No claim for point %" PetscInt_FMT "\n", rank, r)); 13953be36e83SMatthew G. Knepley d += claims[off + d].index + 1; 13967bffde78SMichael Lange } 13977bffde78SMichael Lange } 13983be36e83SMatthew G. Knepley } 13999566063dSJacob Faibussowitsch if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 14003be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 14019566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(claimshash, &NlNew)); 14029566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &localPointsNew)); 14049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl + NlNew, &remotePointsNew)); 14053be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 14063be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 14073be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 14083be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 14097bffde78SMichael Lange } 14103be36e83SMatthew G. Knepley p = Nl; 14119566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetKeys(claimshash, &p, localPointsNew)); 14123be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 14139566063dSJacob Faibussowitsch PetscCall(PetscSortInt(NlNew, &localPointsNew[Nl])); 14143be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 14153be36e83SMatthew G. Knepley PetscInt off; 14169566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(claimshash, localPointsNew[p], &off)); 14171dca8a05SBarry 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); 14183be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 14197bffde78SMichael Lange } 14209566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfPointNew)); 14219566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointNew, pEnd - pStart, Nl + NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 14229566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfPointNew)); 14239566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPointNew)); 14249566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)sfPointNew, NULL, "-petscsf_interp_view")); 1425d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPointNew, PETSC_FALSE)); 14269566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPointNew)); 14279566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&claimshash)); 14287bffde78SMichael Lange } 14299566063dSJacob Faibussowitsch PetscCall(PetscHMapIJDestroy(&remoteHash)); 14309566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateSection)); 14319566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&candidateRemoteSection)); 14329566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&claimSection)); 14339566063dSJacob Faibussowitsch PetscCall(PetscFree(candidates)); 14349566063dSJacob Faibussowitsch PetscCall(PetscFree(candidatesRemote)); 14359566063dSJacob Faibussowitsch PetscCall(PetscFree(claims)); 14369566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_InterpolateSF, dm, 0, 0, 0)); 14373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14387bffde78SMichael Lange } 14397bffde78SMichael Lange 1440248eb259SVaclav Hapla /*@ 144180330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 144280330477SMatthew G. Knepley 1443*20f4b53cSBarry Smith Collective 144480330477SMatthew G. Knepley 1445*20f4b53cSBarry Smith Input Parameter: 1446*20f4b53cSBarry Smith . dm - The `DMPLEX` object with only cells and vertices 144780330477SMatthew G. Knepley 144880330477SMatthew G. Knepley Output Parameter: 1449*20f4b53cSBarry Smith . dmInt - The complete `DMPLEX` object 145080330477SMatthew G. Knepley 145180330477SMatthew G. Knepley Level: intermediate 145280330477SMatthew G. Knepley 1453*20f4b53cSBarry Smith Note: 14547fb59074SVaclav Hapla Labels and coordinates are copied. 145543eeeb2dSStefano Zampini 1456*20f4b53cSBarry Smith Developer Note: 1457*20f4b53cSBarry Smith It sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`. 14589ade3219SVaclav Hapla 1459*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexUninterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()` 146080330477SMatthew G. Knepley @*/ 1461d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 1462d71ae5a4SJacob Faibussowitsch { 1463a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 14649a5b13a2SMatthew G Knepley DM idm, odm = dm; 14657bffde78SMichael Lange PetscSF sfPoint; 14662e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 146710a67516SMatthew G. Knepley const char *name; 1468b325530aSVaclav Hapla PetscBool flg = PETSC_TRUE; 14699f074e33SMatthew G Knepley 14709f074e33SMatthew G Knepley PetscFunctionBegin; 147110a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 147210a67516SMatthew G. Knepley PetscValidPointer(dmInt, 2); 14739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Interpolate, dm, 0, 0, 0)); 14749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 14759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 14769566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 147708401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1478827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 14799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 148076b791aaSMatthew G. Knepley idm = dm; 1481b21b8912SMatthew G. Knepley } else { 14829a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 14839a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 14849566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &idm)); 14859566063dSJacob Faibussowitsch PetscCall(DMSetType(idm, DMPLEX)); 14869566063dSJacob Faibussowitsch PetscCall(DMSetDimension(idm, dim)); 14877bffde78SMichael Lange if (depth > 0) { 14889566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateFaces_Internal(odm, 1, idm)); 14899566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(odm, &sfPoint)); 1490d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(odm, sfPoint, PETSC_FALSE)); 149194488200SVaclav Hapla { 14923be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 149394488200SVaclav Hapla PetscInt nroots; 14949566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 14959566063dSJacob Faibussowitsch if (nroots >= 0) PetscCall(DMPlexInterpolatePointSF(idm, sfPoint)); 149694488200SVaclav Hapla } 14977bffde78SMichael Lange } 14989566063dSJacob Faibussowitsch if (odm != dm) PetscCall(DMDestroy(&odm)); 14999a5b13a2SMatthew G Knepley odm = idm; 15009f074e33SMatthew G Knepley } 15019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 15029566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)idm, name)); 15039566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 15049566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL)); 15059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL)); 15069566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexOrientInterface_Internal(idm)); 150784699f70SSatish Balay } 1508827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1509827c4036SVaclav Hapla { 1510d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)idm->data; 1511827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1512827c4036SVaclav Hapla } 15135de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, idm)); 15149a5b13a2SMatthew G Knepley *dmInt = idm; 15159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Interpolate, dm, 0, 0, 0)); 15163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15179f074e33SMatthew G Knepley } 151807b0a1fcSMatthew G Knepley 151980330477SMatthew G. Knepley /*@ 152080330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 152180330477SMatthew G. Knepley 1522*20f4b53cSBarry Smith Collective 152380330477SMatthew G. Knepley 152480330477SMatthew G. Knepley Input Parameter: 1525*20f4b53cSBarry Smith . dmA - The `DMPLEX` object with initial coordinates 152680330477SMatthew G. Knepley 152780330477SMatthew G. Knepley Output Parameter: 1528*20f4b53cSBarry Smith . dmB - The `DMPLEX` object with copied coordinates 152980330477SMatthew G. Knepley 153080330477SMatthew G. Knepley Level: intermediate 153180330477SMatthew G. Knepley 1532*20f4b53cSBarry Smith Note: 1533*20f4b53cSBarry Smith This is typically used when adding pieces other than vertices to a mesh 153480330477SMatthew G. Knepley 1535*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMCopyLabels()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMGetCoordinateSection()` 153680330477SMatthew G. Knepley @*/ 1537d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 1538d71ae5a4SJacob Faibussowitsch { 153907b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 154043eeeb2dSStefano Zampini VecType vtype; 154107b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 154207b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 15430bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 154490a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 154543eeeb2dSStefano Zampini PetscBool lc = PETSC_FALSE; 154607b0a1fcSMatthew G Knepley 154707b0a1fcSMatthew G Knepley PetscFunctionBegin; 154843eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 154943eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 15503ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS); 15519566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &cdim)); 15529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dmB, cdim)); 15539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA)); 15549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB)); 155563a3b9bcSJacob 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); 155661a622f3SMatthew G. Knepley /* Copy over discretization if it exists */ 155761a622f3SMatthew G. Knepley { 155861a622f3SMatthew G. Knepley DM cdmA, cdmB; 155961a622f3SMatthew G. Knepley PetscDS dsA, dsB; 156061a622f3SMatthew G. Knepley PetscObject objA, objB; 156161a622f3SMatthew G. Knepley PetscClassId idA, idB; 156261a622f3SMatthew G. Knepley const PetscScalar *constants; 156361a622f3SMatthew G. Knepley PetscInt cdim, Nc; 156461a622f3SMatthew G. Knepley 15659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &cdmA)); 15669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &cdmB)); 15679566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmA, 0, NULL, &objA)); 15689566063dSJacob Faibussowitsch PetscCall(DMGetField(cdmB, 0, NULL, &objB)); 15699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objA, &idA)); 15709566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objB, &idB)); 157161a622f3SMatthew G. Knepley if ((idA == PETSCFE_CLASSID) && (idA != idB)) { 15729566063dSJacob Faibussowitsch PetscCall(DMSetField(cdmB, 0, NULL, objA)); 15739566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdmB)); 15749566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmA, &dsA)); 15759566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdmB, &dsB)); 15769566063dSJacob Faibussowitsch PetscCall(PetscDSGetCoordinateDimension(dsA, &cdim)); 15779566063dSJacob Faibussowitsch PetscCall(PetscDSSetCoordinateDimension(dsB, cdim)); 15789566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(dsA, &Nc, &constants)); 15799566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(dsB, Nc, (PetscScalar *)constants)); 158061a622f3SMatthew G. Knepley } 158161a622f3SMatthew G. Knepley } 15829566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA)); 15839566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB)); 15849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmA, &coordSectionA)); 15859566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmB, &coordSectionB)); 15863ba16761SJacob Faibussowitsch if (coordSectionA == coordSectionB) PetscFunctionReturn(PETSC_SUCCESS); 15879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSectionA, &Nf)); 15883ba16761SJacob Faibussowitsch if (!Nf) PetscFunctionReturn(PETSC_SUCCESS); 158963a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %" PetscInt_FMT, Nf); 1590df26b574SMatthew G. Knepley if (!coordSectionB) { 1591df26b574SMatthew G. Knepley PetscInt dim; 1592df26b574SMatthew G. Knepley 15939566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coordSectionA), &coordSectionB)); 15949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmA, &dim)); 15959566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dmB, dim, coordSectionB)); 15969566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordSectionB)); 1597df26b574SMatthew G. Knepley } 15989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSectionB, 1)); 15999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim)); 16009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim)); 16019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSectionA, &cS, &cE)); 160243eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 160363a3b9bcSJacob Faibussowitsch PetscCheck((cEndA - cStartA) == (cEndB - cStartB), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %" PetscInt_FMT " != %" PetscInt_FMT " in the second DM", cEndA - cStartA, cEndB - cStartB); 160443eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 160543eeeb2dSStefano Zampini cE = vEndB; 160643eeeb2dSStefano Zampini lc = PETSC_TRUE; 160743eeeb2dSStefano Zampini } else { 160843eeeb2dSStefano Zampini cS = vStartB; 160943eeeb2dSStefano Zampini cE = vEndB; 161043eeeb2dSStefano Zampini } 16119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSectionB, cS, cE)); 161207b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 16139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSectionB, v, spaceDim)); 16149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim)); 161507b0a1fcSMatthew G Knepley } 161643eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 161743eeeb2dSStefano Zampini PetscInt c; 161843eeeb2dSStefano Zampini 161943eeeb2dSStefano Zampini for (c = cS - cStartB; c < cEndB - cStartB; c++) { 162043eeeb2dSStefano Zampini PetscInt dof; 162143eeeb2dSStefano Zampini 16229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof)); 16239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSectionB, c + cStartB, dof)); 16249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof)); 162543eeeb2dSStefano Zampini } 162643eeeb2dSStefano Zampini } 16279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSectionB)); 16289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSectionB, &coordSizeB)); 16299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordinatesA)); 16309566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinatesB)); 16319566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinatesB, "coordinates")); 16329566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE)); 16339566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(coordinatesA, &d)); 16349566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinatesB, d)); 16359566063dSJacob Faibussowitsch PetscCall(VecGetType(coordinatesA, &vtype)); 16369566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinatesB, vtype)); 16379566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesA, &coordsA)); 16389566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinatesB, &coordsB)); 163907b0a1fcSMatthew G Knepley for (v = 0; v < vEndB - vStartB; ++v) { 164043eeeb2dSStefano Zampini PetscInt offA, offB; 164143eeeb2dSStefano Zampini 16429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA)); 16439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB)); 1644ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coordsB[offB + d] = coordsA[offA + d]; 164543eeeb2dSStefano Zampini } 164643eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 164743eeeb2dSStefano Zampini PetscInt c; 164843eeeb2dSStefano Zampini 164943eeeb2dSStefano Zampini for (c = cS - cStartB; c < cEndB - cStartB; c++) { 165043eeeb2dSStefano Zampini PetscInt dof, offA, offB; 165143eeeb2dSStefano Zampini 16529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA)); 16539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB)); 16549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSectionA, c + cStartA, &dof)); 16559566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(coordsB + offB, coordsA + offA, dof)); 165607b0a1fcSMatthew G Knepley } 165707b0a1fcSMatthew G Knepley } 16589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesA, &coordsA)); 16599566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinatesB, &coordsB)); 16609566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordinatesB)); 16619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinatesB)); 16623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 166307b0a1fcSMatthew G Knepley } 16645c386225SMatthew G. Knepley 16654e3744c5SMatthew G. Knepley /*@ 16664e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 16674e3744c5SMatthew G. Knepley 1668*20f4b53cSBarry Smith Collective 16694e3744c5SMatthew G. Knepley 16704e3744c5SMatthew G. Knepley Input Parameter: 1671*20f4b53cSBarry Smith . dm - The complete `DMPLEX` object 16724e3744c5SMatthew G. Knepley 16734e3744c5SMatthew G. Knepley Output Parameter: 1674*20f4b53cSBarry Smith . dmUnint - The `DMPLEX` object with only cells and vertices 16754e3744c5SMatthew G. Knepley 16764e3744c5SMatthew G. Knepley Level: intermediate 16774e3744c5SMatthew G. Knepley 1678*20f4b53cSBarry Smith Note: 167995452b02SPatrick Sanan It does not copy over the coordinates. 168043eeeb2dSStefano Zampini 1681*20f4b53cSBarry Smith Developer Note: 1682*20f4b53cSBarry Smith Sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`. 16839ade3219SVaclav Hapla 1684*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCopyCoordinates()` 16854e3744c5SMatthew G. Knepley @*/ 1686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 1687d71ae5a4SJacob Faibussowitsch { 1688827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 16894e3744c5SMatthew G. Knepley DM udm; 1690412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; 16914e3744c5SMatthew G. Knepley 16924e3744c5SMatthew G. Knepley PetscFunctionBegin; 169343eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 169443eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 16959566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 16969566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 169708401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1698827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1699827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 17009566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 1701595d4abbSMatthew G. Knepley *dmUnint = dm; 17023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17034e3744c5SMatthew G. Knepley } 17049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 17059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 17069566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &udm)); 17079566063dSJacob Faibussowitsch PetscCall(DMSetType(udm, DMPLEX)); 17089566063dSJacob Faibussowitsch PetscCall(DMSetDimension(udm, dim)); 17099566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(udm, cStart, vEnd)); 17104e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1711595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 17124e3744c5SMatthew G. Knepley 17139566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 17144e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 17154e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 17164e3744c5SMatthew G. Knepley 17174e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 17184e3744c5SMatthew G. Knepley } 17199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 17209566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(udm, c, coneSize)); 1721595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 17224e3744c5SMatthew G. Knepley } 17239566063dSJacob Faibussowitsch PetscCall(DMSetUp(udm)); 17249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConeSize, &cone)); 17254e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1726595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 17274e3744c5SMatthew G. Knepley 17289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 17294e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 17304e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 17314e3744c5SMatthew G. Knepley 17324e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 17334e3744c5SMatthew G. Knepley } 17349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 17359566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(udm, c, cone)); 17364e3744c5SMatthew G. Knepley } 17379566063dSJacob Faibussowitsch PetscCall(PetscFree(cone)); 17389566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(udm)); 17399566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(udm)); 17405c7de58aSMatthew G. Knepley /* Reduce SF */ 17415c7de58aSMatthew G. Knepley { 17425c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 17435c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 17445c7de58aSMatthew G. Knepley const PetscInt *localPoints; 17455c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 17465c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 174722fd0ad9SVaclav Hapla PetscInt numRoots, numLeaves, l; 17485c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 17495c7de58aSMatthew G. Knepley 17505c7de58aSMatthew G. Knepley /* Get original SF information */ 17519566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 1752d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sfPoint, PETSC_FALSE)); 17539566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(udm, &sfPointUn)); 17549566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 175522fd0ad9SVaclav Hapla if (numRoots >= 0) { 17565c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 175722fd0ad9SVaclav Hapla for (l = 0; l < numLeaves; ++l) { 175822fd0ad9SVaclav Hapla const PetscInt p = localPoints[l]; 175922fd0ad9SVaclav Hapla 176022fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) numLeavesUn++; 176122fd0ad9SVaclav Hapla } 17625c7de58aSMatthew G. Knepley /* Fill in leaves */ 17639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &remotePointsUn)); 17649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesUn, &localPointsUn)); 17655c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 176622fd0ad9SVaclav Hapla const PetscInt p = localPoints[l]; 176722fd0ad9SVaclav Hapla 176822fd0ad9SVaclav Hapla if ((vStart <= p && p < vEnd) || (cStart <= p && p < cEnd)) { 176922fd0ad9SVaclav Hapla localPointsUn[n] = p; 17705c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 17715c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 17725c7de58aSMatthew G. Knepley ++n; 17735c7de58aSMatthew G. Knepley } 17745c7de58aSMatthew G. Knepley } 177563a3b9bcSJacob Faibussowitsch PetscCheck(n == numLeavesUn, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %" PetscInt_FMT " != %" PetscInt_FMT, n, numLeavesUn); 177622fd0ad9SVaclav Hapla PetscCall(PetscSFSetGraph(sfPointUn, cEnd - cStart + vEnd - vStart, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER)); 17775c7de58aSMatthew G. Knepley } 17785c7de58aSMatthew G. Knepley } 1779827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1780827c4036SVaclav Hapla { 1781d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *)udm->data; 1782827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1783827c4036SVaclav Hapla } 17845de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, udm)); 1785d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(udm, NULL, PETSC_FALSE)); 17864e3744c5SMatthew G. Knepley *dmUnint = udm; 17873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17884e3744c5SMatthew G. Knepley } 1789a7748839SVaclav Hapla 1790d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1791d71ae5a4SJacob Faibussowitsch { 1792a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1793a7748839SVaclav Hapla MPI_Comm comm; 1794a7748839SVaclav Hapla 1795a7748839SVaclav Hapla PetscFunctionBegin; 17969566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 17979566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 17989566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1799a7748839SVaclav Hapla 1800a7748839SVaclav Hapla if (depth == dim) { 1801a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1802a7748839SVaclav Hapla if (!dim) goto finish; 1803a7748839SVaclav Hapla 1804a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 18059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd)); 1806a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) { 18079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1808a7748839SVaclav Hapla if (coneSize) { 1809a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1810a7748839SVaclav Hapla goto finish; 1811a7748839SVaclav Hapla } 1812a7748839SVaclav Hapla } 1813a7748839SVaclav Hapla 1814a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1815a7748839SVaclav Hapla for (h = 0; h < dim; h++) { 18169566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 1817a7748839SVaclav Hapla for (p = pStart; p < pEnd; p++) { 18189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1819a7748839SVaclav Hapla if (!coneSize) { 1820a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1821a7748839SVaclav Hapla goto finish; 1822a7748839SVaclav Hapla } 1823a7748839SVaclav Hapla } 1824a7748839SVaclav Hapla } 1825a7748839SVaclav Hapla } else if (depth == 1) { 1826a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1827a7748839SVaclav Hapla } else { 1828a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1829a7748839SVaclav Hapla } 1830a7748839SVaclav Hapla finish: 18313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1832a7748839SVaclav Hapla } 1833a7748839SVaclav Hapla 1834a7748839SVaclav Hapla /*@ 1835*20f4b53cSBarry Smith DMPlexIsInterpolated - Find out to what extent the `DMPLEX` is topologically interpolated. 1836a7748839SVaclav Hapla 1837a7748839SVaclav Hapla Not Collective 1838a7748839SVaclav Hapla 1839a7748839SVaclav Hapla Input Parameter: 1840*20f4b53cSBarry Smith . dm - The `DMPLEX` object 1841a7748839SVaclav Hapla 1842a7748839SVaclav Hapla Output Parameter: 1843*20f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated 1844a7748839SVaclav Hapla 1845a7748839SVaclav Hapla Level: intermediate 1846a7748839SVaclav Hapla 1847a7748839SVaclav Hapla Notes: 1848*20f4b53cSBarry Smith Unlike `DMPlexIsInterpolatedCollective()`, this is NOT collective 18499ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1850*20f4b53cSBarry Smith However, `DMPlexInterpolate()` guarantees the result is the same on all. 18519ade3219SVaclav Hapla 1852*20f4b53cSBarry Smith Unlike `DMPlexIsInterpolatedCollective()`, this cannot return `DMPLEX_INTERPOLATED_MIXED`. 1853a7748839SVaclav Hapla 18549ade3219SVaclav Hapla Developer Notes: 1855*20f4b53cSBarry Smith Initially, plex->interpolated = `DMPLEX_INTERPOLATED_INVALID`. 18569ade3219SVaclav Hapla 1857*20f4b53cSBarry Smith If plex->interpolated == `DMPLEX_INTERPOLATED_INVALID`, `DMPlexIsInterpolated_Internal()` is called. 18589ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 1859*20f4b53cSBarry Smith `DMPLEX_INTERPOLATED_NONE`, `DMPLEX_INTERPOLATED_PARTIAL` or `DMPLEX_INTERPOLATED_FULL`. 18609ade3219SVaclav Hapla 1861*20f4b53cSBarry Smith If plex->interpolated != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolated. 18629ade3219SVaclav Hapla 1863*20f4b53cSBarry Smith `DMPlexInterpolate()` sets plex->interpolated = `DMPLEX_INTERPOLATED_FULL`, 1864*20f4b53cSBarry Smith and DMPlexUninterpolate() sets plex->interpolated = `DMPLEX_INTERPOLATED_NONE`. 18659ade3219SVaclav Hapla 1866*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolatedCollective()` 1867a7748839SVaclav Hapla @*/ 1868d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1869d71ae5a4SJacob Faibussowitsch { 1870a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data; 1871a7748839SVaclav Hapla 1872a7748839SVaclav Hapla PetscFunctionBegin; 1873a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1874a7748839SVaclav Hapla PetscValidPointer(interpolated, 2); 1875a7748839SVaclav Hapla if (plex->interpolated < 0) { 18769566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &plex->interpolated)); 187776bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 1878a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1879a7748839SVaclav Hapla 18809566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated_Internal(dm, &flg)); 188108401ef6SPierre Jolivet PetscCheck(flg == plex->interpolated, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]); 1882a7748839SVaclav Hapla } 1883a7748839SVaclav Hapla *interpolated = plex->interpolated; 18843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1885a7748839SVaclav Hapla } 1886a7748839SVaclav Hapla 1887a7748839SVaclav Hapla /*@ 1888*20f4b53cSBarry Smith DMPlexIsInterpolatedCollective - Find out to what extent the `DMPLEX` is topologically interpolated (in collective manner). 1889a7748839SVaclav Hapla 18902666ff3cSVaclav Hapla Collective 1891a7748839SVaclav Hapla 1892a7748839SVaclav Hapla Input Parameter: 1893*20f4b53cSBarry Smith . dm - The `DMPLEX` object 1894a7748839SVaclav Hapla 1895a7748839SVaclav Hapla Output Parameter: 1896*20f4b53cSBarry Smith . interpolated - Flag whether the `DM` is interpolated 1897a7748839SVaclav Hapla 1898a7748839SVaclav Hapla Level: intermediate 1899a7748839SVaclav Hapla 1900a7748839SVaclav Hapla Notes: 1901*20f4b53cSBarry Smith Unlike `DMPlexIsInterpolated()`, this is collective so the results are guaranteed to be the same on all ranks. 19029ade3219SVaclav Hapla 1903*20f4b53cSBarry Smith This function will return `DMPLEX_INTERPOLATED_MIXED` if the results of `DMPlexIsInterpolated()` are different on different ranks. 19049ade3219SVaclav Hapla 19059ade3219SVaclav Hapla Developer Notes: 1906*20f4b53cSBarry Smith Initially, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_INVALID`. 19079ade3219SVaclav Hapla 1908*20f4b53cSBarry Smith If plex->interpolatedCollective == `DMPLEX_INTERPOLATED_INVALID`, this function calls `DMPlexIsInterpolated()` which sets plex->interpolated. 1909*20f4b53cSBarry Smith `MPI_Allreduce()` is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 1910*20f4b53cSBarry Smith if plex->interpolated varies on different ranks, plex->interpolatedCollective = `DMPLEX_INTERPOLATED_MIXED`, 19119ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 19129ade3219SVaclav Hapla 1913*20f4b53cSBarry Smith If plex->interpolatedCollective != `DMPLEX_INTERPOLATED_INVALID`, this function just returns plex->interpolatedCollective. 1914a7748839SVaclav Hapla 1915*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexInterpolate()`, `DMPlexIsInterpolated()` 1916a7748839SVaclav Hapla @*/ 1917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 1918d71ae5a4SJacob Faibussowitsch { 1919a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *)dm->data; 1920a7748839SVaclav Hapla PetscBool debug = PETSC_FALSE; 1921a7748839SVaclav Hapla 1922a7748839SVaclav Hapla PetscFunctionBegin; 1923a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1924a7748839SVaclav Hapla PetscValidPointer(interpolated, 2); 19259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL)); 1926a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1927a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1928a7748839SVaclav Hapla MPI_Comm comm; 1929a7748839SVaclav Hapla 19309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 19319566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &plex->interpolatedCollective)); 19329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm)); 19339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm)); 1934a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1935a7748839SVaclav Hapla if (debug) { 1936a7748839SVaclav Hapla PetscMPIInt rank; 1937a7748839SVaclav Hapla 19389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 19399566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective])); 19409566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 1941a7748839SVaclav Hapla } 1942a7748839SVaclav Hapla } 1943a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 19443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1945a7748839SVaclav Hapla } 1946