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; 283da9060c4SMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 284da9060c4SMatthew G. Knepley /* 285da9060c4SMatthew G. Knepley 4---- 286da9060c4SMatthew G. Knepley |\-\ \----- 287da9060c4SMatthew G. Knepley | \ -\ \ 288da9060c4SMatthew G. Knepley | 1--\-----2 289da9060c4SMatthew G. Knepley | / \ / 290da9060c4SMatthew G. Knepley |/ \ / 291da9060c4SMatthew G. Knepley 0--------3 292da9060c4SMatthew G. Knepley */ 293da9060c4SMatthew G. Knepley if (numFaces) *numFaces = 5; 294da9060c4SMatthew G. Knepley if (faceTypes) { 295da9060c4SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 296da9060c4SMatthew G. Knepley typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; typesTmp[4] = DM_POLYTOPE_TRIANGLE; 297da9060c4SMatthew G. Knepley *faceTypes = typesTmp; 298da9060c4SMatthew G. Knepley } 299da9060c4SMatthew G. Knepley if (faceSizes) { 300da9060c4SMatthew G. Knepley sizesTmp[0] = 4; 301da9060c4SMatthew G. Knepley sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; sizesTmp[4] = 3; 302da9060c4SMatthew G. Knepley *faceSizes = sizesTmp; 303da9060c4SMatthew G. Knepley } 304da9060c4SMatthew G. Knepley if (faces) { 305da9060c4SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 306da9060c4SMatthew G. Knepley facesTmp[4] = cone[0]; facesTmp[5] = cone[3]; facesTmp[6] = cone[4]; /* Front */ 307da9060c4SMatthew G. Knepley facesTmp[7] = cone[3]; facesTmp[8] = cone[2]; facesTmp[9] = cone[4]; /* Right */ 308da9060c4SMatthew G. Knepley facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[4]; /* Back */ 309da9060c4SMatthew G. Knepley facesTmp[13] = cone[1]; facesTmp[14] = cone[0]; facesTmp[15] = cone[4]; /* Left */ 310da9060c4SMatthew G. Knepley *faces = facesTmp; 311da9060c4SMatthew G. Knepley } 312da9060c4SMatthew 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]; 3359318fe57SMatthew G. Knepley PetscInt depth, d, pStart, 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 */ 4209318fe57SMatthew G. Knepley ierr = DMPlexGetChart(dm, &pStart, &Np);CHKERRQ(ierr); 4219318fe57SMatthew G. Knepley ierr = DMPlexSetChart(idm, pStart, 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. */ 6139dddd249SSatish Balay PetscInt mainCone[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); 643ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 644ffc4695bSBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRMPI(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 } 673ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf, MPIU_2INT, roots, leaves,MPI_REPLACE);CHKERRQ(ierr); 674ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf, MPI_2INT, rootsRanks, leavesRanks,MPI_REPLACE);CHKERRQ(ierr); 675ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf, MPIU_2INT, roots, leaves,MPI_REPLACE);CHKERRQ(ierr); 676ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf, MPI_2INT, rootsRanks, leavesRanks,MPI_REPLACE);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])) { 6859dddd249SSatish Balay /* Translate these two leaves to my cone points; mainCone 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 */ 6899dddd249SSatish Balay mainCone[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 */ 7039dddd249SSatish Balay mainCone[c] = rmine1[o+ind0];CHKERRQ(ierr); 704f80536cbSVaclav Hapla } 7059dddd249SSatish Balay if (debug) {ierr = PetscSynchronizedPrintf(comm, " mainCone=[%4D %4D]\n", mainCone[0], mainCone[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. */ 7089dddd249SSatish Balay ierr = DMPlexOrientCell(dm, p, 2, mainCone);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); 713ffc4695bSBarry Smith ierr = MPI_Barrier(comm);CHKERRMPI(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); 731ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(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); 748ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(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; 767ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(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; 796ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(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); 893ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(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); 992064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 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); 998ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(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); 1075ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE);CHKERRQ(ierr); 1076ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE);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; 1214ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE);CHKERRQ(ierr); 1215ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE);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); 1426*61a622f3SMatthew G. Knepley /* Copy over discretization if it exists */ 1427*61a622f3SMatthew G. Knepley { 1428*61a622f3SMatthew G. Knepley DM cdmA, cdmB; 1429*61a622f3SMatthew G. Knepley PetscDS dsA, dsB; 1430*61a622f3SMatthew G. Knepley PetscObject objA, objB; 1431*61a622f3SMatthew G. Knepley PetscClassId idA, idB; 1432*61a622f3SMatthew G. Knepley const PetscScalar *constants; 1433*61a622f3SMatthew G. Knepley PetscInt cdim, Nc; 1434*61a622f3SMatthew G. Knepley 1435*61a622f3SMatthew G. Knepley ierr = DMGetCoordinateDM(dmA, &cdmA);CHKERRQ(ierr); 1436*61a622f3SMatthew G. Knepley ierr = DMGetCoordinateDM(dmB, &cdmB);CHKERRQ(ierr); 1437*61a622f3SMatthew G. Knepley ierr = DMGetField(cdmA, 0, NULL, &objA);CHKERRQ(ierr); 1438*61a622f3SMatthew G. Knepley ierr = DMGetField(cdmB, 0, NULL, &objB);CHKERRQ(ierr); 1439*61a622f3SMatthew G. Knepley ierr = PetscObjectGetClassId(objA, &idA);CHKERRQ(ierr); 1440*61a622f3SMatthew G. Knepley ierr = PetscObjectGetClassId(objB, &idB);CHKERRQ(ierr); 1441*61a622f3SMatthew G. Knepley if ((idA == PETSCFE_CLASSID) && (idA != idB)) { 1442*61a622f3SMatthew G. Knepley ierr = DMSetField(cdmB, 0, NULL, objA);CHKERRQ(ierr); 1443*61a622f3SMatthew G. Knepley ierr = DMCreateDS(cdmB);CHKERRQ(ierr); 1444*61a622f3SMatthew G. Knepley ierr = DMGetDS(cdmA, &dsA);CHKERRQ(ierr); 1445*61a622f3SMatthew G. Knepley ierr = DMGetDS(cdmB, &dsB);CHKERRQ(ierr); 1446*61a622f3SMatthew G. Knepley ierr = PetscDSGetCoordinateDimension(dsA, &cdim);CHKERRQ(ierr); 1447*61a622f3SMatthew G. Knepley ierr = PetscDSSetCoordinateDimension(dsB, cdim);CHKERRQ(ierr); 1448*61a622f3SMatthew G. Knepley ierr = PetscDSGetConstants(dsA, &Nc, &constants);CHKERRQ(ierr); 1449*61a622f3SMatthew G. Knepley ierr = PetscDSSetConstants(dsB, Nc, (PetscScalar *) constants);CHKERRQ(ierr); 1450*61a622f3SMatthew G. Knepley } 1451*61a622f3SMatthew G. Knepley } 145243eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr); 145343eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr); 145469d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr); 145569d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr); 1456972bc18aSToby Isaac if (coordSectionA == coordSectionB) PetscFunctionReturn(0); 14570bedd6beSMatthew G. Knepley ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr); 14580bedd6beSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 14590bedd6beSMatthew G. Knepley if (Nf > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf); 1460df26b574SMatthew G. Knepley if (!coordSectionB) { 1461df26b574SMatthew G. Knepley PetscInt dim; 1462df26b574SMatthew G. Knepley 1463df26b574SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr); 1464df26b574SMatthew G. Knepley ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr); 1465df26b574SMatthew G. Knepley ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr); 1466df26b574SMatthew G. Knepley ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr); 1467df26b574SMatthew G. Knepley } 146807b0a1fcSMatthew G Knepley ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); 146907b0a1fcSMatthew G Knepley ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr); 147007b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr); 147143eeeb2dSStefano Zampini ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr); 147243eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 1473367003a6SStefano 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); 147443eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 147543eeeb2dSStefano Zampini cE = vEndB; 147643eeeb2dSStefano Zampini lc = PETSC_TRUE; 147743eeeb2dSStefano Zampini } else { 147843eeeb2dSStefano Zampini cS = vStartB; 147943eeeb2dSStefano Zampini cE = vEndB; 148043eeeb2dSStefano Zampini } 148143eeeb2dSStefano Zampini ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr); 148207b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 148307b0a1fcSMatthew G Knepley ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr); 148407b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr); 148507b0a1fcSMatthew G Knepley } 148643eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 148743eeeb2dSStefano Zampini PetscInt c; 148843eeeb2dSStefano Zampini 148943eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 149043eeeb2dSStefano Zampini PetscInt dof; 149143eeeb2dSStefano Zampini 149243eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 149343eeeb2dSStefano Zampini ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr); 149443eeeb2dSStefano Zampini ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr); 149543eeeb2dSStefano Zampini } 149643eeeb2dSStefano Zampini } 149707b0a1fcSMatthew G Knepley ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); 149807b0a1fcSMatthew G Knepley ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr); 149907b0a1fcSMatthew G Knepley ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr); 15008b9ced59SLisandro Dalcin ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr); 150107b0a1fcSMatthew G Knepley ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); 150207b0a1fcSMatthew G Knepley ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr); 150343eeeb2dSStefano Zampini ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr); 150443eeeb2dSStefano Zampini ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr); 150543eeeb2dSStefano Zampini ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr); 150643eeeb2dSStefano Zampini ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr); 150707b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr); 150807b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); 150907b0a1fcSMatthew G Knepley for (v = 0; v < vEndB-vStartB; ++v) { 151043eeeb2dSStefano Zampini PetscInt offA, offB; 151143eeeb2dSStefano Zampini 151243eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr); 151343eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr); 151407b0a1fcSMatthew G Knepley for (d = 0; d < spaceDim; ++d) { 151543eeeb2dSStefano Zampini coordsB[offB+d] = coordsA[offA+d]; 151643eeeb2dSStefano Zampini } 151743eeeb2dSStefano Zampini } 151843eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 151943eeeb2dSStefano Zampini PetscInt c; 152043eeeb2dSStefano Zampini 152143eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 152243eeeb2dSStefano Zampini PetscInt dof, offA, offB; 152343eeeb2dSStefano Zampini 152443eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr); 152543eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr); 152643eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 1527580bdb30SBarry Smith ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr); 152807b0a1fcSMatthew G Knepley } 152907b0a1fcSMatthew G Knepley } 153007b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr); 153107b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); 153207b0a1fcSMatthew G Knepley ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr); 153307b0a1fcSMatthew G Knepley ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); 153407b0a1fcSMatthew G Knepley PetscFunctionReturn(0); 153507b0a1fcSMatthew G Knepley } 15365c386225SMatthew G. Knepley 15374e3744c5SMatthew G. Knepley /*@ 15384e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 15394e3744c5SMatthew G. Knepley 1540d083f849SBarry Smith Collective on dm 15414e3744c5SMatthew G. Knepley 15424e3744c5SMatthew G. Knepley Input Parameter: 15434e3744c5SMatthew G. Knepley . dm - The complete DMPlex object 15444e3744c5SMatthew G. Knepley 15454e3744c5SMatthew G. Knepley Output Parameter: 15464e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices 15474e3744c5SMatthew G. Knepley 15484e3744c5SMatthew G. Knepley Level: intermediate 15494e3744c5SMatthew G. Knepley 155095452b02SPatrick Sanan Notes: 155195452b02SPatrick Sanan It does not copy over the coordinates. 155243eeeb2dSStefano Zampini 15539ade3219SVaclav Hapla Developer Notes: 15549ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 15559ade3219SVaclav Hapla 1556a4a685f2SJacob Faibussowitsch .seealso: DMPlexInterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates() 15574e3744c5SMatthew G. Knepley @*/ 15584e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 15594e3744c5SMatthew G. Knepley { 1560827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 15614e3744c5SMatthew G. Knepley DM udm; 1562412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; 15634e3744c5SMatthew G. Knepley PetscErrorCode ierr; 15644e3744c5SMatthew G. Knepley 15654e3744c5SMatthew G. Knepley PetscFunctionBegin; 156643eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 156743eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 1568c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1569827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1570827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1571827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1572827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 15734e3744c5SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 1574595d4abbSMatthew G. Knepley *dmUnint = dm; 1575595d4abbSMatthew G. Knepley PetscFunctionReturn(0); 15764e3744c5SMatthew G. Knepley } 1577595d4abbSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1578595d4abbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 15794e3744c5SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr); 15804e3744c5SMatthew G. Knepley ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr); 1581c73cfb54SMatthew G. Knepley ierr = DMSetDimension(udm, dim);CHKERRQ(ierr); 15824e3744c5SMatthew G. Knepley ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr); 15834e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1584595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 15854e3744c5SMatthew G. Knepley 15864e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15874e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 15884e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 15894e3744c5SMatthew G. Knepley 15904e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 15914e3744c5SMatthew G. Knepley } 15924e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15934e3744c5SMatthew G. Knepley ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr); 1594595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 15954e3744c5SMatthew G. Knepley } 15964e3744c5SMatthew G. Knepley ierr = DMSetUp(udm);CHKERRQ(ierr); 1597785e854fSJed Brown ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr); 15984e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1599595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 16004e3744c5SMatthew G. Knepley 16014e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 16024e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 16034e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 16044e3744c5SMatthew G. Knepley 16054e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 16064e3744c5SMatthew G. Knepley } 16074e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 16084e3744c5SMatthew G. Knepley ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr); 16094e3744c5SMatthew G. Knepley } 16104e3744c5SMatthew G. Knepley ierr = PetscFree(cone);CHKERRQ(ierr); 16114e3744c5SMatthew G. Knepley ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr); 16124e3744c5SMatthew G. Knepley ierr = DMPlexStratify(udm);CHKERRQ(ierr); 16135c7de58aSMatthew G. Knepley /* Reduce SF */ 16145c7de58aSMatthew G. Knepley { 16155c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 16165c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 16175c7de58aSMatthew G. Knepley const PetscInt *localPoints; 16185c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 16195c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 16205c7de58aSMatthew G. Knepley PetscInt vEnd, numRoots, numLeaves, l; 16215c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 16225c7de58aSMatthew G. Knepley PetscErrorCode ierr; 16235c7de58aSMatthew G. Knepley 16245c7de58aSMatthew G. Knepley /* Get original SF information */ 16255c7de58aSMatthew G. Knepley ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 16265c7de58aSMatthew G. Knepley ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr); 16275c7de58aSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr); 16285c7de58aSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 16295c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 16305c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++; 16315c7de58aSMatthew G. Knepley /* Fill in leaves */ 16325c7de58aSMatthew G. Knepley if (vEnd >= 0) { 16335c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr); 16345c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr); 16355c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 16365c7de58aSMatthew G. Knepley if (localPoints[l] < vEnd) { 16375c7de58aSMatthew G. Knepley localPointsUn[n] = localPoints[l]; 16385c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 16395c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 16405c7de58aSMatthew G. Knepley ++n; 16415c7de58aSMatthew G. Knepley } 16425c7de58aSMatthew G. Knepley } 16435c7de58aSMatthew G. Knepley if (n != numLeavesUn) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn); 16445c7de58aSMatthew G. Knepley ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr); 16455c7de58aSMatthew G. Knepley } 16465c7de58aSMatthew G. Knepley } 164743eeeb2dSStefano Zampini { 164843eeeb2dSStefano Zampini PetscBool isper; 164943eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 165043eeeb2dSStefano Zampini const DMBoundaryType *bd; 165143eeeb2dSStefano Zampini 165243eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 165343eeeb2dSStefano Zampini ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr); 165443eeeb2dSStefano Zampini } 1655827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1656827c4036SVaclav Hapla { 1657d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) udm->data; 1658827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1659827c4036SVaclav Hapla } 16604e3744c5SMatthew G. Knepley *dmUnint = udm; 16614e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 16624e3744c5SMatthew G. Knepley } 1663a7748839SVaclav Hapla 1664a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1665a7748839SVaclav Hapla { 1666a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1667a7748839SVaclav Hapla MPI_Comm comm; 1668a7748839SVaclav Hapla PetscErrorCode ierr; 1669a7748839SVaclav Hapla 1670a7748839SVaclav Hapla PetscFunctionBegin; 1671a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1672a7748839SVaclav Hapla ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1673a7748839SVaclav Hapla ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1674a7748839SVaclav Hapla 1675a7748839SVaclav Hapla if (depth == dim) { 1676a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1677a7748839SVaclav Hapla if (!dim) goto finish; 1678a7748839SVaclav Hapla 1679a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 1680a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr); 1681a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1682a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1683a7748839SVaclav Hapla if (coneSize) { 1684a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1685a7748839SVaclav Hapla goto finish; 1686a7748839SVaclav Hapla } 1687a7748839SVaclav Hapla } 1688a7748839SVaclav Hapla 1689a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1690a7748839SVaclav Hapla for (h=0; h<dim; h++) { 1691a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 1692a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1693a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1694a7748839SVaclav Hapla if (!coneSize) { 1695a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1696a7748839SVaclav Hapla goto finish; 1697a7748839SVaclav Hapla } 1698a7748839SVaclav Hapla } 1699a7748839SVaclav Hapla } 1700a7748839SVaclav Hapla } else if (depth == 1) { 1701a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1702a7748839SVaclav Hapla } else { 1703a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1704a7748839SVaclav Hapla } 1705a7748839SVaclav Hapla finish: 1706a7748839SVaclav Hapla PetscFunctionReturn(0); 1707a7748839SVaclav Hapla } 1708a7748839SVaclav Hapla 1709a7748839SVaclav Hapla /*@ 17109ade3219SVaclav Hapla DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated. 1711a7748839SVaclav Hapla 1712a7748839SVaclav Hapla Not Collective 1713a7748839SVaclav Hapla 1714a7748839SVaclav Hapla Input Parameter: 1715a7748839SVaclav Hapla . dm - The DM object 1716a7748839SVaclav Hapla 1717a7748839SVaclav Hapla Output Parameter: 1718a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1719a7748839SVaclav Hapla 1720a7748839SVaclav Hapla Level: intermediate 1721a7748839SVaclav Hapla 1722a7748839SVaclav Hapla Notes: 17239ade3219SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this is NOT collective 17249ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1725a7748839SVaclav Hapla However, DMPlexInterpolate() guarantees the result is the same on all. 17269ade3219SVaclav Hapla 1727a7748839SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED. 1728a7748839SVaclav Hapla 17299ade3219SVaclav Hapla Developer Notes: 17309ade3219SVaclav Hapla Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID. 17319ade3219SVaclav Hapla 17329ade3219SVaclav Hapla If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called. 17339ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 17349ade3219SVaclav Hapla DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL. 17359ade3219SVaclav Hapla 17369ade3219SVaclav Hapla If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated. 17379ade3219SVaclav Hapla 17389ade3219SVaclav Hapla DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL, 17399ade3219SVaclav Hapla and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 17409ade3219SVaclav Hapla 1741a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective() 1742a7748839SVaclav Hapla @*/ 1743a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1744a7748839SVaclav Hapla { 1745a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1746a7748839SVaclav Hapla PetscErrorCode ierr; 1747a7748839SVaclav Hapla 1748a7748839SVaclav Hapla PetscFunctionBegin; 1749a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1750a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1751a7748839SVaclav Hapla if (plex->interpolated < 0) { 1752a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr); 175376bd3646SJed Brown } else if (PetscDefined (USE_DEBUG)) { 1754a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1755a7748839SVaclav Hapla 1756a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr); 17577fc06600SVaclav 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]); 1758a7748839SVaclav Hapla } 1759a7748839SVaclav Hapla *interpolated = plex->interpolated; 1760a7748839SVaclav Hapla PetscFunctionReturn(0); 1761a7748839SVaclav Hapla } 1762a7748839SVaclav Hapla 1763a7748839SVaclav Hapla /*@ 17649ade3219SVaclav Hapla DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner). 1765a7748839SVaclav Hapla 17662666ff3cSVaclav Hapla Collective 1767a7748839SVaclav Hapla 1768a7748839SVaclav Hapla Input Parameter: 1769a7748839SVaclav Hapla . dm - The DM object 1770a7748839SVaclav Hapla 1771a7748839SVaclav Hapla Output Parameter: 1772a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1773a7748839SVaclav Hapla 1774a7748839SVaclav Hapla Level: intermediate 1775a7748839SVaclav Hapla 1776a7748839SVaclav Hapla Notes: 17779ade3219SVaclav Hapla Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks. 17789ade3219SVaclav Hapla 17799ade3219SVaclav Hapla This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks. 17809ade3219SVaclav Hapla 17819ade3219SVaclav Hapla Developer Notes: 17829ade3219SVaclav Hapla Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID. 17839ade3219SVaclav Hapla 17849ade3219SVaclav Hapla If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated. 17859ade3219SVaclav Hapla MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 17869ade3219SVaclav Hapla if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED, 17879ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 17889ade3219SVaclav Hapla 17899ade3219SVaclav Hapla If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective. 1790a7748839SVaclav Hapla 1791a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated() 1792a7748839SVaclav Hapla @*/ 1793a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 1794a7748839SVaclav Hapla { 1795a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1796a7748839SVaclav Hapla PetscBool debug=PETSC_FALSE; 1797a7748839SVaclav Hapla PetscErrorCode ierr; 1798a7748839SVaclav Hapla 1799a7748839SVaclav Hapla PetscFunctionBegin; 1800a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1801a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1802a7748839SVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr); 1803a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1804a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1805a7748839SVaclav Hapla MPI_Comm comm; 1806a7748839SVaclav Hapla 1807a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1808a7748839SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr); 1809ffc4695bSBarry Smith ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRMPI(ierr); 1810ffc4695bSBarry Smith ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRMPI(ierr); 1811a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1812a7748839SVaclav Hapla if (debug) { 1813a7748839SVaclav Hapla PetscMPIInt rank; 1814a7748839SVaclav Hapla 1815ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1816a7748839SVaclav Hapla ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr); 1817a7748839SVaclav Hapla ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr); 1818a7748839SVaclav Hapla } 1819a7748839SVaclav Hapla } 1820a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 1821a7748839SVaclav Hapla PetscFunctionReturn(0); 1822a7748839SVaclav Hapla } 1823