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 11e8f14785SLisandro Dalcin typedef struct _PetscHashIJKLKey { PetscInt i, j, k, l; } PetscHashIJKLKey; 12e8f14785SLisandro Dalcin 13e8f14785SLisandro Dalcin #define PetscHashIJKLKeyHash(key) \ 14e8f14785SLisandro Dalcin PetscHashCombine(PetscHashCombine(PetscHashInt((key).i),PetscHashInt((key).j)), \ 15e8f14785SLisandro Dalcin PetscHashCombine(PetscHashInt((key).k),PetscHashInt((key).l))) 16e8f14785SLisandro Dalcin 17e8f14785SLisandro Dalcin #define PetscHashIJKLKeyEqual(k1,k2) \ 18e8f14785SLisandro Dalcin (((k1).i==(k2).i) ? ((k1).j==(k2).j) ? ((k1).k==(k2).k) ? ((k1).l==(k2).l) : 0 : 0 : 0) 19e8f14785SLisandro Dalcin 20e8f14785SLisandro Dalcin PETSC_HASH_MAP(HashIJKL, PetscHashIJKLKey, PetscInt, PetscHashIJKLKeyHash, PetscHashIJKLKeyEqual, -1) 21e8f14785SLisandro Dalcin 223be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1}; 233be36e83SMatthew G. Knepley 243be36e83SMatthew G. Knepley typedef struct _PetscHashIJKLRemoteKey { PetscSFNode i, j, k, l; } PetscHashIJKLRemoteKey; 253be36e83SMatthew G. Knepley 263be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \ 273be36e83SMatthew G. Knepley PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index),PetscHashInt((key).j.rank + (key).j.index)), \ 283be36e83SMatthew G. Knepley 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 333be36e83SMatthew G. Knepley PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode) 343be36e83SMatthew G. Knepley 353be36e83SMatthew G. Knepley static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[]) 363be36e83SMatthew G. Knepley { 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 } 503be36e83SMatthew G. Knepley PetscFunctionReturn(0); 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 */ 56412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) 57439ece16SMatthew G. Knepley { 58412e9a14SMatthew G. Knepley DMPolytopeType *typesTmp; 59412e9a14SMatthew G. Knepley PetscInt *sizesTmp, *facesTmp; 60439ece16SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 61439ece16SMatthew G. Knepley PetscErrorCode ierr; 62439ece16SMatthew G. Knepley 63439ece16SMatthew G. Knepley PetscFunctionBegin; 64439ece16SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 65ba2698f1SMatthew G. Knepley if (cone) PetscValidIntPointer(cone, 3); 66439ece16SMatthew G. Knepley ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 67412e9a14SMatthew G. Knepley if (faceTypes) {ierr = DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &typesTmp);CHKERRQ(ierr);} 68412e9a14SMatthew G. Knepley if (faceSizes) {ierr = DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &sizesTmp);CHKERRQ(ierr);} 6969291d52SBarry Smith if (faces) {ierr = DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp);CHKERRQ(ierr);} 70ba2698f1SMatthew G. Knepley switch (ct) { 71ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 72ba2698f1SMatthew G. Knepley if (numFaces) *numFaces = 0; 73ba2698f1SMatthew G. Knepley break; 74ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 75412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 2; 76412e9a14SMatthew G. Knepley if (faceTypes) { 77412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT; 78412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 79412e9a14SMatthew G. Knepley } 80412e9a14SMatthew G. Knepley if (faceSizes) { 81412e9a14SMatthew G. Knepley sizesTmp[0] = 1; sizesTmp[1] = 1; 82412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 83412e9a14SMatthew G. Knepley } 84c49d9212SMatthew G. Knepley if (faces) { 85c49d9212SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 86c49d9212SMatthew G. Knepley *faces = facesTmp; 87c49d9212SMatthew G. Knepley } 88412e9a14SMatthew G. Knepley break; 89412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 90c49d9212SMatthew G. Knepley if (numFaces) *numFaces = 2; 91412e9a14SMatthew G. Knepley if (faceTypes) { 92412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT; 93412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 94412e9a14SMatthew G. Knepley } 95412e9a14SMatthew G. Knepley if (faceSizes) { 96412e9a14SMatthew G. Knepley sizesTmp[0] = 1; sizesTmp[1] = 1; 97412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 98412e9a14SMatthew G. Knepley } 99412e9a14SMatthew G. Knepley if (faces) { 100412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 101412e9a14SMatthew G. Knepley *faces = facesTmp; 102412e9a14SMatthew G. Knepley } 103c49d9212SMatthew G. Knepley break; 104ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 105412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 3; 106412e9a14SMatthew G. Knepley if (faceTypes) { 107412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT; 108412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 109412e9a14SMatthew G. Knepley } 110412e9a14SMatthew G. Knepley if (faceSizes) { 111412e9a14SMatthew G. Knepley sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; 112412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 113412e9a14SMatthew G. Knepley } 1149a5b13a2SMatthew G Knepley if (faces) { 1159a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1169a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1179a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[0]; 1189a5b13a2SMatthew G Knepley *faces = facesTmp; 1199a5b13a2SMatthew G Knepley } 1209f074e33SMatthew G Knepley break; 121ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 1229a5b13a2SMatthew G Knepley /* Vertices follow right hand rule */ 123412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 124412e9a14SMatthew G. Knepley if (faceTypes) { 125412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT; typesTmp[3] = DM_POLYTOPE_SEGMENT; 126412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 127412e9a14SMatthew G. Knepley } 128412e9a14SMatthew G. Knepley if (faceSizes) { 129412e9a14SMatthew G. Knepley sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2; 130412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 131412e9a14SMatthew G. Knepley } 1329a5b13a2SMatthew G Knepley if (faces) { 1339a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1349a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1359a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[3]; 1369a5b13a2SMatthew G Knepley facesTmp[6] = cone[3]; facesTmp[7] = cone[0]; 1379a5b13a2SMatthew G Knepley *faces = facesTmp; 1389a5b13a2SMatthew G Knepley } 139412e9a14SMatthew G. Knepley break; 140412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 1419a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 142412e9a14SMatthew G. Knepley if (faceTypes) { 143412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_POINT_PRISM_TENSOR; typesTmp[3] = DM_POLYTOPE_POINT_PRISM_TENSOR; 144412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 145412e9a14SMatthew G. Knepley } 146412e9a14SMatthew G. Knepley if (faceSizes) { 147412e9a14SMatthew G. Knepley sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2; 148412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 149412e9a14SMatthew G. Knepley } 150412e9a14SMatthew G. Knepley if (faces) { 151412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 152412e9a14SMatthew G. Knepley facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; 153412e9a14SMatthew G. Knepley facesTmp[4] = cone[0]; facesTmp[5] = cone[2]; 154412e9a14SMatthew G. Knepley facesTmp[6] = cone[1]; facesTmp[7] = cone[3]; 155412e9a14SMatthew G. Knepley *faces = facesTmp; 156412e9a14SMatthew G. Knepley } 1579f074e33SMatthew G Knepley break; 158ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 1592e1b13c2SMatthew G. Knepley /* Vertices of first face follow right hand rule and normal points away from last vertex */ 160412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 161412e9a14SMatthew G. Knepley if (faceTypes) { 162412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; 163412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 164412e9a14SMatthew G. Knepley } 165412e9a14SMatthew G. Knepley if (faceSizes) { 166412e9a14SMatthew G. Knepley sizesTmp[0] = 3; sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; 167412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 168412e9a14SMatthew G. Knepley } 1699a5b13a2SMatthew G Knepley if (faces) { 1702e1b13c2SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; 1712e1b13c2SMatthew G. Knepley facesTmp[3] = cone[0]; facesTmp[4] = cone[3]; facesTmp[5] = cone[1]; 1722e1b13c2SMatthew G. Knepley facesTmp[6] = cone[0]; facesTmp[7] = cone[2]; facesTmp[8] = cone[3]; 1732e1b13c2SMatthew G. Knepley facesTmp[9] = cone[2]; facesTmp[10] = cone[1]; facesTmp[11] = cone[3]; 1749a5b13a2SMatthew G Knepley *faces = facesTmp; 1759a5b13a2SMatthew G Knepley } 1769a5b13a2SMatthew G Knepley break; 177ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 178e368ef20SMatthew G. Knepley /* 7--------6 179e368ef20SMatthew G. Knepley /| /| 180e368ef20SMatthew G. Knepley / | / | 181e368ef20SMatthew G. Knepley 4--------5 | 182e368ef20SMatthew G. Knepley | | | | 183e368ef20SMatthew G. Knepley | | | | 184e368ef20SMatthew G. Knepley | 1--------2 185e368ef20SMatthew G. Knepley | / | / 186e368ef20SMatthew G. Knepley |/ |/ 187e368ef20SMatthew G. Knepley 0--------3 188e368ef20SMatthew G. Knepley */ 189412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 190412e9a14SMatthew G. Knepley if (faceTypes) { 191412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; 192412e9a14SMatthew G. Knepley typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; typesTmp[5] = DM_POLYTOPE_QUADRILATERAL; 193412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 194412e9a14SMatthew G. Knepley } 195412e9a14SMatthew G. Knepley if (faceSizes) { 196412e9a14SMatthew G. Knepley sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4; 197412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 198412e9a14SMatthew G. Knepley } 1999a5b13a2SMatthew G Knepley if (faces) { 20051cfd6a4SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 20151cfd6a4SMatthew G. Knepley facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; facesTmp[6] = cone[6]; facesTmp[7] = cone[7]; /* Top */ 20251cfd6a4SMatthew G. Knepley facesTmp[8] = cone[0]; facesTmp[9] = cone[3]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; /* Front */ 20351cfd6a4SMatthew G. Knepley facesTmp[12] = cone[2]; facesTmp[13] = cone[1]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; /* Back */ 20451cfd6a4SMatthew G. Knepley facesTmp[16] = cone[3]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; /* Right */ 20551cfd6a4SMatthew G. Knepley facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[1]; /* Left */ 2069a5b13a2SMatthew G Knepley *faces = facesTmp; 2079a5b13a2SMatthew G Knepley } 20899836e0eSStefano Zampini break; 209ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 210412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 211412e9a14SMatthew G. Knepley if (faceTypes) { 212412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; 213412e9a14SMatthew G. Knepley typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; 214412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 215412e9a14SMatthew G. Knepley } 216412e9a14SMatthew G. Knepley if (faceSizes) { 217412e9a14SMatthew G. Knepley sizesTmp[0] = 3; sizesTmp[1] = 3; 218412e9a14SMatthew G. Knepley sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; 219412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 220412e9a14SMatthew G. Knepley } 221ba2698f1SMatthew G. Knepley if (faces) { 222412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; /* Bottom */ 223412e9a14SMatthew G. Knepley facesTmp[3] = cone[3]; facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; /* Top */ 224412e9a14SMatthew G. Knepley facesTmp[6] = cone[0]; facesTmp[7] = cone[2]; facesTmp[8] = cone[4]; facesTmp[9] = cone[3]; /* Back left */ 225412e9a14SMatthew G. Knepley facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[5]; facesTmp[13] = cone[4]; /* Front */ 226412e9a14SMatthew G. Knepley facesTmp[14] = cone[1]; facesTmp[15] = cone[0]; facesTmp[16] = cone[3]; facesTmp[17] = cone[5]; /* Back right */ 227ba2698f1SMatthew G. Knepley *faces = facesTmp; 22899836e0eSStefano Zampini } 22999836e0eSStefano Zampini break; 230ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 231412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 232412e9a14SMatthew G. Knepley if (faceTypes) { 233412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; 234412e9a14SMatthew G. Knepley typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; 235412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 236412e9a14SMatthew G. Knepley } 237412e9a14SMatthew G. Knepley if (faceSizes) { 238412e9a14SMatthew G. Knepley sizesTmp[0] = 3; sizesTmp[1] = 3; 239412e9a14SMatthew G. Knepley sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; 240412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 241412e9a14SMatthew G. Knepley } 24299836e0eSStefano Zampini if (faces) { 243412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; /* Bottom */ 244412e9a14SMatthew G. Knepley facesTmp[3] = cone[3]; facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; /* Top */ 245412e9a14SMatthew G. Knepley facesTmp[6] = cone[0]; facesTmp[7] = cone[1]; facesTmp[8] = cone[3]; facesTmp[9] = cone[4]; /* Back left */ 246412e9a14SMatthew G. Knepley facesTmp[10] = cone[1]; facesTmp[11] = cone[2]; facesTmp[12] = cone[4]; facesTmp[13] = cone[5]; /* Back right */ 247412e9a14SMatthew G. Knepley facesTmp[14] = cone[2]; facesTmp[15] = cone[0]; facesTmp[16] = cone[5]; facesTmp[17] = cone[3]; /* Front */ 24899836e0eSStefano Zampini *faces = facesTmp; 24999836e0eSStefano Zampini } 250412e9a14SMatthew G. Knepley break; 251412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 252412e9a14SMatthew G. Knepley /* 7--------6 253412e9a14SMatthew G. Knepley /| /| 254412e9a14SMatthew G. Knepley / | / | 255412e9a14SMatthew G. Knepley 4--------5 | 256412e9a14SMatthew G. Knepley | | | | 257412e9a14SMatthew G. Knepley | | | | 258412e9a14SMatthew G. Knepley | 3--------2 259412e9a14SMatthew G. Knepley | / | / 260412e9a14SMatthew G. Knepley |/ |/ 261412e9a14SMatthew G. Knepley 0--------1 262412e9a14SMatthew G. Knepley */ 263412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 264412e9a14SMatthew G. Knepley if (faceTypes) { 265412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; 266412e9a14SMatthew G. Knepley typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR; 267412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 268412e9a14SMatthew G. Knepley } 269412e9a14SMatthew G. Knepley if (faceSizes) { 270412e9a14SMatthew G. Knepley sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4; 271412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 272412e9a14SMatthew G. Knepley } 273412e9a14SMatthew G. Knepley if (faces) { 274412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 275412e9a14SMatthew G. Knepley facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; facesTmp[6] = cone[6]; facesTmp[7] = cone[7]; /* Top */ 276412e9a14SMatthew G. Knepley facesTmp[8] = cone[0]; facesTmp[9] = cone[1]; facesTmp[10] = cone[4]; facesTmp[11] = cone[5]; /* Front */ 277412e9a14SMatthew G. Knepley facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[5]; facesTmp[15] = cone[6]; /* Right */ 278412e9a14SMatthew G. Knepley facesTmp[16] = cone[2]; facesTmp[17] = cone[3]; facesTmp[18] = cone[6]; facesTmp[19] = cone[7]; /* Back */ 279412e9a14SMatthew G. Knepley facesTmp[20] = cone[3]; facesTmp[21] = cone[0]; facesTmp[22] = cone[7]; facesTmp[23] = cone[4]; /* Left */ 280412e9a14SMatthew G. Knepley *faces = facesTmp; 281412e9a14SMatthew G. Knepley } 28299836e0eSStefano Zampini break; 283*da9060c4SMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 284*da9060c4SMatthew G. Knepley /* 285*da9060c4SMatthew G. Knepley 4---- 286*da9060c4SMatthew G. Knepley |\-\ \----- 287*da9060c4SMatthew G. Knepley | \ -\ \ 288*da9060c4SMatthew G. Knepley | 1--\-----2 289*da9060c4SMatthew G. Knepley | / \ / 290*da9060c4SMatthew G. Knepley |/ \ / 291*da9060c4SMatthew G. Knepley 0--------3 292*da9060c4SMatthew G. Knepley */ 293*da9060c4SMatthew G. Knepley if (numFaces) *numFaces = 5; 294*da9060c4SMatthew G. Knepley if (faceTypes) { 295*da9060c4SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 296*da9060c4SMatthew G. Knepley typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; typesTmp[4] = DM_POLYTOPE_TRIANGLE; 297*da9060c4SMatthew G. Knepley *faceTypes = typesTmp; 298*da9060c4SMatthew G. Knepley } 299*da9060c4SMatthew G. Knepley if (faceSizes) { 300*da9060c4SMatthew G. Knepley sizesTmp[0] = 4; 301*da9060c4SMatthew G. Knepley sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; sizesTmp[4] = 3; 302*da9060c4SMatthew G. Knepley *faceSizes = sizesTmp; 303*da9060c4SMatthew G. Knepley } 304*da9060c4SMatthew G. Knepley if (faces) { 305*da9060c4SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 306*da9060c4SMatthew G. Knepley facesTmp[4] = cone[0]; facesTmp[5] = cone[3]; facesTmp[6] = cone[4]; /* Front */ 307*da9060c4SMatthew G. Knepley facesTmp[7] = cone[3]; facesTmp[8] = cone[2]; facesTmp[9] = cone[4]; /* Right */ 308*da9060c4SMatthew G. Knepley facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[4]; /* Back */ 309*da9060c4SMatthew G. Knepley facesTmp[13] = cone[1]; facesTmp[14] = cone[0]; facesTmp[15] = cone[4]; /* Left */ 310*da9060c4SMatthew G. Knepley *faces = facesTmp; 311*da9060c4SMatthew G. Knepley } 312*da9060c4SMatthew G. Knepley break; 313ba2698f1SMatthew G. Knepley default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]); 31499836e0eSStefano Zampini } 31599836e0eSStefano Zampini PetscFunctionReturn(0); 31699836e0eSStefano Zampini } 31799836e0eSStefano Zampini 318412e9a14SMatthew G. Knepley PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) 31999836e0eSStefano Zampini { 32099836e0eSStefano Zampini PetscErrorCode ierr; 32199836e0eSStefano Zampini 32299836e0eSStefano Zampini PetscFunctionBegin; 323412e9a14SMatthew G. Knepley if (faceTypes) {ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceTypes);CHKERRQ(ierr);} 324412e9a14SMatthew G. Knepley if (faceSizes) {ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceSizes);CHKERRQ(ierr);} 32599836e0eSStefano Zampini if (faces) {ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces);CHKERRQ(ierr);} 32699836e0eSStefano Zampini PetscFunctionReturn(0); 32799836e0eSStefano Zampini } 32899836e0eSStefano Zampini 3299a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */ 3309a5b13a2SMatthew G Knepley static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm) 3319f074e33SMatthew G Knepley { 332412e9a14SMatthew G. Knepley DMLabel ctLabel; 3339a5b13a2SMatthew G Knepley PetscHashIJKL faceTable; 334412e9a14SMatthew G. Knepley PetscInt faceTypeNum[DM_NUM_POLYTOPES]; 335412e9a14SMatthew G. Knepley PetscInt depth, d, Np, cStart, cEnd, c, fStart, fEnd; 3369f074e33SMatthew G Knepley PetscErrorCode ierr; 3379f074e33SMatthew G Knepley 3389f074e33SMatthew G Knepley PetscFunctionBegin; 3399a5b13a2SMatthew G Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 34099836e0eSStefano Zampini ierr = PetscHashIJKLCreate(&faceTable);CHKERRQ(ierr); 341412e9a14SMatthew G. Knepley ierr = PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES);CHKERRQ(ierr); 342412e9a14SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd);CHKERRQ(ierr); 343412e9a14SMatthew G. Knepley /* Number new faces and save face vertices in hash table */ 344412e9a14SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart);CHKERRQ(ierr); 345412e9a14SMatthew G. Knepley fEnd = fStart; 346412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 347412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 348412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 349ba2698f1SMatthew G. Knepley DMPolytopeType ct; 350412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 35199836e0eSStefano Zampini 352ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 35399836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 354412e9a14SMatthew G. Knepley ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 355412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 356412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 357412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 358412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 3599a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 360e8f14785SLisandro Dalcin PetscHashIter iter; 361e8f14785SLisandro Dalcin PetscBool missing; 3629f074e33SMatthew G Knepley 363412e9a14SMatthew G. Knepley if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize); 364412e9a14SMatthew G. Knepley key.i = face[0]; 365412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 366412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 367412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 368302440fdSBarry Smith ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 369e8f14785SLisandro Dalcin ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 370e9fa77a1SMatthew G. Knepley if (missing) { 371412e9a14SMatthew G. Knepley ierr = PetscHashIJKLIterSet(faceTable, iter, fEnd++);CHKERRQ(ierr); 372412e9a14SMatthew G. Knepley ++faceTypeNum[faceType]; 373e9fa77a1SMatthew G. Knepley } 3749a5b13a2SMatthew G Knepley } 375412e9a14SMatthew G. Knepley ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 37699836e0eSStefano Zampini } 377412e9a14SMatthew G. Knepley /* We need to number faces contiguously among types */ 378412e9a14SMatthew G. Knepley { 379412e9a14SMatthew G. Knepley PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0; 38099836e0eSStefano Zampini 381412e9a14SMatthew G. Knepley for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {if (faceTypeNum[ct]) ++numFT; faceTypeStart[ct] = 0;} 382412e9a14SMatthew G. Knepley if (numFT > 1) { 383412e9a14SMatthew G. Knepley ierr = PetscHashIJKLClear(faceTable);CHKERRQ(ierr); 384412e9a14SMatthew G. Knepley faceTypeStart[0] = fStart; 385412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct-1] + faceTypeNum[ct-1]; 386412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 387412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 388412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 389ba2698f1SMatthew G. Knepley DMPolytopeType ct; 390412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 39199836e0eSStefano Zampini 392ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 39399836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 394412e9a14SMatthew G. Knepley ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 395412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 396412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 397412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 398412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 39999836e0eSStefano Zampini PetscHashIJKLKey key; 40099836e0eSStefano Zampini PetscHashIter iter; 40199836e0eSStefano Zampini PetscBool missing; 40299836e0eSStefano Zampini 403412e9a14SMatthew G. Knepley if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize); 404412e9a14SMatthew G. Knepley key.i = face[0]; 405412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 406412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 407412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 40899836e0eSStefano Zampini ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 40999836e0eSStefano Zampini ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 410412e9a14SMatthew G. Knepley if (missing) {ierr = PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++);CHKERRQ(ierr);} 41199836e0eSStefano Zampini } 412412e9a14SMatthew G. Knepley ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 41399836e0eSStefano Zampini } 414412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) { 415412e9a14SMatthew G. Knepley if (faceTypeStart[ct] != faceTypeStart[ct-1] + faceTypeNum[ct]) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent numbering for cell type %s, %D != %D + %D", DMPolytopeTypes[ct], faceTypeStart[ct], faceTypeStart[ct-1], faceTypeNum[ct]); 4169a5b13a2SMatthew G Knepley } 4179a5b13a2SMatthew G Knepley } 418412e9a14SMatthew G. Knepley } 419412e9a14SMatthew G. Knepley /* Add new points, always at the end of the numbering */ 420412e9a14SMatthew G. Knepley ierr = DMPlexGetChart(dm, NULL, &Np);CHKERRQ(ierr); 421412e9a14SMatthew G. Knepley ierr = DMPlexSetChart(idm, 0, Np + (fEnd - fStart));CHKERRQ(ierr); 4229a5b13a2SMatthew G Knepley /* Set cone sizes */ 423412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 424412e9a14SMatthew G. Knepley ierr = DMCreateLabel(idm, "celltype");CHKERRQ(ierr); 425412e9a14SMatthew G. Knepley ierr = DMPlexGetCellTypeLabel(idm, &ctLabel);CHKERRQ(ierr); 4269a5b13a2SMatthew G Knepley for (d = 0; d <= depth; ++d) { 427412e9a14SMatthew G. Knepley DMPolytopeType ct; 428412e9a14SMatthew G. Knepley PetscInt coneSize, pStart, pEnd, p; 4299f074e33SMatthew G Knepley 430412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 431412e9a14SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 432412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4339a5b13a2SMatthew G Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 4349a5b13a2SMatthew G Knepley ierr = DMPlexSetConeSize(idm, p, coneSize);CHKERRQ(ierr); 435412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 436412e9a14SMatthew G. Knepley ierr = DMPlexSetCellType(idm, p, ct);CHKERRQ(ierr); 4379f074e33SMatthew G Knepley } 4389f074e33SMatthew G Knepley } 439412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 440412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 441412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 442412e9a14SMatthew G. Knepley DMPolytopeType ct; 443412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 444412e9a14SMatthew G. Knepley 445412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 446412e9a14SMatthew G. Knepley ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 447412e9a14SMatthew G. Knepley ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 448412e9a14SMatthew G. Knepley ierr = DMPlexSetCellType(idm, c, ct);CHKERRQ(ierr); 449412e9a14SMatthew G. Knepley ierr = DMPlexSetConeSize(idm, c, numFaces);CHKERRQ(ierr); 450412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 451412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 452412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 453412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 454412e9a14SMatthew G. Knepley PetscHashIJKLKey key; 455412e9a14SMatthew G. Knepley PetscHashIter iter; 456412e9a14SMatthew G. Knepley PetscBool missing; 457412e9a14SMatthew G. Knepley PetscInt f; 458412e9a14SMatthew G. Knepley 459412e9a14SMatthew G. Knepley if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize); 460412e9a14SMatthew G. Knepley key.i = face[0]; 461412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 462412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 463412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 464412e9a14SMatthew G. Knepley ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 465412e9a14SMatthew G. Knepley ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 466412e9a14SMatthew G. Knepley if (missing) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %D, lf %D)", c, cf); 467412e9a14SMatthew G. Knepley ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr); 468412e9a14SMatthew G. Knepley ierr = DMPlexSetConeSize(idm, f, faceSize);CHKERRQ(ierr); 469412e9a14SMatthew G. Knepley ierr = DMPlexSetCellType(idm, f, faceType);CHKERRQ(ierr); 470412e9a14SMatthew G. Knepley } 471412e9a14SMatthew G. Knepley ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 4729f074e33SMatthew G Knepley } 4739f074e33SMatthew G Knepley ierr = DMSetUp(idm);CHKERRQ(ierr); 474412e9a14SMatthew G. Knepley /* Initialize cones so we do not need the bash table to tell us that a cone has been set */ 475412e9a14SMatthew G. Knepley { 476412e9a14SMatthew G. Knepley PetscSection cs; 477412e9a14SMatthew G. Knepley PetscInt *cones, csize; 4789a5b13a2SMatthew G Knepley 479412e9a14SMatthew G. Knepley ierr = DMPlexGetConeSection(idm, &cs);CHKERRQ(ierr); 480412e9a14SMatthew G. Knepley ierr = DMPlexGetCones(idm, &cones);CHKERRQ(ierr); 481412e9a14SMatthew G. Knepley ierr = PetscSectionGetStorageSize(cs, &csize);CHKERRQ(ierr); 482412e9a14SMatthew G. Knepley for (c = 0; c < csize; ++c) cones[c] = -1; 483412e9a14SMatthew G. Knepley } 484412e9a14SMatthew G. Knepley /* Set cones */ 485412e9a14SMatthew G. Knepley for (d = 0; d <= depth; ++d) { 486412e9a14SMatthew G. Knepley const PetscInt *cone; 487412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 488412e9a14SMatthew G. Knepley 489412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 490412e9a14SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 491412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4929a5b13a2SMatthew G Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 4939a5b13a2SMatthew G Knepley ierr = DMPlexSetCone(idm, p, cone);CHKERRQ(ierr); 4949a5b13a2SMatthew G Knepley ierr = DMPlexGetConeOrientation(dm, p, &cone);CHKERRQ(ierr); 4959a5b13a2SMatthew G Knepley ierr = DMPlexSetConeOrientation(idm, p, cone);CHKERRQ(ierr); 4969f074e33SMatthew G Knepley } 4979a5b13a2SMatthew G Knepley } 498412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 499412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 500412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 501ba2698f1SMatthew G. Knepley DMPolytopeType ct; 502412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 50399836e0eSStefano Zampini 504ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 50599836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 506412e9a14SMatthew G. Knepley ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 507412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 508412e9a14SMatthew G. Knepley DMPolytopeType faceType = faceTypes[cf]; 509412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 510412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 511412e9a14SMatthew G. Knepley const PetscInt *fcone; 5129a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 513e8f14785SLisandro Dalcin PetscHashIter iter; 514e8f14785SLisandro Dalcin PetscBool missing; 515412e9a14SMatthew G. Knepley PetscInt f; 5169f074e33SMatthew G Knepley 517412e9a14SMatthew G. Knepley if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize); 518412e9a14SMatthew G. Knepley key.i = face[0]; 519412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 520412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 521412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 52299836e0eSStefano Zampini ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 52399836e0eSStefano Zampini ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 52499836e0eSStefano Zampini ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr); 52599836e0eSStefano Zampini ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 526412e9a14SMatthew G. Knepley ierr = DMPlexGetCone(idm, f, &fcone);CHKERRQ(ierr); 527412e9a14SMatthew G. Knepley if (fcone[0] < 0) {ierr = DMPlexSetCone(idm, f, face);CHKERRQ(ierr);} 528412e9a14SMatthew G. Knepley /* TODO This should be unnecessary since we have autoamtic orientation */ 529412e9a14SMatthew G. Knepley { 530a74221b0SStefano Zampini /* when matching hybrid faces in 3D, only few cases are possible. 531a74221b0SStefano Zampini Face traversal however can no longer follow the usual convention, this seems a serious issue to me */ 532a74221b0SStefano Zampini PetscInt tquad_map[4][4] = { {PETSC_MIN_INT, 0,PETSC_MIN_INT,PETSC_MIN_INT}, 533a74221b0SStefano Zampini { -1,PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT}, 534a74221b0SStefano Zampini {PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT, 1}, 535a74221b0SStefano Zampini {PETSC_MIN_INT,PETSC_MIN_INT, -2,PETSC_MIN_INT} }; 536412e9a14SMatthew G. Knepley PetscInt i, i2, j; 537412e9a14SMatthew G. Knepley const PetscInt *cone; 538412e9a14SMatthew G. Knepley PetscInt coneSize, ornt; 539a74221b0SStefano Zampini 540412e9a14SMatthew G. Knepley /* Orient face: Do not allow reverse orientation at the first vertex */ 541412e9a14SMatthew G. Knepley ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 542412e9a14SMatthew G. Knepley ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 543412e9a14SMatthew G. Knepley if (coneSize != faceSize) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %D for face %D should be %D", coneSize, f, faceSize); 544412e9a14SMatthew G. Knepley /* - First find the initial vertex */ 545412e9a14SMatthew G. Knepley for (i = 0; i < faceSize; ++i) if (face[0] == cone[i]) break; 546412e9a14SMatthew G. Knepley /* If we want to compare tensor faces to regular faces, we have to flip them and take the else branch here */ 547412e9a14SMatthew G. Knepley if (faceType == DM_POLYTOPE_SEG_PRISM_TENSOR) { 548a74221b0SStefano Zampini /* find the second vertex */ 549412e9a14SMatthew G. Knepley for (i2 = 0; i2 < faceSize; ++i2) if (face[1] == cone[i2]) break; 550412e9a14SMatthew G. Knepley switch (faceSize) { 551a74221b0SStefano Zampini case 2: 552a74221b0SStefano Zampini ornt = i ? -2 : 0; 553a74221b0SStefano Zampini break; 554a74221b0SStefano Zampini case 4: 555a74221b0SStefano Zampini ornt = tquad_map[i][i2]; 556a74221b0SStefano Zampini break; 557412e9a14SMatthew G. Knepley default: SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unhandled face size %D for face %D in cell %D", faceSize, f, c); 558412e9a14SMatthew G. Knepley } 559412e9a14SMatthew G. Knepley } else { 560412e9a14SMatthew G. Knepley /* Try forward comparison */ 561412e9a14SMatthew G. Knepley for (j = 0; j < faceSize; ++j) if (face[j] != cone[(i+j)%faceSize]) break; 562412e9a14SMatthew G. Knepley if (j == faceSize) { 563412e9a14SMatthew G. Knepley if ((faceSize == 2) && (i == 1)) ornt = -2; 564412e9a14SMatthew G. Knepley else ornt = i; 565412e9a14SMatthew G. Knepley } else { 566412e9a14SMatthew G. Knepley /* Try backward comparison */ 567412e9a14SMatthew G. Knepley for (j = 0; j < faceSize; ++j) if (face[j] != cone[(i+faceSize-j)%faceSize]) break; 568412e9a14SMatthew G. Knepley if (j == faceSize) { 569412e9a14SMatthew G. Knepley if (i == 0) ornt = -faceSize; 570412e9a14SMatthew G. Knepley else ornt = -i; 571412e9a14SMatthew G. Knepley } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not determine orientation of face %D in cell %D", f, c); 572a74221b0SStefano Zampini } 573a74221b0SStefano Zampini } 57499836e0eSStefano Zampini ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr); 57599836e0eSStefano Zampini } 57699836e0eSStefano Zampini } 577412e9a14SMatthew G. Knepley ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 57899836e0eSStefano Zampini } 5799a5b13a2SMatthew G Knepley ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr); 5809a5b13a2SMatthew G Knepley ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 5819a5b13a2SMatthew G Knepley ierr = DMPlexStratify(idm);CHKERRQ(ierr); 5829f074e33SMatthew G Knepley PetscFunctionReturn(0); 5839f074e33SMatthew G Knepley } 5849f074e33SMatthew G Knepley 585f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) 586f80536cbSVaclav Hapla { 587f80536cbSVaclav Hapla PetscInt nleaves; 588f80536cbSVaclav Hapla PetscInt nranks; 589a0d42dbcSVaclav Hapla const PetscMPIInt *ranks=NULL; 590a0d42dbcSVaclav Hapla const PetscInt *roffset=NULL, *rmine=NULL, *rremote=NULL; 591f80536cbSVaclav Hapla PetscInt n, o, r; 592f80536cbSVaclav Hapla PetscErrorCode ierr; 593f80536cbSVaclav Hapla 594f80536cbSVaclav Hapla PetscFunctionBegin; 595dec1416fSJunchao Zhang ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote);CHKERRQ(ierr); 596f80536cbSVaclav Hapla nleaves = roffset[nranks]; 597f80536cbSVaclav Hapla ierr = PetscMalloc2(nleaves, rmine1, nleaves, rremote1);CHKERRQ(ierr); 598f80536cbSVaclav Hapla for (r=0; r<nranks; r++) { 599f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 600f80536cbSVaclav Hapla - to unify order with the other side */ 601f80536cbSVaclav Hapla o = roffset[r]; 602f80536cbSVaclav Hapla n = roffset[r+1] - o; 603580bdb30SBarry Smith ierr = PetscArraycpy(&(*rmine1)[o], &rmine[o], n);CHKERRQ(ierr); 604580bdb30SBarry Smith ierr = PetscArraycpy(&(*rremote1)[o], &rremote[o], n);CHKERRQ(ierr); 605f80536cbSVaclav Hapla ierr = PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]);CHKERRQ(ierr); 606f80536cbSVaclav Hapla } 607f80536cbSVaclav Hapla PetscFunctionReturn(0); 608f80536cbSVaclav Hapla } 609f80536cbSVaclav Hapla 61027d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm) 6112e745bdaSMatthew G. Knepley { 61227d0e99aSVaclav Hapla /* Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */ 61327d0e99aSVaclav Hapla PetscInt masterCone[2]; 614cae7fe92SVaclav Hapla PetscInt (*roots)[2], (*leaves)[2]; 6158a650c75SVaclav Hapla PetscMPIInt (*rootsRanks)[2], (*leavesRanks)[2]; 61627d0e99aSVaclav Hapla 61727d0e99aSVaclav Hapla PetscSF sf=NULL; 618a0d42dbcSVaclav Hapla const PetscInt *locals=NULL; 619a0d42dbcSVaclav Hapla const PetscSFNode *remotes=NULL; 6208a650c75SVaclav Hapla PetscInt nroots, nleaves, p, c; 621f80536cbSVaclav Hapla PetscInt nranks, n, o, r; 622a0d42dbcSVaclav Hapla const PetscMPIInt *ranks=NULL; 623a0d42dbcSVaclav Hapla const PetscInt *roffset=NULL; 624a0d42dbcSVaclav Hapla PetscInt *rmine1=NULL, *rremote1=NULL; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 625a0d42dbcSVaclav Hapla const PetscInt *cone=NULL; 626adeface4SVaclav Hapla PetscInt coneSize, ind0; 6272e745bdaSMatthew G. Knepley MPI_Comm comm; 62827d0e99aSVaclav Hapla PetscMPIInt rank,size; 6292e745bdaSMatthew G. Knepley PetscInt debug = 0; 6302e745bdaSMatthew G. Knepley PetscErrorCode ierr; 6312e745bdaSMatthew G. Knepley 6322e745bdaSMatthew G. Knepley PetscFunctionBegin; 633df6a9fadSVaclav Hapla ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6342e745bdaSMatthew G. Knepley ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes);CHKERRQ(ierr); 6353ede9f65SMatthew G. Knepley if (nroots < 0) PetscFunctionReturn(0); 636f80536cbSVaclav Hapla ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 637dec1416fSJunchao Zhang ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL);CHKERRQ(ierr); 638dc21a0bfSVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-before_fix_dm_view");CHKERRQ(ierr); 63976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) {ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr);} 640f80536cbSVaclav Hapla ierr = SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1);CHKERRQ(ierr); 6418a650c75SVaclav Hapla ierr = PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks);CHKERRQ(ierr); 6422e745bdaSMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 6432e745bdaSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 64427d0e99aSVaclav Hapla ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 6459e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 6469e24d8a0SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6479e24d8a0SVaclav Hapla ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 64827d0e99aSVaclav Hapla if (coneSize < 2) { 64927d0e99aSVaclav Hapla for (c = 0; c < 2; c++) { 65027d0e99aSVaclav Hapla roots[p][c] = -1; 65127d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 65227d0e99aSVaclav Hapla } 65327d0e99aSVaclav Hapla continue; 65427d0e99aSVaclav Hapla } 6552e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 6568a650c75SVaclav Hapla for (c = 0; c < 2; c++) { 6578a650c75SVaclav Hapla ierr = PetscFindInt(cone[c], nleaves, locals, &ind0);CHKERRQ(ierr); 6588a650c75SVaclav Hapla if (ind0 < 0) { 6598a650c75SVaclav Hapla roots[p][c] = cone[c]; 6608a650c75SVaclav Hapla rootsRanks[p][c] = rank; 661c8148b97SVaclav Hapla } else { 6628a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 6638a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 6648a650c75SVaclav Hapla } 6652e745bdaSMatthew G. Knepley } 6662e745bdaSMatthew G. Knepley } 6679e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 6688ccb905dSVaclav Hapla for (c = 0; c < 2; c++) { 6698ccb905dSVaclav Hapla leaves[p][c] = -2; 6708ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 6718ccb905dSVaclav Hapla } 672c8148b97SVaclav Hapla } 6732e745bdaSMatthew G. Knepley ierr = PetscSFBcastBegin(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr); 6748a650c75SVaclav Hapla ierr = PetscSFBcastBegin(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr); 6752e745bdaSMatthew G. Knepley ierr = PetscSFBcastEnd(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr); 6768a650c75SVaclav Hapla ierr = PetscSFBcastEnd(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr); 677c8148b97SVaclav Hapla if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 67827d0e99aSVaclav Hapla if (debug && rank == 0) {ierr = PetscSynchronizedPrintf(comm, "Referenced roots\n");CHKERRQ(ierr);} 6799e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 6809e24d8a0SVaclav Hapla if (leaves[p][0] < 0) continue; 6819e24d8a0SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6829e24d8a0SVaclav Hapla ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 68327d0e99aSVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] %4D: cone=[%4D %4D] roots=[(%d,%4D) (%d,%4D)] leaves=[(%d,%4D) (%d,%4D)]", rank, p, cone[0], cone[1], rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1]);CHKERRQ(ierr);} 68482f5c0aeSVaclav Hapla if ((leaves[p][0] != roots[p][0]) || (leaves[p][1] != roots[p][1]) || (leavesRanks[p][0] != rootsRanks[p][0]) || (leavesRanks[p][1] != rootsRanks[p][1])) { 68527d0e99aSVaclav Hapla /* Translate these two leaves to my cone points; masterCone means desired order p's cone points */ 686f80536cbSVaclav Hapla for (c = 0; c < 2; c++) { 68727d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 68827d0e99aSVaclav Hapla /* A local leave is just taken as it is */ 68927d0e99aSVaclav Hapla masterCone[c] = leaves[p][c]; 69027d0e99aSVaclav Hapla continue; 69127d0e99aSVaclav Hapla } 692f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 693f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 694f80536cbSVaclav Hapla ierr = PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r);CHKERRQ(ierr); 69527d0e99aSVaclav Hapla if (PetscUnlikely(r < 0)) SETERRQ7(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leave (%d,%D): leave rank not found among remote ranks",p,c,cone[c],rootsRanks[p][c],roots[p][c],leavesRanks[p][c],leaves[p][c]); 69627d0e99aSVaclav Hapla if (PetscUnlikely(ranks[r] < 0 || ranks[r] >= size)) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%D c=%D commsize=%d: ranks[%D] = %d makes no sense",p,c,size,r,ranks[r]); 697f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 698f80536cbSVaclav Hapla o = roffset[r]; 699f80536cbSVaclav Hapla n = roffset[r+1] - o; 700f80536cbSVaclav Hapla ierr = PetscFindInt(leaves[p][c], n, &rremote1[o], &ind0);CHKERRQ(ierr); 70127d0e99aSVaclav Hapla if (PetscUnlikely(ind0 < 0)) SETERRQ7(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leave (%d,%D): 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]); 702f80536cbSVaclav Hapla /* Get the corresponding local point */ 703f80536cbSVaclav Hapla masterCone[c] = rmine1[o+ind0];CHKERRQ(ierr); 704f80536cbSVaclav Hapla } 70527d0e99aSVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(comm, " masterCone=[%4D %4D]\n", masterCone[0], masterCone[1]);CHKERRQ(ierr);} 70627d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 707f80536cbSVaclav Hapla /* Vaclav's note: Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */ 708f80536cbSVaclav Hapla ierr = DMPlexOrientCell(dm, p, 2, masterCone);CHKERRQ(ierr); 70927d0e99aSVaclav Hapla } else if (debug) {ierr = PetscSynchronizedPrintf(comm, " ==\n");CHKERRQ(ierr);} 71023aaf07bSVaclav Hapla } 71127d0e99aSVaclav Hapla if (debug) { 71227d0e99aSVaclav Hapla ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 71327d0e99aSVaclav Hapla ierr = MPI_Barrier(comm);CHKERRQ(ierr); 7142e745bdaSMatthew G. Knepley } 715adeface4SVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-after_fix_dm_view");CHKERRQ(ierr); 7168a650c75SVaclav Hapla ierr = PetscFree4(roots, leaves, rootsRanks, leavesRanks);CHKERRQ(ierr); 7177c7bb832SVaclav Hapla ierr = PetscFree2(rmine1, rremote1);CHKERRQ(ierr); 7182e745bdaSMatthew G. Knepley PetscFunctionReturn(0); 7192e745bdaSMatthew G. Knepley } 7202e745bdaSMatthew G. Knepley 7212e72742cSMatthew G. Knepley static PetscErrorCode IntArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], const char valname[], PetscInt n, const PetscInt a[]) 7227bffde78SMichael Lange { 7232e72742cSMatthew G. Knepley PetscInt idx; 7242e72742cSMatthew G. Knepley PetscMPIInt rank; 7252e72742cSMatthew G. Knepley PetscBool flg; 7267bffde78SMichael Lange PetscErrorCode ierr; 7277bffde78SMichael Lange 7287bffde78SMichael Lange PetscFunctionBegin; 7292e72742cSMatthew G. Knepley ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr); 7302e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 7312e72742cSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 7322e72742cSMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr); 7332e72742cSMatthew G. Knepley for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]%s %D %s %D\n", rank, idxname, idx, valname, a[idx]);CHKERRQ(ierr);} 7342e72742cSMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 7352e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7362e72742cSMatthew G. Knepley } 7372e72742cSMatthew G. Knepley 7382e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) 7392e72742cSMatthew G. Knepley { 7402e72742cSMatthew G. Knepley PetscInt idx; 7412e72742cSMatthew G. Knepley PetscMPIInt rank; 7422e72742cSMatthew G. Knepley PetscBool flg; 7432e72742cSMatthew G. Knepley PetscErrorCode ierr; 7442e72742cSMatthew G. Knepley 7452e72742cSMatthew G. Knepley PetscFunctionBegin; 7462e72742cSMatthew G. Knepley ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr); 7472e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 7482e72742cSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 7492e72742cSMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr); 7502e72742cSMatthew G. Knepley if (idxname) { 7512e72742cSMatthew G. Knepley for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]%s %D rank %D index %D\n", rank, idxname, idx, a[idx].rank, a[idx].index);CHKERRQ(ierr);} 7522e72742cSMatthew G. Knepley } else { 7532e72742cSMatthew G. Knepley for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]rank %D index %D\n", rank, a[idx].rank, a[idx].index);CHKERRQ(ierr);} 7542e72742cSMatthew G. Knepley } 7552e72742cSMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 7562e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7572e72742cSMatthew G. Knepley } 7582e72742cSMatthew G. Knepley 7593be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint) 7602e72742cSMatthew G. Knepley { 7613be36e83SMatthew G. Knepley PetscSF sf; 7623be36e83SMatthew G. Knepley const PetscInt *locals; 7633be36e83SMatthew G. Knepley PetscMPIInt rank; 7642e72742cSMatthew G. Knepley PetscErrorCode ierr; 7652e72742cSMatthew G. Knepley 7662e72742cSMatthew G. Knepley PetscFunctionBegin; 7673be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 7683be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7693be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, NULL, &locals, NULL);CHKERRQ(ierr); 7702e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 7712e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 7722e72742cSMatthew G. Knepley } else { 7732e72742cSMatthew G. Knepley PetscHashIJKey key; 7743be36e83SMatthew G. Knepley PetscInt l; 7752e72742cSMatthew G. Knepley 7762e72742cSMatthew G. Knepley key.i = remotePoint.index; 7772e72742cSMatthew G. Knepley key.j = remotePoint.rank; 7783be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(remotehash, key, &l);CHKERRQ(ierr); 7793be36e83SMatthew G. Knepley if (l >= 0) { 7803be36e83SMatthew G. Knepley *localPoint = locals[l]; 7812e72742cSMatthew G. Knepley } else PetscFunctionReturn(1); 7822e72742cSMatthew G. Knepley } 7832e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7842e72742cSMatthew G. Knepley } 7852e72742cSMatthew G. Knepley 7863be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint) 7873be36e83SMatthew G. Knepley { 7883be36e83SMatthew G. Knepley PetscSF sf; 7893be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 7903be36e83SMatthew G. Knepley const PetscSFNode *remotes; 7913be36e83SMatthew G. Knepley PetscInt Nl, l; 7923be36e83SMatthew G. Knepley PetscMPIInt rank; 7933be36e83SMatthew G. Knepley PetscErrorCode ierr; 7943be36e83SMatthew G. Knepley 7953be36e83SMatthew G. Knepley PetscFunctionBegin; 7963be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 7973be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7983be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes);CHKERRQ(ierr); 7993be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 8003be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 8013be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 8023be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 8033be36e83SMatthew G. Knepley ierr = PetscFindInt(localPoint, Nl, locals, &l);CHKERRQ(ierr); 8043be36e83SMatthew G. Knepley if (l < 0) PetscFunctionReturn(1); 8053be36e83SMatthew G. Knepley *remotePoint = remotes[l]; 8063be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8073be36e83SMatthew G. Knepley owned: 8083be36e83SMatthew G. Knepley remotePoint->rank = rank; 8093be36e83SMatthew G. Knepley remotePoint->index = localPoint; 8103be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8113be36e83SMatthew G. Knepley } 8123be36e83SMatthew G. Knepley 8133be36e83SMatthew G. Knepley 8143be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) 8153be36e83SMatthew G. Knepley { 8163be36e83SMatthew G. Knepley PetscSF sf; 8173be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 8183be36e83SMatthew G. Knepley PetscInt Nl, idx; 8193be36e83SMatthew G. Knepley PetscErrorCode ierr; 8203be36e83SMatthew G. Knepley 8213be36e83SMatthew G. Knepley PetscFunctionBegin; 8223be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 8233be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 8243be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL);CHKERRQ(ierr); 8253be36e83SMatthew G. Knepley if (Nl < 0) PetscFunctionReturn(0); 8263be36e83SMatthew G. Knepley ierr = PetscFindInt(p, Nl, locals, &idx);CHKERRQ(ierr); 8273be36e83SMatthew G. Knepley if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);} 8283be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 8293be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 8303be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 8313be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8323be36e83SMatthew G. Knepley } 8333be36e83SMatthew G. Knepley 8343be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) 8353be36e83SMatthew G. Knepley { 8363be36e83SMatthew G. Knepley const PetscInt *cone; 8373be36e83SMatthew G. Knepley PetscInt coneSize, c; 8383be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 8393be36e83SMatthew G. Knepley PetscErrorCode ierr; 8403be36e83SMatthew G. Knepley 8413be36e83SMatthew G. Knepley PetscFunctionBegin; 8423be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8433be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8443be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8453be36e83SMatthew G. Knepley PetscBool pointShared; 8463be36e83SMatthew G. Knepley 8473be36e83SMatthew G. Knepley ierr = DMPlexPointIsShared(dm, cone[c], &pointShared);CHKERRQ(ierr); 8483be36e83SMatthew G. Knepley cShared = (PetscBool) (cShared && pointShared); 8493be36e83SMatthew G. Knepley } 8503be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 8513be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8523be36e83SMatthew G. Knepley } 8533be36e83SMatthew G. Knepley 8543be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) 8553be36e83SMatthew G. Knepley { 8563be36e83SMatthew G. Knepley const PetscInt *cone; 8573be36e83SMatthew G. Knepley PetscInt coneSize, c; 8583be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 8593be36e83SMatthew G. Knepley PetscErrorCode ierr; 8603be36e83SMatthew G. Knepley 8613be36e83SMatthew G. Knepley PetscFunctionBegin; 8623be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8633be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8643be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8653be36e83SMatthew G. Knepley PetscSFNode rcp; 8663be36e83SMatthew G. Knepley 8673be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cone[c], &rcp); 8683be36e83SMatthew G. Knepley if (ierr) { 8693be36e83SMatthew G. Knepley cmin = missing; 8703be36e83SMatthew G. Knepley } else { 8713be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 8723be36e83SMatthew G. Knepley } 8733be36e83SMatthew G. Knepley } 8743be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 8753be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8763be36e83SMatthew G. Knepley } 8773be36e83SMatthew G. Knepley 8783be36e83SMatthew G. Knepley /* 8793be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 8803be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 8813be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 8823be36e83SMatthew G. Knepley */ 8833be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) 8843be36e83SMatthew G. Knepley { 8853be36e83SMatthew G. Knepley MPI_Comm comm; 8863be36e83SMatthew G. Knepley const PetscInt *support; 887cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height; 8883be36e83SMatthew G. Knepley PetscMPIInt rank; 8893be36e83SMatthew G. Knepley PetscErrorCode ierr; 8903be36e83SMatthew G. Knepley 8913be36e83SMatthew G. Knepley PetscFunctionBegin; 8923be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8933be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 894cf4dc471SVaclav Hapla ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 895cf4dc471SVaclav Hapla ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 896cf4dc471SVaclav Hapla ierr = DMPlexGetPointHeight(dm, p, &height);CHKERRQ(ierr); 897cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight+1) { 898cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */ 899cf4dc471SVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Skipping face %D to avoid adding cell to hashmap since this is nonoverlapping mesh\n", rank, p);CHKERRQ(ierr);} 900cf4dc471SVaclav Hapla PetscFunctionReturn(0); 901cf4dc471SVaclav Hapla } 9023be36e83SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 9033be36e83SMatthew G. Knepley ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 9043be36e83SMatthew G. Knepley if (candidates) {ierr = PetscSectionGetOffset(candidateSection, p, &off);CHKERRQ(ierr);} 9053be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 9063be36e83SMatthew G. Knepley const PetscInt face = support[s]; 9073be36e83SMatthew G. Knepley const PetscInt *cone; 9083be36e83SMatthew G. Knepley PetscSFNode cpmin={-1,-1}, rp={-1,-1}; 9093be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 9103be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 9113be36e83SMatthew G. Knepley PetscHashIJKey key; 9123be36e83SMatthew G. Knepley 9133be36e83SMatthew G. Knepley /* Only add point once */ 9143be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Support face %D\n", rank, face);CHKERRQ(ierr);} 9153be36e83SMatthew G. Knepley key.i = p; 9163be36e83SMatthew G. Knepley key.j = face; 9173be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(faceHash, key, &f);CHKERRQ(ierr); 9183be36e83SMatthew G. Knepley if (f >= 0) continue; 9193be36e83SMatthew G. Knepley ierr = DMPlexConeIsShared(dm, face, &isShared);CHKERRQ(ierr); 9203be36e83SMatthew G. Knepley ierr = DMPlexGetConeMinimum(dm, face, &cpmin);CHKERRQ(ierr); 9213be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, p, &rp);CHKERRQ(ierr); 9223be36e83SMatthew G. Knepley if (debug) { 9233be36e83SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] Face point %D is shared: %d\n", rank, face, (int) isShared);CHKERRQ(ierr); 9243be36e83SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] Global point (%D, %D) Min Cone Point (%D, %D)\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index);CHKERRQ(ierr); 9253be36e83SMatthew G. Knepley } 9263be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 9273be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 9283be36e83SMatthew G. Knepley if (candidates) { 9293be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Adding shared face %D at idx %D\n[%d] ", rank, face, idx, rank);CHKERRQ(ierr);} 9303be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 9313be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 9323be36e83SMatthew G. Knepley candidates[off+idx].rank = -1; 9333be36e83SMatthew G. Knepley candidates[off+idx++].index = coneSize-1; 9343be36e83SMatthew G. Knepley candidates[off+idx].rank = rank; 9353be36e83SMatthew G. Knepley candidates[off+idx++].index = face; 9363be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9373be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 9383be36e83SMatthew G. Knepley 9393be36e83SMatthew G. Knepley if (cp == p) continue; 9403be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx]);CHKERRQ(ierr); 9413be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index);CHKERRQ(ierr);} 9423be36e83SMatthew G. Knepley ++idx; 9433be36e83SMatthew G. Knepley } 9443be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "\n");CHKERRQ(ierr);} 9453be36e83SMatthew G. Knepley } else { 9463be36e83SMatthew G. Knepley /* Add cone size to section */ 9473be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %D\n", rank, face);CHKERRQ(ierr);} 9483be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 9493be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 9503be36e83SMatthew G. Knepley ierr = PetscSectionAddDof(candidateSection, p, coneSize+1);CHKERRQ(ierr); 9513be36e83SMatthew G. Knepley } 9523be36e83SMatthew G. Knepley } 9533be36e83SMatthew G. Knepley } 9543be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9553be36e83SMatthew G. Knepley } 9563be36e83SMatthew G. Knepley 9572e72742cSMatthew G. Knepley /*@ 9582e72742cSMatthew G. Knepley DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation 9592e72742cSMatthew G. Knepley 960d083f849SBarry Smith Collective on dm 9612e72742cSMatthew G. Knepley 9622e72742cSMatthew G. Knepley Input Parameters: 9632e72742cSMatthew G. Knepley + dm - The interpolated DM 9642e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points 9652e72742cSMatthew G. Knepley 9662e72742cSMatthew G. Knepley Output Parameter: 9672e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points 9682e72742cSMatthew G. Knepley 969f0cfc026SVaclav Hapla Level: developer 9702e72742cSMatthew G. Knepley 9712e72742cSMatthew G. Knepley Note: All debugging for this process can be turned on with the options: -dm_interp_pre_view -petscsf_interp_pre_view -petscsection_interp_candidate_view -petscsection_interp_candidate_remote_view -petscsection_interp_claim_view -petscsf_interp_pre_view -dmplex_interp_debug 9722e72742cSMatthew G. Knepley 9732e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate() 9742e72742cSMatthew G. Knepley @*/ 975e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 9762e72742cSMatthew G. Knepley { 9773be36e83SMatthew G. Knepley MPI_Comm comm; 9783be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 9793be36e83SMatthew G. Knepley PetscHMapI claimshash; 9803be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 9813be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 9822e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 9832e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 9843be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 9853be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 9863be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 987f0cfc026SVaclav Hapla PetscMPIInt rank; 9882e72742cSMatthew G. Knepley PetscErrorCode ierr; 9892e72742cSMatthew G. Knepley 9902e72742cSMatthew G. Knepley PetscFunctionBegin; 991f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9923be36e83SMatthew G. Knepley PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 3); 993f0cfc026SVaclav Hapla ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr); 994f0cfc026SVaclav Hapla if (!flg) PetscFunctionReturn(0); 9953be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 9963be36e83SMatthew G. Knepley ierr = DMSetPointSF(dm, pointSF);CHKERRQ(ierr); 9973be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 9983be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 9993be36e83SMatthew G. Knepley ierr = DMPlexGetOverlap(dm, &ov);CHKERRQ(ierr); 10003be36e83SMatthew G. Knepley if (ov) SETERRQ(comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 10013be36e83SMatthew G. Knepley ierr = PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug);CHKERRQ(ierr); 10022e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view");CHKERRQ(ierr); 10032e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view");CHKERRQ(ierr); 100425afeb17SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 10053be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 10063be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints);CHKERRQ(ierr); 10073be36e83SMatthew G. Knepley if (Nr < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 10083be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&remoteHash);CHKERRQ(ierr); 10093be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 10103be36e83SMatthew G. Knepley PetscHashIJKey key; 10112e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 10122e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 10133be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(remoteHash, key, l);CHKERRQ(ierr); 10147bffde78SMichael Lange } 101566aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 10162e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 10172e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 10183be36e83SMatthew G. Knepley ierr = IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree);CHKERRQ(ierr); 10193be36e83SMatthew G. Knepley /* 10203be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 10213be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 10223be36e83SMatthew G. Knepley \begin{itemize} 10233be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 10243be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 10253be36e83SMatthew G. Knepley \end{itemize} 10263be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 10273be36e83SMatthew 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 10283be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 10293be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 10303be36e83SMatthew G. Knepley */ 10313be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 10323be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 10333be36e83SMatthew G. Knepley The array holds candidate shared faces, each face is refered to by the leaf point */ 10343be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateSection);CHKERRQ(ierr); 10353be36e83SMatthew G. Knepley ierr = PetscSectionSetChart(candidateSection, 0, Nr);CHKERRQ(ierr); 10367bffde78SMichael Lange { 10373be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 10382e72742cSMatthew G. Knepley 10393be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&faceHash);CHKERRQ(ierr); 10403be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 10413be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 10422e72742cSMatthew G. Knepley 10433be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 10443be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug);CHKERRQ(ierr); 10452e72742cSMatthew G. Knepley } 10463be36e83SMatthew G. Knepley ierr = PetscHMapIJClear(faceHash);CHKERRQ(ierr); 10477bffde78SMichael Lange ierr = PetscSectionSetUp(candidateSection);CHKERRQ(ierr); 10487bffde78SMichael Lange ierr = PetscSectionGetStorageSize(candidateSection, &candidatesSize);CHKERRQ(ierr); 10497bffde78SMichael Lange ierr = PetscMalloc1(candidatesSize, &candidates);CHKERRQ(ierr); 10503be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 10513be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 10522e72742cSMatthew G. Knepley 10533be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 10543be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug);CHKERRQ(ierr); 10552e72742cSMatthew G. Knepley } 10563be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&faceHash);CHKERRQ(ierr); 10573be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 10587bffde78SMichael Lange } 10593be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateSection, "Candidate Section");CHKERRQ(ierr); 10602e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view");CHKERRQ(ierr); 10613be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates);CHKERRQ(ierr); 10623be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 10632e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 10647bffde78SMichael Lange { 10657bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 10667bffde78SMichael Lange PetscInt *remoteOffsets; 10672e72742cSMatthew G. Knepley 10687bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 10697bffde78SMichael Lange ierr = PetscSFCreateInverseSF(sfMulti, &sfInverse);CHKERRQ(ierr); 10703be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateRemoteSection);CHKERRQ(ierr); 10713be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection);CHKERRQ(ierr); 10723be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates);CHKERRQ(ierr); 10733be36e83SMatthew G. Knepley ierr = PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize);CHKERRQ(ierr); 10747bffde78SMichael Lange ierr = PetscMalloc1(candidatesRemoteSize, &candidatesRemote);CHKERRQ(ierr); 10757bffde78SMichael Lange ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr); 10767bffde78SMichael Lange ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr); 10777bffde78SMichael Lange ierr = PetscSFDestroy(&sfInverse);CHKERRQ(ierr); 10787bffde78SMichael Lange ierr = PetscSFDestroy(&sfCandidates);CHKERRQ(ierr); 10797bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 10802e72742cSMatthew G. Knepley 10813be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section");CHKERRQ(ierr); 10823be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view");CHKERRQ(ierr); 10833be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote);CHKERRQ(ierr); 10847bffde78SMichael Lange } 10853be36e83SMatthew 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 */ 10867bffde78SMichael Lange { 10873be36e83SMatthew G. Knepley PetscHashIJKLRemote faceTable; 10883be36e83SMatthew G. Knepley PetscInt idx, idx2; 10893be36e83SMatthew G. Knepley 10903be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteCreate(&faceTable);CHKERRQ(ierr); 10912e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 10923be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 10932e72742cSMatthew G. Knepley PetscInt deg; 10943be36e83SMatthew G. Knepley 10952e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 10962e72742cSMatthew G. Knepley PetscInt offset, dof, d; 10972e72742cSMatthew G. Knepley 10983be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx, &dof);CHKERRQ(ierr); 10993be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx, &offset);CHKERRQ(ierr); 11003be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 11012e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11023be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 11033be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 11043be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx+1]; 11053be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 11063be36e83SMatthew G. Knepley PetscSFNode fcp0; 11073be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 11082e72742cSMatthew G. Knepley const PetscInt *join = NULL; 11093be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 11103be36e83SMatthew G. Knepley PetscHashIter iter; 11113be36e83SMatthew G. Knepley PetscBool missing; 11122e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 11132e72742cSMatthew G. Knepley 111466e92ce5SVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking face (%D, %D) at (%D, %D, %D) with cone size %D\n", rank, rface.rank, rface.index, r, idx, d, Np);CHKERRQ(ierr);} 111566e92ce5SVaclav Hapla if (Np > 4) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle face (%D, %D) at (%D, %D, %D) with %D cone points", rface.rank, rface.index, r, idx, d, Np); 11163be36e83SMatthew G. Knepley fcp0.rank = rank; 11173be36e83SMatthew G. Knepley fcp0.index = r; 11183be36e83SMatthew G. Knepley d += Np; 11193be36e83SMatthew G. Knepley /* Put remote face in hash table */ 11203be36e83SMatthew G. Knepley key.i = fcp0; 11213be36e83SMatthew G. Knepley key.j = fcone[0]; 11223be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 11233be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 11243be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 11253be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 11263be36e83SMatthew G. Knepley if (missing) { 11273be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Setting remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 11283be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 11293be36e83SMatthew G. Knepley } else { 11303be36e83SMatthew G. Knepley PetscSFNode oface; 11313be36e83SMatthew G. Knepley 11323be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 11333be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 11343be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 11353be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 11363be36e83SMatthew G. Knepley } 11373be36e83SMatthew G. Knepley } 11383be36e83SMatthew G. Knepley /* Check for local face */ 11392e72742cSMatthew G. Knepley points[0] = r; 11403be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 11413be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p]); 11423be36e83SMatthew G. Knepley if (ierr) break; /* We got a point not in our overlap */ 11433be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking local candidate %D\n", rank, points[p]);CHKERRQ(ierr);} 11447bffde78SMichael Lange } 11452e72742cSMatthew G. Knepley if (ierr) continue; 11463be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 11477bffde78SMichael Lange if (joinSize == 1) { 11483be36e83SMatthew G. Knepley PetscSFNode lface; 11493be36e83SMatthew G. Knepley PetscSFNode oface; 11503be36e83SMatthew G. Knepley 11513be36e83SMatthew G. Knepley /* Always replace with local face */ 11523be36e83SMatthew G. Knepley lface.rank = rank; 11533be36e83SMatthew G. Knepley lface.index = join[0]; 11543be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 11553be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing (%D, %D) with local face (%D, %D)\n", rank, oface.index, oface.rank, lface.index, lface.rank);CHKERRQ(ierr);} 11563be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, lface);CHKERRQ(ierr); 11577bffde78SMichael Lange } 11583be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 11593be36e83SMatthew G. Knepley } 11603be36e83SMatthew G. Knepley } 11613be36e83SMatthew G. Knepley /* Put back faces for this root */ 11623be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 11633be36e83SMatthew G. Knepley PetscInt offset, dof, d; 11643be36e83SMatthew G. Knepley 11653be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx2, &dof);CHKERRQ(ierr); 11663be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx2, &offset);CHKERRQ(ierr); 11673be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 11683be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 11693be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 11703be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 11713be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 11723be36e83SMatthew G. Knepley PetscSFNode fcp0; 11733be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 11743be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 11753be36e83SMatthew G. Knepley PetscHashIter iter; 11763be36e83SMatthew G. Knepley PetscBool missing; 11773be36e83SMatthew G. Knepley 11783be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Entering face at (%D, %D)\n", rank, r, idx);CHKERRQ(ierr);} 11793be36e83SMatthew G. Knepley if (Np > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np); 11803be36e83SMatthew G. Knepley fcp0.rank = rank; 11813be36e83SMatthew G. Knepley fcp0.index = r; 11823be36e83SMatthew G. Knepley d += Np; 11833be36e83SMatthew G. Knepley /* Find remote face in hash table */ 11843be36e83SMatthew G. Knepley key.i = fcp0; 11853be36e83SMatthew G. Knepley key.j = fcone[0]; 11863be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 11873be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 11883be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 11893be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] key (%D, %D) (%D, %D) (%D, %D) (%D, %D)\n", rank, key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index);CHKERRQ(ierr);} 11903be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 11912479783cSJose E. Roman if (missing) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an associated face", r, idx2); 11923be36e83SMatthew G. Knepley else {ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]);CHKERRQ(ierr);} 11937bffde78SMichael Lange } 11947bffde78SMichael Lange } 11957bffde78SMichael Lange } 11962e72742cSMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL);CHKERRQ(ierr);} 11973be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteDestroy(&faceTable);CHKERRQ(ierr); 11987bffde78SMichael Lange } 11993be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 12007bffde78SMichael Lange { 12017bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 12027bffde78SMichael Lange PetscSFNode *remotePointsNew; 12032e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 12043be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 12052e72742cSMatthew G. Knepley 12063be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 12077bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 12083be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &claimSection);CHKERRQ(ierr); 12093be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection);CHKERRQ(ierr); 12103be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims);CHKERRQ(ierr); 12112e72742cSMatthew G. Knepley ierr = PetscSectionGetStorageSize(claimSection, &claimsSize);CHKERRQ(ierr); 12122e72742cSMatthew G. Knepley ierr = PetscMalloc1(claimsSize, &claims);CHKERRQ(ierr); 12133be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 12147bffde78SMichael Lange ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr); 12157bffde78SMichael Lange ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr); 12167bffde78SMichael Lange ierr = PetscSFDestroy(&sfClaims);CHKERRQ(ierr); 12177bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 12183be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) claimSection, "Claim Section");CHKERRQ(ierr); 12192e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view");CHKERRQ(ierr); 12203be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims);CHKERRQ(ierr); 12213be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 12223be36e83SMatthew 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 */ 1223e8f14785SLisandro Dalcin ierr = PetscHMapICreate(&claimshash);CHKERRQ(ierr); 12243be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 12253be36e83SMatthew G. Knepley PetscInt dof, off, d; 12262e72742cSMatthew G. Knepley 12273be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %D\n", rank, r);CHKERRQ(ierr);} 12283be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateSection, r, &dof);CHKERRQ(ierr); 12293be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateSection, r, &off);CHKERRQ(ierr); 12302e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 12313be36e83SMatthew G. Knepley if (claims[off+d].rank >= 0) { 12323be36e83SMatthew G. Knepley const PetscInt faceInd = off+d; 12333be36e83SMatthew G. Knepley const PetscInt Np = candidates[off+d].index; 12342e72742cSMatthew G. Knepley const PetscInt *join = NULL; 12352e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 12362e72742cSMatthew G. Knepley 12373be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Found claim for remote point (%D, %D)\n", rank, claims[faceInd].rank, claims[faceInd].index);CHKERRQ(ierr);} 12383be36e83SMatthew G. Knepley points[0] = r; 12393be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[0]);CHKERRQ(ierr);} 12403be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 12413be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1]);CHKERRQ(ierr); 12423be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[c+1]);CHKERRQ(ierr);} 12432e72742cSMatthew G. Knepley } 12443be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 12452e72742cSMatthew G. Knepley if (joinSize == 1) { 12463be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 12473be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %D for non-remote partner\n", rank, join[0]);CHKERRQ(ierr);} 12483be36e83SMatthew G. Knepley } else { 12493be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Found local face %D\n", rank, join[0]);CHKERRQ(ierr);} 12502e72742cSMatthew G. Knepley ierr = PetscHMapISet(claimshash, join[0], faceInd);CHKERRQ(ierr); 12512e72742cSMatthew G. Knepley } 12523be36e83SMatthew G. Knepley } else { 12533be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank);CHKERRQ(ierr);} 12543be36e83SMatthew G. Knepley } 12553be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 12563be36e83SMatthew G. Knepley } else { 12573be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] No claim for point %D\n", rank, r);CHKERRQ(ierr);} 12583be36e83SMatthew G. Knepley d += claims[off+d].index+1; 12597bffde78SMichael Lange } 12607bffde78SMichael Lange } 12613be36e83SMatthew G. Knepley } 12623be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 12633be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 12643be36e83SMatthew G. Knepley ierr = PetscHMapIGetSize(claimshash, &NlNew);CHKERRQ(ierr); 12657bffde78SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 12663be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &localPointsNew);CHKERRQ(ierr); 12673be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &remotePointsNew);CHKERRQ(ierr); 12683be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 12693be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 12703be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 12713be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 12727bffde78SMichael Lange } 12733be36e83SMatthew G. Knepley p = Nl; 1274e8f14785SLisandro Dalcin ierr = PetscHMapIGetKeys(claimshash, &p, localPointsNew);CHKERRQ(ierr); 12753be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 12763be36e83SMatthew G. Knepley ierr = PetscSortInt(NlNew, &localPointsNew[Nl]);CHKERRQ(ierr); 12773be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 12783be36e83SMatthew G. Knepley PetscInt off; 12793be36e83SMatthew G. Knepley ierr = PetscHMapIGet(claimshash, localPointsNew[p], &off);CHKERRQ(ierr); 12803be36e83SMatthew G. Knepley if (claims[off].rank < 0 || claims[off].index < 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %D, (%D, %D)", localPointsNew[p], claims[off].rank, claims[off].index); 12813be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 12827bffde78SMichael Lange } 12833be36e83SMatthew G. Knepley ierr = PetscSFCreate(comm, &sfPointNew);CHKERRQ(ierr); 12843be36e83SMatthew G. Knepley ierr = PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 12853be36e83SMatthew G. Knepley ierr = PetscSFSetUp(sfPointNew);CHKERRQ(ierr); 12867bffde78SMichael Lange ierr = DMSetPointSF(dm, sfPointNew);CHKERRQ(ierr); 12873be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view");CHKERRQ(ierr); 12887bffde78SMichael Lange ierr = PetscSFDestroy(&sfPointNew);CHKERRQ(ierr); 1289e8f14785SLisandro Dalcin ierr = PetscHMapIDestroy(&claimshash);CHKERRQ(ierr); 12907bffde78SMichael Lange } 12913be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&remoteHash);CHKERRQ(ierr); 12927bffde78SMichael Lange ierr = PetscSectionDestroy(&candidateSection);CHKERRQ(ierr); 12933be36e83SMatthew G. Knepley ierr = PetscSectionDestroy(&candidateRemoteSection);CHKERRQ(ierr); 12947bffde78SMichael Lange ierr = PetscSectionDestroy(&claimSection);CHKERRQ(ierr); 12957bffde78SMichael Lange ierr = PetscFree(candidates);CHKERRQ(ierr); 12967bffde78SMichael Lange ierr = PetscFree(candidatesRemote);CHKERRQ(ierr); 12977bffde78SMichael Lange ierr = PetscFree(claims);CHKERRQ(ierr); 129825afeb17SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 12997bffde78SMichael Lange PetscFunctionReturn(0); 13007bffde78SMichael Lange } 13017bffde78SMichael Lange 1302248eb259SVaclav Hapla /*@ 130380330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 130480330477SMatthew G. Knepley 1305d083f849SBarry Smith Collective on dm 130680330477SMatthew G. Knepley 1307e56d480eSMatthew G. Knepley Input Parameters: 1308e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices 130910a67516SMatthew G. Knepley - dmInt - The interpolated DM 131080330477SMatthew G. Knepley 131180330477SMatthew G. Knepley Output Parameter: 13124e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object 131380330477SMatthew G. Knepley 131480330477SMatthew G. Knepley Level: intermediate 131580330477SMatthew G. Knepley 131695452b02SPatrick Sanan Notes: 131795452b02SPatrick Sanan It does not copy over the coordinates. 131843eeeb2dSStefano Zampini 13199ade3219SVaclav Hapla Developer Notes: 13209ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL. 13219ade3219SVaclav Hapla 1322a4a685f2SJacob Faibussowitsch .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates() 132380330477SMatthew G. Knepley @*/ 13249f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 13259f074e33SMatthew G Knepley { 1326a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 13279a5b13a2SMatthew G Knepley DM idm, odm = dm; 13287bffde78SMichael Lange PetscSF sfPoint; 13292e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 133010a67516SMatthew G. Knepley const char *name; 1331b325530aSVaclav Hapla PetscBool flg=PETSC_TRUE; 13329f074e33SMatthew G Knepley PetscErrorCode ierr; 13339f074e33SMatthew G Knepley 13349f074e33SMatthew G Knepley PetscFunctionBegin; 133510a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 133610a67516SMatthew G. Knepley PetscValidPointer(dmInt, 2); 1337a72f3261SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 13382e1b13c2SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1339c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1340827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1341827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1342827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 134376b791aaSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 134476b791aaSMatthew G. Knepley idm = dm; 1345b21b8912SMatthew G. Knepley } else { 13469a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 13479a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 134810a67516SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 13499a5b13a2SMatthew G Knepley ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 1350c73cfb54SMatthew G. Knepley ierr = DMSetDimension(idm, dim);CHKERRQ(ierr); 13517bffde78SMichael Lange if (depth > 0) { 13527bffde78SMichael Lange ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr); 13537bffde78SMichael Lange ierr = DMGetPointSF(odm, &sfPoint);CHKERRQ(ierr); 135494488200SVaclav Hapla { 13553be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 135694488200SVaclav Hapla PetscInt nroots; 135794488200SVaclav Hapla ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 135894488200SVaclav Hapla if (nroots >= 0) {ierr = DMPlexInterpolatePointSF(idm, sfPoint);CHKERRQ(ierr);} 135994488200SVaclav Hapla } 13607bffde78SMichael Lange } 13619a5b13a2SMatthew G Knepley if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);} 13629a5b13a2SMatthew G Knepley odm = idm; 13639f074e33SMatthew G Knepley } 136410a67516SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 136510a67516SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) idm, name);CHKERRQ(ierr); 136610a67516SMatthew G. Knepley ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr); 13675d80c0bfSVaclav Hapla ierr = DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE);CHKERRQ(ierr); 1368b325530aSVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL);CHKERRQ(ierr); 136927d0e99aSVaclav Hapla if (flg) {ierr = DMPlexOrientInterface_Internal(idm);CHKERRQ(ierr);} 137084699f70SSatish Balay } 137143eeeb2dSStefano Zampini { 137243eeeb2dSStefano Zampini PetscBool isper; 137343eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 137443eeeb2dSStefano Zampini const DMBoundaryType *bd; 137543eeeb2dSStefano Zampini 137643eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 137743eeeb2dSStefano Zampini ierr = DMSetPeriodicity(idm,isper,maxCell,L,bd);CHKERRQ(ierr); 137843eeeb2dSStefano Zampini } 1379827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1380827c4036SVaclav Hapla { 1381d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) idm->data; 1382827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1383827c4036SVaclav Hapla } 13849a5b13a2SMatthew G Knepley *dmInt = idm; 1385a72f3261SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 13869f074e33SMatthew G Knepley PetscFunctionReturn(0); 13879f074e33SMatthew G Knepley } 138807b0a1fcSMatthew G Knepley 138980330477SMatthew G. Knepley /*@ 139080330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 139180330477SMatthew G. Knepley 1392d083f849SBarry Smith Collective on dmA 139380330477SMatthew G. Knepley 139480330477SMatthew G. Knepley Input Parameter: 139580330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates 139680330477SMatthew G. Knepley 139780330477SMatthew G. Knepley Output Parameter: 139880330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates 139980330477SMatthew G. Knepley 140080330477SMatthew G. Knepley Level: intermediate 140180330477SMatthew G. Knepley 140280330477SMatthew G. Knepley Note: This is typically used when adding pieces other than vertices to a mesh 140380330477SMatthew G. Knepley 140465f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 140580330477SMatthew G. Knepley @*/ 140607b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 140707b0a1fcSMatthew G Knepley { 140807b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 140943eeeb2dSStefano Zampini VecType vtype; 141007b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 141107b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 14120bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 141390a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 141443eeeb2dSStefano Zampini PetscBool lc = PETSC_FALSE; 141507b0a1fcSMatthew G Knepley PetscErrorCode ierr; 141607b0a1fcSMatthew G Knepley 141707b0a1fcSMatthew G Knepley PetscFunctionBegin; 141843eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 141943eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 142076b791aaSMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 142190a8aa44SJed Brown ierr = DMGetCoordinateDim(dmA, &cdim);CHKERRQ(ierr); 142290a8aa44SJed Brown ierr = DMSetCoordinateDim(dmB, cdim);CHKERRQ(ierr); 142307b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr); 142407b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr); 142507b0a1fcSMatthew G Knepley if ((vEndA-vStartA) != (vEndB-vStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %d != %d in the second DM", vEndA-vStartA, vEndB-vStartB); 142643eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr); 142743eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr); 142869d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr); 142969d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr); 1430972bc18aSToby Isaac if (coordSectionA == coordSectionB) PetscFunctionReturn(0); 14310bedd6beSMatthew G. Knepley ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr); 14320bedd6beSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 14330bedd6beSMatthew G. Knepley if (Nf > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf); 1434df26b574SMatthew G. Knepley if (!coordSectionB) { 1435df26b574SMatthew G. Knepley PetscInt dim; 1436df26b574SMatthew G. Knepley 1437df26b574SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr); 1438df26b574SMatthew G. Knepley ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr); 1439df26b574SMatthew G. Knepley ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr); 1440df26b574SMatthew G. Knepley ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr); 1441df26b574SMatthew G. Knepley } 144207b0a1fcSMatthew G Knepley ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); 144307b0a1fcSMatthew G Knepley ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr); 144407b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr); 144543eeeb2dSStefano Zampini ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr); 144643eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 1447367003a6SStefano Zampini if ((cEndA-cStartA) != (cEndB-cStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %D != %D in the second DM", cEndA-cStartA, cEndB-cStartB); 144843eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 144943eeeb2dSStefano Zampini cE = vEndB; 145043eeeb2dSStefano Zampini lc = PETSC_TRUE; 145143eeeb2dSStefano Zampini } else { 145243eeeb2dSStefano Zampini cS = vStartB; 145343eeeb2dSStefano Zampini cE = vEndB; 145443eeeb2dSStefano Zampini } 145543eeeb2dSStefano Zampini ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr); 145607b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 145707b0a1fcSMatthew G Knepley ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr); 145807b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr); 145907b0a1fcSMatthew G Knepley } 146043eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 146143eeeb2dSStefano Zampini PetscInt c; 146243eeeb2dSStefano Zampini 146343eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 146443eeeb2dSStefano Zampini PetscInt dof; 146543eeeb2dSStefano Zampini 146643eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 146743eeeb2dSStefano Zampini ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr); 146843eeeb2dSStefano Zampini ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr); 146943eeeb2dSStefano Zampini } 147043eeeb2dSStefano Zampini } 147107b0a1fcSMatthew G Knepley ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); 147207b0a1fcSMatthew G Knepley ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr); 147307b0a1fcSMatthew G Knepley ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr); 14748b9ced59SLisandro Dalcin ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr); 147507b0a1fcSMatthew G Knepley ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); 147607b0a1fcSMatthew G Knepley ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr); 147743eeeb2dSStefano Zampini ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr); 147843eeeb2dSStefano Zampini ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr); 147943eeeb2dSStefano Zampini ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr); 148043eeeb2dSStefano Zampini ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr); 148107b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr); 148207b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); 148307b0a1fcSMatthew G Knepley for (v = 0; v < vEndB-vStartB; ++v) { 148443eeeb2dSStefano Zampini PetscInt offA, offB; 148543eeeb2dSStefano Zampini 148643eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr); 148743eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr); 148807b0a1fcSMatthew G Knepley for (d = 0; d < spaceDim; ++d) { 148943eeeb2dSStefano Zampini coordsB[offB+d] = coordsA[offA+d]; 149043eeeb2dSStefano Zampini } 149143eeeb2dSStefano Zampini } 149243eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 149343eeeb2dSStefano Zampini PetscInt c; 149443eeeb2dSStefano Zampini 149543eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 149643eeeb2dSStefano Zampini PetscInt dof, offA, offB; 149743eeeb2dSStefano Zampini 149843eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr); 149943eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr); 150043eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 1501580bdb30SBarry Smith ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr); 150207b0a1fcSMatthew G Knepley } 150307b0a1fcSMatthew G Knepley } 150407b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr); 150507b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); 150607b0a1fcSMatthew G Knepley ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr); 150707b0a1fcSMatthew G Knepley ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); 150807b0a1fcSMatthew G Knepley PetscFunctionReturn(0); 150907b0a1fcSMatthew G Knepley } 15105c386225SMatthew G. Knepley 15114e3744c5SMatthew G. Knepley /*@ 15124e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 15134e3744c5SMatthew G. Knepley 1514d083f849SBarry Smith Collective on dm 15154e3744c5SMatthew G. Knepley 15164e3744c5SMatthew G. Knepley Input Parameter: 15174e3744c5SMatthew G. Knepley . dm - The complete DMPlex object 15184e3744c5SMatthew G. Knepley 15194e3744c5SMatthew G. Knepley Output Parameter: 15204e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices 15214e3744c5SMatthew G. Knepley 15224e3744c5SMatthew G. Knepley Level: intermediate 15234e3744c5SMatthew G. Knepley 152495452b02SPatrick Sanan Notes: 152595452b02SPatrick Sanan It does not copy over the coordinates. 152643eeeb2dSStefano Zampini 15279ade3219SVaclav Hapla Developer Notes: 15289ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 15299ade3219SVaclav Hapla 1530a4a685f2SJacob Faibussowitsch .seealso: DMPlexInterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates() 15314e3744c5SMatthew G. Knepley @*/ 15324e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 15334e3744c5SMatthew G. Knepley { 1534827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 15354e3744c5SMatthew G. Knepley DM udm; 1536412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; 15374e3744c5SMatthew G. Knepley PetscErrorCode ierr; 15384e3744c5SMatthew G. Knepley 15394e3744c5SMatthew G. Knepley PetscFunctionBegin; 154043eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 154143eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 1542c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1543827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1544827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1545827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1546827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 15474e3744c5SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 1548595d4abbSMatthew G. Knepley *dmUnint = dm; 1549595d4abbSMatthew G. Knepley PetscFunctionReturn(0); 15504e3744c5SMatthew G. Knepley } 1551595d4abbSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1552595d4abbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 15534e3744c5SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr); 15544e3744c5SMatthew G. Knepley ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr); 1555c73cfb54SMatthew G. Knepley ierr = DMSetDimension(udm, dim);CHKERRQ(ierr); 15564e3744c5SMatthew G. Knepley ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr); 15574e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1558595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 15594e3744c5SMatthew G. Knepley 15604e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15614e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 15624e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 15634e3744c5SMatthew G. Knepley 15644e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 15654e3744c5SMatthew G. Knepley } 15664e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15674e3744c5SMatthew G. Knepley ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr); 1568595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 15694e3744c5SMatthew G. Knepley } 15704e3744c5SMatthew G. Knepley ierr = DMSetUp(udm);CHKERRQ(ierr); 1571785e854fSJed Brown ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr); 15724e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1573595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 15744e3744c5SMatthew G. Knepley 15754e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15764e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 15774e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 15784e3744c5SMatthew G. Knepley 15794e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 15804e3744c5SMatthew G. Knepley } 15814e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15824e3744c5SMatthew G. Knepley ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr); 15834e3744c5SMatthew G. Knepley } 15844e3744c5SMatthew G. Knepley ierr = PetscFree(cone);CHKERRQ(ierr); 15854e3744c5SMatthew G. Knepley ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr); 15864e3744c5SMatthew G. Knepley ierr = DMPlexStratify(udm);CHKERRQ(ierr); 15875c7de58aSMatthew G. Knepley /* Reduce SF */ 15885c7de58aSMatthew G. Knepley { 15895c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 15905c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 15915c7de58aSMatthew G. Knepley const PetscInt *localPoints; 15925c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 15935c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 15945c7de58aSMatthew G. Knepley PetscInt vEnd, numRoots, numLeaves, l; 15955c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 15965c7de58aSMatthew G. Knepley PetscErrorCode ierr; 15975c7de58aSMatthew G. Knepley 15985c7de58aSMatthew G. Knepley /* Get original SF information */ 15995c7de58aSMatthew G. Knepley ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 16005c7de58aSMatthew G. Knepley ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr); 16015c7de58aSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr); 16025c7de58aSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 16035c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 16045c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++; 16055c7de58aSMatthew G. Knepley /* Fill in leaves */ 16065c7de58aSMatthew G. Knepley if (vEnd >= 0) { 16075c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr); 16085c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr); 16095c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 16105c7de58aSMatthew G. Knepley if (localPoints[l] < vEnd) { 16115c7de58aSMatthew G. Knepley localPointsUn[n] = localPoints[l]; 16125c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 16135c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 16145c7de58aSMatthew G. Knepley ++n; 16155c7de58aSMatthew G. Knepley } 16165c7de58aSMatthew G. Knepley } 16175c7de58aSMatthew G. Knepley if (n != numLeavesUn) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn); 16185c7de58aSMatthew G. Knepley ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr); 16195c7de58aSMatthew G. Knepley } 16205c7de58aSMatthew G. Knepley } 162143eeeb2dSStefano Zampini { 162243eeeb2dSStefano Zampini PetscBool isper; 162343eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 162443eeeb2dSStefano Zampini const DMBoundaryType *bd; 162543eeeb2dSStefano Zampini 162643eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 162743eeeb2dSStefano Zampini ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr); 162843eeeb2dSStefano Zampini } 1629827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1630827c4036SVaclav Hapla { 1631d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) udm->data; 1632827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1633827c4036SVaclav Hapla } 16344e3744c5SMatthew G. Knepley *dmUnint = udm; 16354e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 16364e3744c5SMatthew G. Knepley } 1637a7748839SVaclav Hapla 1638a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1639a7748839SVaclav Hapla { 1640a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1641a7748839SVaclav Hapla MPI_Comm comm; 1642a7748839SVaclav Hapla PetscErrorCode ierr; 1643a7748839SVaclav Hapla 1644a7748839SVaclav Hapla PetscFunctionBegin; 1645a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1646a7748839SVaclav Hapla ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1647a7748839SVaclav Hapla ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1648a7748839SVaclav Hapla 1649a7748839SVaclav Hapla if (depth == dim) { 1650a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1651a7748839SVaclav Hapla if (!dim) goto finish; 1652a7748839SVaclav Hapla 1653a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 1654a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr); 1655a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1656a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1657a7748839SVaclav Hapla if (coneSize) { 1658a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1659a7748839SVaclav Hapla goto finish; 1660a7748839SVaclav Hapla } 1661a7748839SVaclav Hapla } 1662a7748839SVaclav Hapla 1663a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1664a7748839SVaclav Hapla for (h=0; h<dim; h++) { 1665a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 1666a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1667a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1668a7748839SVaclav Hapla if (!coneSize) { 1669a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1670a7748839SVaclav Hapla goto finish; 1671a7748839SVaclav Hapla } 1672a7748839SVaclav Hapla } 1673a7748839SVaclav Hapla } 1674a7748839SVaclav Hapla } else if (depth == 1) { 1675a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1676a7748839SVaclav Hapla } else { 1677a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1678a7748839SVaclav Hapla } 1679a7748839SVaclav Hapla finish: 1680a7748839SVaclav Hapla PetscFunctionReturn(0); 1681a7748839SVaclav Hapla } 1682a7748839SVaclav Hapla 1683a7748839SVaclav Hapla /*@ 16849ade3219SVaclav Hapla DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated. 1685a7748839SVaclav Hapla 1686a7748839SVaclav Hapla Not Collective 1687a7748839SVaclav Hapla 1688a7748839SVaclav Hapla Input Parameter: 1689a7748839SVaclav Hapla . dm - The DM object 1690a7748839SVaclav Hapla 1691a7748839SVaclav Hapla Output Parameter: 1692a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1693a7748839SVaclav Hapla 1694a7748839SVaclav Hapla Level: intermediate 1695a7748839SVaclav Hapla 1696a7748839SVaclav Hapla Notes: 16979ade3219SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this is NOT collective 16989ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1699a7748839SVaclav Hapla However, DMPlexInterpolate() guarantees the result is the same on all. 17009ade3219SVaclav Hapla 1701a7748839SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED. 1702a7748839SVaclav Hapla 17039ade3219SVaclav Hapla Developer Notes: 17049ade3219SVaclav Hapla Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID. 17059ade3219SVaclav Hapla 17069ade3219SVaclav Hapla If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called. 17079ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 17089ade3219SVaclav Hapla DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL. 17099ade3219SVaclav Hapla 17109ade3219SVaclav Hapla If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated. 17119ade3219SVaclav Hapla 17129ade3219SVaclav Hapla DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL, 17139ade3219SVaclav Hapla and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 17149ade3219SVaclav Hapla 1715a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective() 1716a7748839SVaclav Hapla @*/ 1717a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1718a7748839SVaclav Hapla { 1719a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1720a7748839SVaclav Hapla PetscErrorCode ierr; 1721a7748839SVaclav Hapla 1722a7748839SVaclav Hapla PetscFunctionBegin; 1723a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1724a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1725a7748839SVaclav Hapla if (plex->interpolated < 0) { 1726a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr); 172776bd3646SJed Brown } else if (PetscDefined (USE_DEBUG)) { 1728a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1729a7748839SVaclav Hapla 1730a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr); 17317fc06600SVaclav Hapla if (flg != plex->interpolated) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]); 1732a7748839SVaclav Hapla } 1733a7748839SVaclav Hapla *interpolated = plex->interpolated; 1734a7748839SVaclav Hapla PetscFunctionReturn(0); 1735a7748839SVaclav Hapla } 1736a7748839SVaclav Hapla 1737a7748839SVaclav Hapla /*@ 17389ade3219SVaclav Hapla DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner). 1739a7748839SVaclav Hapla 17402666ff3cSVaclav Hapla Collective 1741a7748839SVaclav Hapla 1742a7748839SVaclav Hapla Input Parameter: 1743a7748839SVaclav Hapla . dm - The DM object 1744a7748839SVaclav Hapla 1745a7748839SVaclav Hapla Output Parameter: 1746a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1747a7748839SVaclav Hapla 1748a7748839SVaclav Hapla Level: intermediate 1749a7748839SVaclav Hapla 1750a7748839SVaclav Hapla Notes: 17519ade3219SVaclav Hapla Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks. 17529ade3219SVaclav Hapla 17539ade3219SVaclav Hapla This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks. 17549ade3219SVaclav Hapla 17559ade3219SVaclav Hapla Developer Notes: 17569ade3219SVaclav Hapla Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID. 17579ade3219SVaclav Hapla 17589ade3219SVaclav Hapla If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated. 17599ade3219SVaclav Hapla MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 17609ade3219SVaclav Hapla if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED, 17619ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 17629ade3219SVaclav Hapla 17639ade3219SVaclav Hapla If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective. 1764a7748839SVaclav Hapla 1765a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated() 1766a7748839SVaclav Hapla @*/ 1767a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 1768a7748839SVaclav Hapla { 1769a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1770a7748839SVaclav Hapla PetscBool debug=PETSC_FALSE; 1771a7748839SVaclav Hapla PetscErrorCode ierr; 1772a7748839SVaclav Hapla 1773a7748839SVaclav Hapla PetscFunctionBegin; 1774a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1775a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1776a7748839SVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr); 1777a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1778a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1779a7748839SVaclav Hapla MPI_Comm comm; 1780a7748839SVaclav Hapla 1781a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1782a7748839SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr); 1783a7748839SVaclav Hapla ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRQ(ierr); 1784a7748839SVaclav Hapla ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRQ(ierr); 1785a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1786a7748839SVaclav Hapla if (debug) { 1787a7748839SVaclav Hapla PetscMPIInt rank; 1788a7748839SVaclav Hapla 1789a7748839SVaclav Hapla ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1790a7748839SVaclav Hapla ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr); 1791a7748839SVaclav Hapla ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr); 1792a7748839SVaclav Hapla } 1793a7748839SVaclav Hapla } 1794a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 1795a7748839SVaclav Hapla PetscFunctionReturn(0); 1796a7748839SVaclav Hapla } 1797