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 { 529412e9a14SMatthew G. Knepley const PetscInt *cone; 530412e9a14SMatthew G. Knepley PetscInt coneSize, ornt; 531a74221b0SStefano Zampini 532412e9a14SMatthew G. Knepley ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 533412e9a14SMatthew G. Knepley ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 534412e9a14SMatthew 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); 535*d89e6e46SMatthew G. Knepley /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */ 536*d89e6e46SMatthew G. Knepley ierr = DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt);CHKERRQ(ierr); 53799836e0eSStefano Zampini ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr); 53899836e0eSStefano Zampini } 53999836e0eSStefano Zampini } 540412e9a14SMatthew G. Knepley ierr = DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 54199836e0eSStefano Zampini } 5429a5b13a2SMatthew G Knepley ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr); 5439a5b13a2SMatthew G Knepley ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 5449a5b13a2SMatthew G Knepley ierr = DMPlexStratify(idm);CHKERRQ(ierr); 5459f074e33SMatthew G Knepley PetscFunctionReturn(0); 5469f074e33SMatthew G Knepley } 5479f074e33SMatthew G Knepley 548f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) 549f80536cbSVaclav Hapla { 550f80536cbSVaclav Hapla PetscInt nleaves; 551f80536cbSVaclav Hapla PetscInt nranks; 552a0d42dbcSVaclav Hapla const PetscMPIInt *ranks=NULL; 553a0d42dbcSVaclav Hapla const PetscInt *roffset=NULL, *rmine=NULL, *rremote=NULL; 554f80536cbSVaclav Hapla PetscInt n, o, r; 555f80536cbSVaclav Hapla PetscErrorCode ierr; 556f80536cbSVaclav Hapla 557f80536cbSVaclav Hapla PetscFunctionBegin; 558dec1416fSJunchao Zhang ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote);CHKERRQ(ierr); 559f80536cbSVaclav Hapla nleaves = roffset[nranks]; 560f80536cbSVaclav Hapla ierr = PetscMalloc2(nleaves, rmine1, nleaves, rremote1);CHKERRQ(ierr); 561f80536cbSVaclav Hapla for (r=0; r<nranks; r++) { 562f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 563f80536cbSVaclav Hapla - to unify order with the other side */ 564f80536cbSVaclav Hapla o = roffset[r]; 565f80536cbSVaclav Hapla n = roffset[r+1] - o; 566580bdb30SBarry Smith ierr = PetscArraycpy(&(*rmine1)[o], &rmine[o], n);CHKERRQ(ierr); 567580bdb30SBarry Smith ierr = PetscArraycpy(&(*rremote1)[o], &rremote[o], n);CHKERRQ(ierr); 568f80536cbSVaclav Hapla ierr = PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]);CHKERRQ(ierr); 569f80536cbSVaclav Hapla } 570f80536cbSVaclav Hapla PetscFunctionReturn(0); 571f80536cbSVaclav Hapla } 572f80536cbSVaclav Hapla 57327d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm) 5742e745bdaSMatthew G. Knepley { 575*d89e6e46SMatthew G. Knepley PetscSF sf; 576*d89e6e46SMatthew G. Knepley const PetscInt *locals; 577*d89e6e46SMatthew G. Knepley const PetscSFNode *remotes; 578*d89e6e46SMatthew G. Knepley const PetscMPIInt *ranks; 579*d89e6e46SMatthew G. Knepley const PetscInt *roffset; 580*d89e6e46SMatthew G. Knepley PetscInt *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 581*d89e6e46SMatthew G. Knepley PetscInt nroots, p, nleaves, nranks, r, maxConeSize = 0; 582*d89e6e46SMatthew G. Knepley PetscInt (*roots)[4], (*leaves)[4], mainCone[4]; 583*d89e6e46SMatthew G. Knepley PetscMPIInt (*rootsRanks)[4], (*leavesRanks)[4]; 5842e745bdaSMatthew G. Knepley MPI_Comm comm; 58527d0e99aSVaclav Hapla PetscMPIInt rank, size; 5862e745bdaSMatthew G. Knepley PetscInt debug = 0; 5872e745bdaSMatthew G. Knepley PetscErrorCode ierr; 5882e745bdaSMatthew G. Knepley 5892e745bdaSMatthew G. Knepley PetscFunctionBegin; 5902e745bdaSMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 591ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 592ffc4695bSBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 593*d89e6e46SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 594*d89e6e46SMatthew G. Knepley ierr = DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view");CHKERRQ(ierr); 595*d89e6e46SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) {ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr);} 596*d89e6e46SMatthew G. Knepley ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes);CHKERRQ(ierr); 597*d89e6e46SMatthew G. Knepley if (nroots < 0) PetscFunctionReturn(0); 598*d89e6e46SMatthew G. Knepley ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 599*d89e6e46SMatthew G. Knepley ierr = SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1);CHKERRQ(ierr); 600*d89e6e46SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 601*d89e6e46SMatthew G. Knepley PetscInt coneSize; 602*d89e6e46SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, locals[p], &coneSize);CHKERRQ(ierr); 603*d89e6e46SMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 604*d89e6e46SMatthew G. Knepley } 605*d89e6e46SMatthew G. Knepley if (maxConeSize > 4) SETERRQ1(comm, PETSC_ERR_SUP, "This method does not support cones of size %D", maxConeSize); 606*d89e6e46SMatthew G. Knepley ierr = PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks);CHKERRQ(ierr); 6079e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 608*d89e6e46SMatthew G. Knepley const PetscInt *cone; 609*d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0; 610*d89e6e46SMatthew G. Knepley 6119e24d8a0SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6129e24d8a0SVaclav Hapla ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 613*d89e6e46SMatthew G. Knepley /* Ignore vertices */ 61427d0e99aSVaclav Hapla if (coneSize < 2) { 615*d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 61627d0e99aSVaclav Hapla roots[p][c] = -1; 61727d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 61827d0e99aSVaclav Hapla } 61927d0e99aSVaclav Hapla continue; 62027d0e99aSVaclav Hapla } 6212e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 622*d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); c++) { 6238a650c75SVaclav Hapla ierr = PetscFindInt(cone[c], nleaves, locals, &ind0);CHKERRQ(ierr); 6248a650c75SVaclav Hapla if (ind0 < 0) { 6258a650c75SVaclav Hapla roots[p][c] = cone[c]; 6268a650c75SVaclav Hapla rootsRanks[p][c] = rank; 627c8148b97SVaclav Hapla } else { 6288a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 6298a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 6308a650c75SVaclav Hapla } 6312e745bdaSMatthew G. Knepley } 632*d89e6e46SMatthew G. Knepley for (c = coneSize; c < 4; c++) { 633*d89e6e46SMatthew G. Knepley roots[p][c] = -1; 634*d89e6e46SMatthew G. Knepley rootsRanks[p][c] = -1; 635*d89e6e46SMatthew G. Knepley } 6362e745bdaSMatthew G. Knepley } 6379e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 638*d89e6e46SMatthew G. Knepley PetscInt c; 639*d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 6408ccb905dSVaclav Hapla leaves[p][c] = -2; 6418ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 6428ccb905dSVaclav Hapla } 643c8148b97SVaclav Hapla } 644*d89e6e46SMatthew G. Knepley ierr = PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE);CHKERRQ(ierr); 645*d89e6e46SMatthew G. Knepley ierr = PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE);CHKERRQ(ierr); 646*d89e6e46SMatthew G. Knepley ierr = PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE);CHKERRQ(ierr); 647*d89e6e46SMatthew G. Knepley ierr = PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE);CHKERRQ(ierr); 648*d89e6e46SMatthew G. Knepley if (debug) { 649*d89e6e46SMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 650*d89e6e46SMatthew G. Knepley if (!rank) {ierr = PetscSynchronizedPrintf(comm, "Referenced roots\n");CHKERRQ(ierr);} 651*d89e6e46SMatthew G. Knepley } 652*d89e6e46SMatthew G. Knepley ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL);CHKERRQ(ierr); 6539e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 654*d89e6e46SMatthew G. Knepley DMPolytopeType ct; 655*d89e6e46SMatthew G. Knepley const PetscInt *cone; 656*d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0, o; 657*d89e6e46SMatthew G. Knepley 658*d89e6e46SMatthew G. Knepley if (leaves[p][0] < 0) continue; /* Ignore vertices */ 659*d89e6e46SMatthew G. Knepley ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 6609e24d8a0SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6619e24d8a0SVaclav Hapla ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 662*d89e6e46SMatthew G. Knepley if (debug) { 663*d89e6e46SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] %4D: cone=[%4D %4D %4D %4D] roots=[(%d,%4D) (%d,%4D) (%d,%4D) (%d,%4D)] leaves=[(%d,%4D) (%d,%4D) (%d,%4D) (%d,%4D)]", 664*d89e6e46SMatthew G. Knepley rank, p, cone[0], cone[1], cone[2], cone[3], 665*d89e6e46SMatthew G. Knepley rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], rootsRanks[p][2], roots[p][2], rootsRanks[p][3], roots[p][3], 666*d89e6e46SMatthew G. Knepley leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1], leavesRanks[p][2], leaves[p][2], leavesRanks[p][3], leaves[p][3]);CHKERRQ(ierr); 667*d89e6e46SMatthew G. Knepley } 668*d89e6e46SMatthew G. Knepley if (leavesRanks[p][0] != rootsRanks[p][0] || leaves[p][0] != roots[p][0] || 669*d89e6e46SMatthew G. Knepley leavesRanks[p][1] != rootsRanks[p][1] || leaves[p][1] != roots[p][1] || 670*d89e6e46SMatthew G. Knepley leavesRanks[p][2] != rootsRanks[p][2] || leaves[p][2] != roots[p][2] || 671*d89e6e46SMatthew G. Knepley leavesRanks[p][3] != rootsRanks[p][3] || leaves[p][3] != roots[p][3]) { 672*d89e6e46SMatthew G. Knepley /* Translate these leaves to my cone points; mainCone means desired order p's cone points */ 673*d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); ++c) { 674*d89e6e46SMatthew G. Knepley PetscInt rS, rN; 675*d89e6e46SMatthew G. Knepley 67627d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 677*d89e6e46SMatthew G. Knepley /* A local leaf is just taken as it is */ 6789dddd249SSatish Balay mainCone[c] = leaves[p][c]; 67927d0e99aSVaclav Hapla continue; 68027d0e99aSVaclav Hapla } 681f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 682f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 683f80536cbSVaclav Hapla ierr = PetscFindMPIInt((PetscMPIInt) leavesRanks[p][c], nranks, ranks, &r);CHKERRQ(ierr); 684*d89e6e46SMatthew G. Knepley if (PetscUnlikely(r < 0)) SETERRQ7(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leaf (%d,%D): leaf rank not found among remote ranks", p, c, cone[c], rootsRanks[p][c], roots[p][c], leavesRanks[p][c], leaves[p][c]); 68527d0e99aSVaclav 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]); 686f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 687*d89e6e46SMatthew G. Knepley rS = roffset[r]; 688*d89e6e46SMatthew G. Knepley rN = roffset[r+1] - rS; 689*d89e6e46SMatthew G. Knepley ierr = PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0);CHKERRQ(ierr); 69027d0e99aSVaclav 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]); 691f80536cbSVaclav Hapla /* Get the corresponding local point */ 692*d89e6e46SMatthew G. Knepley mainCone[c] = rmine1[rS + ind0];CHKERRQ(ierr); 693f80536cbSVaclav Hapla } 694*d89e6e46SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, " mainCone=[%4D %4D %4D %4D]\n", mainCone[0], mainCone[1], mainCone[2], mainCone[3]);CHKERRQ(ierr);} 69527d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 696*d89e6e46SMatthew G. Knepley ierr = DMPolytopeGetOrientation(ct, cone, mainCone, &o);CHKERRQ(ierr); 697*d89e6e46SMatthew G. Knepley ierr = DMPlexOrientPoint(dm, p, o);CHKERRQ(ierr); 69827d0e99aSVaclav Hapla } else if (debug) {ierr = PetscSynchronizedPrintf(comm, " ==\n");CHKERRQ(ierr);} 69923aaf07bSVaclav Hapla } 70027d0e99aSVaclav Hapla if (debug) { 70127d0e99aSVaclav Hapla ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 702ffc4695bSBarry Smith ierr = MPI_Barrier(comm);CHKERRMPI(ierr); 7032e745bdaSMatthew G. Knepley } 704*d89e6e46SMatthew G. Knepley ierr = DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view");CHKERRQ(ierr); 7058a650c75SVaclav Hapla ierr = PetscFree4(roots, leaves, rootsRanks, leavesRanks);CHKERRQ(ierr); 7067c7bb832SVaclav Hapla ierr = PetscFree2(rmine1, rremote1);CHKERRQ(ierr); 7072e745bdaSMatthew G. Knepley PetscFunctionReturn(0); 7082e745bdaSMatthew G. Knepley } 7092e745bdaSMatthew G. Knepley 7102e72742cSMatthew 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[]) 7117bffde78SMichael Lange { 7122e72742cSMatthew G. Knepley PetscInt idx; 7132e72742cSMatthew G. Knepley PetscMPIInt rank; 7142e72742cSMatthew G. Knepley PetscBool flg; 7157bffde78SMichael Lange PetscErrorCode ierr; 7167bffde78SMichael Lange 7177bffde78SMichael Lange PetscFunctionBegin; 7182e72742cSMatthew G. Knepley ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr); 7192e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 720ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 7212e72742cSMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr); 7222e72742cSMatthew 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);} 7232e72742cSMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 7242e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7252e72742cSMatthew G. Knepley } 7262e72742cSMatthew G. Knepley 7272e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) 7282e72742cSMatthew G. Knepley { 7292e72742cSMatthew G. Knepley PetscInt idx; 7302e72742cSMatthew G. Knepley PetscMPIInt rank; 7312e72742cSMatthew G. Knepley PetscBool flg; 7322e72742cSMatthew G. Knepley PetscErrorCode ierr; 7332e72742cSMatthew G. Knepley 7342e72742cSMatthew G. Knepley PetscFunctionBegin; 7352e72742cSMatthew G. Knepley ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr); 7362e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 737ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 7382e72742cSMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr); 7392e72742cSMatthew G. Knepley if (idxname) { 7402e72742cSMatthew 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);} 7412e72742cSMatthew G. Knepley } else { 7422e72742cSMatthew 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);} 7432e72742cSMatthew G. Knepley } 7442e72742cSMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 7452e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7462e72742cSMatthew G. Knepley } 7472e72742cSMatthew G. Knepley 7483be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint) 7492e72742cSMatthew G. Knepley { 7503be36e83SMatthew G. Knepley PetscSF sf; 7513be36e83SMatthew G. Knepley const PetscInt *locals; 7523be36e83SMatthew G. Knepley PetscMPIInt rank; 7532e72742cSMatthew G. Knepley PetscErrorCode ierr; 7542e72742cSMatthew G. Knepley 7552e72742cSMatthew G. Knepley PetscFunctionBegin; 756ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 7573be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7583be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, NULL, &locals, NULL);CHKERRQ(ierr); 7592e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 7602e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 7612e72742cSMatthew G. Knepley } else { 7622e72742cSMatthew G. Knepley PetscHashIJKey key; 7633be36e83SMatthew G. Knepley PetscInt l; 7642e72742cSMatthew G. Knepley 7652e72742cSMatthew G. Knepley key.i = remotePoint.index; 7662e72742cSMatthew G. Knepley key.j = remotePoint.rank; 7673be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(remotehash, key, &l);CHKERRQ(ierr); 7683be36e83SMatthew G. Knepley if (l >= 0) { 7693be36e83SMatthew G. Knepley *localPoint = locals[l]; 7702e72742cSMatthew G. Knepley } else PetscFunctionReturn(1); 7712e72742cSMatthew G. Knepley } 7722e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7732e72742cSMatthew G. Knepley } 7742e72742cSMatthew G. Knepley 7753be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint) 7763be36e83SMatthew G. Knepley { 7773be36e83SMatthew G. Knepley PetscSF sf; 7783be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 7793be36e83SMatthew G. Knepley const PetscSFNode *remotes; 7803be36e83SMatthew G. Knepley PetscInt Nl, l; 7813be36e83SMatthew G. Knepley PetscMPIInt rank; 7823be36e83SMatthew G. Knepley PetscErrorCode ierr; 7833be36e83SMatthew G. Knepley 7843be36e83SMatthew G. Knepley PetscFunctionBegin; 785ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 7863be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7873be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes);CHKERRQ(ierr); 7883be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 7893be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 7903be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 7913be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 7923be36e83SMatthew G. Knepley ierr = PetscFindInt(localPoint, Nl, locals, &l);CHKERRQ(ierr); 7933be36e83SMatthew G. Knepley if (l < 0) PetscFunctionReturn(1); 7943be36e83SMatthew G. Knepley *remotePoint = remotes[l]; 7953be36e83SMatthew G. Knepley PetscFunctionReturn(0); 7963be36e83SMatthew G. Knepley owned: 7973be36e83SMatthew G. Knepley remotePoint->rank = rank; 7983be36e83SMatthew G. Knepley remotePoint->index = localPoint; 7993be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8003be36e83SMatthew G. Knepley } 8013be36e83SMatthew G. Knepley 8023be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) 8033be36e83SMatthew G. Knepley { 8043be36e83SMatthew G. Knepley PetscSF sf; 8053be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 8063be36e83SMatthew G. Knepley PetscInt Nl, idx; 8073be36e83SMatthew G. Knepley PetscErrorCode ierr; 8083be36e83SMatthew G. Knepley 8093be36e83SMatthew G. Knepley PetscFunctionBegin; 8103be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 8113be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 8123be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL);CHKERRQ(ierr); 8133be36e83SMatthew G. Knepley if (Nl < 0) PetscFunctionReturn(0); 8143be36e83SMatthew G. Knepley ierr = PetscFindInt(p, Nl, locals, &idx);CHKERRQ(ierr); 8153be36e83SMatthew G. Knepley if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);} 8163be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 8173be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 8183be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 8193be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8203be36e83SMatthew G. Knepley } 8213be36e83SMatthew G. Knepley 8223be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) 8233be36e83SMatthew G. Knepley { 8243be36e83SMatthew G. Knepley const PetscInt *cone; 8253be36e83SMatthew G. Knepley PetscInt coneSize, c; 8263be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 8273be36e83SMatthew G. Knepley PetscErrorCode ierr; 8283be36e83SMatthew G. Knepley 8293be36e83SMatthew G. Knepley PetscFunctionBegin; 8303be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8313be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8323be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8333be36e83SMatthew G. Knepley PetscBool pointShared; 8343be36e83SMatthew G. Knepley 8353be36e83SMatthew G. Knepley ierr = DMPlexPointIsShared(dm, cone[c], &pointShared);CHKERRQ(ierr); 8363be36e83SMatthew G. Knepley cShared = (PetscBool) (cShared && pointShared); 8373be36e83SMatthew G. Knepley } 8383be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 8393be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8403be36e83SMatthew G. Knepley } 8413be36e83SMatthew G. Knepley 8423be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) 8433be36e83SMatthew G. Knepley { 8443be36e83SMatthew G. Knepley const PetscInt *cone; 8453be36e83SMatthew G. Knepley PetscInt coneSize, c; 8463be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 8473be36e83SMatthew G. Knepley PetscErrorCode ierr; 8483be36e83SMatthew G. Knepley 8493be36e83SMatthew G. Knepley PetscFunctionBegin; 8503be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8513be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8523be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8533be36e83SMatthew G. Knepley PetscSFNode rcp; 8543be36e83SMatthew G. Knepley 8553be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cone[c], &rcp); 8563be36e83SMatthew G. Knepley if (ierr) { 8573be36e83SMatthew G. Knepley cmin = missing; 8583be36e83SMatthew G. Knepley } else { 8593be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 8603be36e83SMatthew G. Knepley } 8613be36e83SMatthew G. Knepley } 8623be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 8633be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8643be36e83SMatthew G. Knepley } 8653be36e83SMatthew G. Knepley 8663be36e83SMatthew G. Knepley /* 8673be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 8683be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 8693be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 8703be36e83SMatthew G. Knepley */ 8713be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) 8723be36e83SMatthew G. Knepley { 8733be36e83SMatthew G. Knepley MPI_Comm comm; 8743be36e83SMatthew G. Knepley const PetscInt *support; 875cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height; 8763be36e83SMatthew G. Knepley PetscMPIInt rank; 8773be36e83SMatthew G. Knepley PetscErrorCode ierr; 8783be36e83SMatthew G. Knepley 8793be36e83SMatthew G. Knepley PetscFunctionBegin; 8803be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 881ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 882cf4dc471SVaclav Hapla ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 883cf4dc471SVaclav Hapla ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 884cf4dc471SVaclav Hapla ierr = DMPlexGetPointHeight(dm, p, &height);CHKERRQ(ierr); 885cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight+1) { 886cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */ 887cf4dc471SVaclav 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);} 888cf4dc471SVaclav Hapla PetscFunctionReturn(0); 889cf4dc471SVaclav Hapla } 8903be36e83SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8913be36e83SMatthew G. Knepley ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8923be36e83SMatthew G. Knepley if (candidates) {ierr = PetscSectionGetOffset(candidateSection, p, &off);CHKERRQ(ierr);} 8933be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8943be36e83SMatthew G. Knepley const PetscInt face = support[s]; 8953be36e83SMatthew G. Knepley const PetscInt *cone; 8963be36e83SMatthew G. Knepley PetscSFNode cpmin={-1,-1}, rp={-1,-1}; 8973be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 8983be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 8993be36e83SMatthew G. Knepley PetscHashIJKey key; 9003be36e83SMatthew G. Knepley 9013be36e83SMatthew G. Knepley /* Only add point once */ 9023be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Support face %D\n", rank, face);CHKERRQ(ierr);} 9033be36e83SMatthew G. Knepley key.i = p; 9043be36e83SMatthew G. Knepley key.j = face; 9053be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(faceHash, key, &f);CHKERRQ(ierr); 9063be36e83SMatthew G. Knepley if (f >= 0) continue; 9073be36e83SMatthew G. Knepley ierr = DMPlexConeIsShared(dm, face, &isShared);CHKERRQ(ierr); 9083be36e83SMatthew G. Knepley ierr = DMPlexGetConeMinimum(dm, face, &cpmin);CHKERRQ(ierr); 9093be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, p, &rp);CHKERRQ(ierr); 9103be36e83SMatthew G. Knepley if (debug) { 9113be36e83SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] Face point %D is shared: %d\n", rank, face, (int) isShared);CHKERRQ(ierr); 9123be36e83SMatthew 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); 9133be36e83SMatthew G. Knepley } 9143be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 9153be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 9163be36e83SMatthew G. Knepley if (candidates) { 9173be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Adding shared face %D at idx %D\n[%d] ", rank, face, idx, rank);CHKERRQ(ierr);} 9183be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 9193be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 9203be36e83SMatthew G. Knepley candidates[off+idx].rank = -1; 9213be36e83SMatthew G. Knepley candidates[off+idx++].index = coneSize-1; 9223be36e83SMatthew G. Knepley candidates[off+idx].rank = rank; 9233be36e83SMatthew G. Knepley candidates[off+idx++].index = face; 9243be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9253be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 9263be36e83SMatthew G. Knepley 9273be36e83SMatthew G. Knepley if (cp == p) continue; 9283be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx]);CHKERRQ(ierr); 9293be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index);CHKERRQ(ierr);} 9303be36e83SMatthew G. Knepley ++idx; 9313be36e83SMatthew G. Knepley } 9323be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "\n");CHKERRQ(ierr);} 9333be36e83SMatthew G. Knepley } else { 9343be36e83SMatthew G. Knepley /* Add cone size to section */ 9353be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %D\n", rank, face);CHKERRQ(ierr);} 9363be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 9373be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 9383be36e83SMatthew G. Knepley ierr = PetscSectionAddDof(candidateSection, p, coneSize+1);CHKERRQ(ierr); 9393be36e83SMatthew G. Knepley } 9403be36e83SMatthew G. Knepley } 9413be36e83SMatthew G. Knepley } 9423be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9433be36e83SMatthew G. Knepley } 9443be36e83SMatthew G. Knepley 9452e72742cSMatthew G. Knepley /*@ 9462e72742cSMatthew G. Knepley DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation 9472e72742cSMatthew G. Knepley 948d083f849SBarry Smith Collective on dm 9492e72742cSMatthew G. Knepley 9502e72742cSMatthew G. Knepley Input Parameters: 9512e72742cSMatthew G. Knepley + dm - The interpolated DM 9522e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points 9532e72742cSMatthew G. Knepley 9542e72742cSMatthew G. Knepley Output Parameter: 9552e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points 9562e72742cSMatthew G. Knepley 957f0cfc026SVaclav Hapla Level: developer 9582e72742cSMatthew G. Knepley 9592e72742cSMatthew 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 9602e72742cSMatthew G. Knepley 9612e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate() 9622e72742cSMatthew G. Knepley @*/ 963e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 9642e72742cSMatthew G. Knepley { 9653be36e83SMatthew G. Knepley MPI_Comm comm; 9663be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 9673be36e83SMatthew G. Knepley PetscHMapI claimshash; 9683be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 9693be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 9702e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 9712e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 9723be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 9733be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 9743be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 975f0cfc026SVaclav Hapla PetscMPIInt rank; 9762e72742cSMatthew G. Knepley PetscErrorCode ierr; 9772e72742cSMatthew G. Knepley 9782e72742cSMatthew G. Knepley PetscFunctionBegin; 979f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 980064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 981f0cfc026SVaclav Hapla ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr); 982f0cfc026SVaclav Hapla if (!flg) PetscFunctionReturn(0); 9833be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 9843be36e83SMatthew G. Knepley ierr = DMSetPointSF(dm, pointSF);CHKERRQ(ierr); 9853be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 986ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 9873be36e83SMatthew G. Knepley ierr = DMPlexGetOverlap(dm, &ov);CHKERRQ(ierr); 9883be36e83SMatthew G. Knepley if (ov) SETERRQ(comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 9893be36e83SMatthew G. Knepley ierr = PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug);CHKERRQ(ierr); 9902e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view");CHKERRQ(ierr); 9912e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view");CHKERRQ(ierr); 99225afeb17SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 9933be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 9943be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints);CHKERRQ(ierr); 9953be36e83SMatthew G. Knepley if (Nr < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 9963be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&remoteHash);CHKERRQ(ierr); 9973be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 9983be36e83SMatthew G. Knepley PetscHashIJKey key; 9992e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 10002e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 10013be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(remoteHash, key, l);CHKERRQ(ierr); 10027bffde78SMichael Lange } 100366aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 10042e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 10052e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 10063be36e83SMatthew G. Knepley ierr = IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree);CHKERRQ(ierr); 10073be36e83SMatthew G. Knepley /* 10083be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 10093be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 10103be36e83SMatthew G. Knepley \begin{itemize} 10113be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 10123be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 10133be36e83SMatthew G. Knepley \end{itemize} 10143be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 10153be36e83SMatthew 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 10163be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 10173be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 10183be36e83SMatthew G. Knepley */ 10193be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 10203be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 10213be36e83SMatthew G. Knepley The array holds candidate shared faces, each face is refered to by the leaf point */ 10223be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateSection);CHKERRQ(ierr); 10233be36e83SMatthew G. Knepley ierr = PetscSectionSetChart(candidateSection, 0, Nr);CHKERRQ(ierr); 10247bffde78SMichael Lange { 10253be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 10262e72742cSMatthew G. Knepley 10273be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&faceHash);CHKERRQ(ierr); 10283be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 10293be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 10302e72742cSMatthew G. Knepley 10313be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 10323be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug);CHKERRQ(ierr); 10332e72742cSMatthew G. Knepley } 10343be36e83SMatthew G. Knepley ierr = PetscHMapIJClear(faceHash);CHKERRQ(ierr); 10357bffde78SMichael Lange ierr = PetscSectionSetUp(candidateSection);CHKERRQ(ierr); 10367bffde78SMichael Lange ierr = PetscSectionGetStorageSize(candidateSection, &candidatesSize);CHKERRQ(ierr); 10377bffde78SMichael Lange ierr = PetscMalloc1(candidatesSize, &candidates);CHKERRQ(ierr); 10383be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 10393be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 10402e72742cSMatthew G. Knepley 10413be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 10423be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug);CHKERRQ(ierr); 10432e72742cSMatthew G. Knepley } 10443be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&faceHash);CHKERRQ(ierr); 10453be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 10467bffde78SMichael Lange } 10473be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateSection, "Candidate Section");CHKERRQ(ierr); 10482e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view");CHKERRQ(ierr); 10493be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates);CHKERRQ(ierr); 10503be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 10512e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 10527bffde78SMichael Lange { 10537bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 10547bffde78SMichael Lange PetscInt *remoteOffsets; 10552e72742cSMatthew G. Knepley 10567bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 10577bffde78SMichael Lange ierr = PetscSFCreateInverseSF(sfMulti, &sfInverse);CHKERRQ(ierr); 10583be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateRemoteSection);CHKERRQ(ierr); 10593be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection);CHKERRQ(ierr); 10603be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates);CHKERRQ(ierr); 10613be36e83SMatthew G. Knepley ierr = PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize);CHKERRQ(ierr); 10627bffde78SMichael Lange ierr = PetscMalloc1(candidatesRemoteSize, &candidatesRemote);CHKERRQ(ierr); 1063ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE);CHKERRQ(ierr); 1064ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE);CHKERRQ(ierr); 10657bffde78SMichael Lange ierr = PetscSFDestroy(&sfInverse);CHKERRQ(ierr); 10667bffde78SMichael Lange ierr = PetscSFDestroy(&sfCandidates);CHKERRQ(ierr); 10677bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 10682e72742cSMatthew G. Knepley 10693be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section");CHKERRQ(ierr); 10703be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view");CHKERRQ(ierr); 10713be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote);CHKERRQ(ierr); 10727bffde78SMichael Lange } 10733be36e83SMatthew 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 */ 10747bffde78SMichael Lange { 10753be36e83SMatthew G. Knepley PetscHashIJKLRemote faceTable; 10763be36e83SMatthew G. Knepley PetscInt idx, idx2; 10773be36e83SMatthew G. Knepley 10783be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteCreate(&faceTable);CHKERRQ(ierr); 10792e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 10803be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 10812e72742cSMatthew G. Knepley PetscInt deg; 10823be36e83SMatthew G. Knepley 10832e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 10842e72742cSMatthew G. Knepley PetscInt offset, dof, d; 10852e72742cSMatthew G. Knepley 10863be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx, &dof);CHKERRQ(ierr); 10873be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx, &offset);CHKERRQ(ierr); 10883be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 10892e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10903be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 10913be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 10923be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx+1]; 10933be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 10943be36e83SMatthew G. Knepley PetscSFNode fcp0; 10953be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 10962e72742cSMatthew G. Knepley const PetscInt *join = NULL; 10973be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 10983be36e83SMatthew G. Knepley PetscHashIter iter; 10993be36e83SMatthew G. Knepley PetscBool missing; 11002e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 11012e72742cSMatthew G. Knepley 110266e92ce5SVaclav 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);} 110366e92ce5SVaclav 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); 11043be36e83SMatthew G. Knepley fcp0.rank = rank; 11053be36e83SMatthew G. Knepley fcp0.index = r; 11063be36e83SMatthew G. Knepley d += Np; 11073be36e83SMatthew G. Knepley /* Put remote face in hash table */ 11083be36e83SMatthew G. Knepley key.i = fcp0; 11093be36e83SMatthew G. Knepley key.j = fcone[0]; 11103be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 11113be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 11123be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 11133be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 11143be36e83SMatthew G. Knepley if (missing) { 11153be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Setting remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 11163be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 11173be36e83SMatthew G. Knepley } else { 11183be36e83SMatthew G. Knepley PetscSFNode oface; 11193be36e83SMatthew G. Knepley 11203be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 11213be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 11223be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 11233be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 11243be36e83SMatthew G. Knepley } 11253be36e83SMatthew G. Knepley } 11263be36e83SMatthew G. Knepley /* Check for local face */ 11272e72742cSMatthew G. Knepley points[0] = r; 11283be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 11293be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p]); 11303be36e83SMatthew G. Knepley if (ierr) break; /* We got a point not in our overlap */ 11313be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking local candidate %D\n", rank, points[p]);CHKERRQ(ierr);} 11327bffde78SMichael Lange } 11332e72742cSMatthew G. Knepley if (ierr) continue; 11343be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 11357bffde78SMichael Lange if (joinSize == 1) { 11363be36e83SMatthew G. Knepley PetscSFNode lface; 11373be36e83SMatthew G. Knepley PetscSFNode oface; 11383be36e83SMatthew G. Knepley 11393be36e83SMatthew G. Knepley /* Always replace with local face */ 11403be36e83SMatthew G. Knepley lface.rank = rank; 11413be36e83SMatthew G. Knepley lface.index = join[0]; 11423be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 11433be36e83SMatthew 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);} 11443be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, lface);CHKERRQ(ierr); 11457bffde78SMichael Lange } 11463be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 11473be36e83SMatthew G. Knepley } 11483be36e83SMatthew G. Knepley } 11493be36e83SMatthew G. Knepley /* Put back faces for this root */ 11503be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 11513be36e83SMatthew G. Knepley PetscInt offset, dof, d; 11523be36e83SMatthew G. Knepley 11533be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx2, &dof);CHKERRQ(ierr); 11543be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx2, &offset);CHKERRQ(ierr); 11553be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 11563be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 11573be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 11583be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 11593be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 11603be36e83SMatthew G. Knepley PetscSFNode fcp0; 11613be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 11623be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 11633be36e83SMatthew G. Knepley PetscHashIter iter; 11643be36e83SMatthew G. Knepley PetscBool missing; 11653be36e83SMatthew G. Knepley 11663be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Entering face at (%D, %D)\n", rank, r, idx);CHKERRQ(ierr);} 11673be36e83SMatthew G. Knepley if (Np > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np); 11683be36e83SMatthew G. Knepley fcp0.rank = rank; 11693be36e83SMatthew G. Knepley fcp0.index = r; 11703be36e83SMatthew G. Knepley d += Np; 11713be36e83SMatthew G. Knepley /* Find remote face in hash table */ 11723be36e83SMatthew G. Knepley key.i = fcp0; 11733be36e83SMatthew G. Knepley key.j = fcone[0]; 11743be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 11753be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 11763be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 11773be36e83SMatthew 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);} 11783be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 11792479783cSJose E. Roman if (missing) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an associated face", r, idx2); 11803be36e83SMatthew G. Knepley else {ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]);CHKERRQ(ierr);} 11817bffde78SMichael Lange } 11827bffde78SMichael Lange } 11837bffde78SMichael Lange } 11842e72742cSMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL);CHKERRQ(ierr);} 11853be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteDestroy(&faceTable);CHKERRQ(ierr); 11867bffde78SMichael Lange } 11873be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 11887bffde78SMichael Lange { 11897bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 11907bffde78SMichael Lange PetscSFNode *remotePointsNew; 11912e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 11923be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 11932e72742cSMatthew G. Knepley 11943be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 11957bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 11963be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &claimSection);CHKERRQ(ierr); 11973be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection);CHKERRQ(ierr); 11983be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims);CHKERRQ(ierr); 11992e72742cSMatthew G. Knepley ierr = PetscSectionGetStorageSize(claimSection, &claimsSize);CHKERRQ(ierr); 12002e72742cSMatthew G. Knepley ierr = PetscMalloc1(claimsSize, &claims);CHKERRQ(ierr); 12013be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 1202ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE);CHKERRQ(ierr); 1203ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE);CHKERRQ(ierr); 12047bffde78SMichael Lange ierr = PetscSFDestroy(&sfClaims);CHKERRQ(ierr); 12057bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 12063be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) claimSection, "Claim Section");CHKERRQ(ierr); 12072e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view");CHKERRQ(ierr); 12083be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims);CHKERRQ(ierr); 12093be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 12103be36e83SMatthew 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 */ 1211e8f14785SLisandro Dalcin ierr = PetscHMapICreate(&claimshash);CHKERRQ(ierr); 12123be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 12133be36e83SMatthew G. Knepley PetscInt dof, off, d; 12142e72742cSMatthew G. Knepley 12153be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %D\n", rank, r);CHKERRQ(ierr);} 12163be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateSection, r, &dof);CHKERRQ(ierr); 12173be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateSection, r, &off);CHKERRQ(ierr); 12182e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 12193be36e83SMatthew G. Knepley if (claims[off+d].rank >= 0) { 12203be36e83SMatthew G. Knepley const PetscInt faceInd = off+d; 12213be36e83SMatthew G. Knepley const PetscInt Np = candidates[off+d].index; 12222e72742cSMatthew G. Knepley const PetscInt *join = NULL; 12232e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 12242e72742cSMatthew G. Knepley 12253be36e83SMatthew 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);} 12263be36e83SMatthew G. Knepley points[0] = r; 12273be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[0]);CHKERRQ(ierr);} 12283be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 12293be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1]);CHKERRQ(ierr); 12303be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[c+1]);CHKERRQ(ierr);} 12312e72742cSMatthew G. Knepley } 12323be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 12332e72742cSMatthew G. Knepley if (joinSize == 1) { 12343be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 12353be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %D for non-remote partner\n", rank, join[0]);CHKERRQ(ierr);} 12363be36e83SMatthew G. Knepley } else { 12373be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Found local face %D\n", rank, join[0]);CHKERRQ(ierr);} 12382e72742cSMatthew G. Knepley ierr = PetscHMapISet(claimshash, join[0], faceInd);CHKERRQ(ierr); 12392e72742cSMatthew G. Knepley } 12403be36e83SMatthew G. Knepley } else { 12413be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank);CHKERRQ(ierr);} 12423be36e83SMatthew G. Knepley } 12433be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 12443be36e83SMatthew G. Knepley } else { 12453be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] No claim for point %D\n", rank, r);CHKERRQ(ierr);} 12463be36e83SMatthew G. Knepley d += claims[off+d].index+1; 12477bffde78SMichael Lange } 12487bffde78SMichael Lange } 12493be36e83SMatthew G. Knepley } 12503be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 12513be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 12523be36e83SMatthew G. Knepley ierr = PetscHMapIGetSize(claimshash, &NlNew);CHKERRQ(ierr); 12537bffde78SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 12543be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &localPointsNew);CHKERRQ(ierr); 12553be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &remotePointsNew);CHKERRQ(ierr); 12563be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 12573be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 12583be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 12593be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 12607bffde78SMichael Lange } 12613be36e83SMatthew G. Knepley p = Nl; 1262e8f14785SLisandro Dalcin ierr = PetscHMapIGetKeys(claimshash, &p, localPointsNew);CHKERRQ(ierr); 12633be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 12643be36e83SMatthew G. Knepley ierr = PetscSortInt(NlNew, &localPointsNew[Nl]);CHKERRQ(ierr); 12653be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 12663be36e83SMatthew G. Knepley PetscInt off; 12673be36e83SMatthew G. Knepley ierr = PetscHMapIGet(claimshash, localPointsNew[p], &off);CHKERRQ(ierr); 12683be36e83SMatthew 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); 12693be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 12707bffde78SMichael Lange } 12713be36e83SMatthew G. Knepley ierr = PetscSFCreate(comm, &sfPointNew);CHKERRQ(ierr); 12723be36e83SMatthew G. Knepley ierr = PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 12733be36e83SMatthew G. Knepley ierr = PetscSFSetUp(sfPointNew);CHKERRQ(ierr); 12747bffde78SMichael Lange ierr = DMSetPointSF(dm, sfPointNew);CHKERRQ(ierr); 12753be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view");CHKERRQ(ierr); 12767bffde78SMichael Lange ierr = PetscSFDestroy(&sfPointNew);CHKERRQ(ierr); 1277e8f14785SLisandro Dalcin ierr = PetscHMapIDestroy(&claimshash);CHKERRQ(ierr); 12787bffde78SMichael Lange } 12793be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&remoteHash);CHKERRQ(ierr); 12807bffde78SMichael Lange ierr = PetscSectionDestroy(&candidateSection);CHKERRQ(ierr); 12813be36e83SMatthew G. Knepley ierr = PetscSectionDestroy(&candidateRemoteSection);CHKERRQ(ierr); 12827bffde78SMichael Lange ierr = PetscSectionDestroy(&claimSection);CHKERRQ(ierr); 12837bffde78SMichael Lange ierr = PetscFree(candidates);CHKERRQ(ierr); 12847bffde78SMichael Lange ierr = PetscFree(candidatesRemote);CHKERRQ(ierr); 12857bffde78SMichael Lange ierr = PetscFree(claims);CHKERRQ(ierr); 128625afeb17SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 12877bffde78SMichael Lange PetscFunctionReturn(0); 12887bffde78SMichael Lange } 12897bffde78SMichael Lange 1290248eb259SVaclav Hapla /*@ 129180330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 129280330477SMatthew G. Knepley 1293d083f849SBarry Smith Collective on dm 129480330477SMatthew G. Knepley 1295e56d480eSMatthew G. Knepley Input Parameters: 1296e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices 129710a67516SMatthew G. Knepley - dmInt - The interpolated DM 129880330477SMatthew G. Knepley 129980330477SMatthew G. Knepley Output Parameter: 13004e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object 130180330477SMatthew G. Knepley 130280330477SMatthew G. Knepley Level: intermediate 130380330477SMatthew G. Knepley 130495452b02SPatrick Sanan Notes: 130595452b02SPatrick Sanan It does not copy over the coordinates. 130643eeeb2dSStefano Zampini 13079ade3219SVaclav Hapla Developer Notes: 13089ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL. 13099ade3219SVaclav Hapla 1310a4a685f2SJacob Faibussowitsch .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates() 131180330477SMatthew G. Knepley @*/ 13129f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 13139f074e33SMatthew G Knepley { 1314a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 13159a5b13a2SMatthew G Knepley DM idm, odm = dm; 13167bffde78SMichael Lange PetscSF sfPoint; 13172e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 131810a67516SMatthew G. Knepley const char *name; 1319b325530aSVaclav Hapla PetscBool flg=PETSC_TRUE; 13209f074e33SMatthew G Knepley PetscErrorCode ierr; 13219f074e33SMatthew G Knepley 13229f074e33SMatthew G Knepley PetscFunctionBegin; 132310a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 132410a67516SMatthew G. Knepley PetscValidPointer(dmInt, 2); 1325a72f3261SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 13262e1b13c2SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1327c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1328827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1329827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1330827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 133176b791aaSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 133276b791aaSMatthew G. Knepley idm = dm; 1333b21b8912SMatthew G. Knepley } else { 13349a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 13359a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 133610a67516SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 13379a5b13a2SMatthew G Knepley ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 1338c73cfb54SMatthew G. Knepley ierr = DMSetDimension(idm, dim);CHKERRQ(ierr); 13397bffde78SMichael Lange if (depth > 0) { 13407bffde78SMichael Lange ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr); 13417bffde78SMichael Lange ierr = DMGetPointSF(odm, &sfPoint);CHKERRQ(ierr); 134294488200SVaclav Hapla { 13433be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 134494488200SVaclav Hapla PetscInt nroots; 134594488200SVaclav Hapla ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 134694488200SVaclav Hapla if (nroots >= 0) {ierr = DMPlexInterpolatePointSF(idm, sfPoint);CHKERRQ(ierr);} 134794488200SVaclav Hapla } 13487bffde78SMichael Lange } 13499a5b13a2SMatthew G Knepley if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);} 13509a5b13a2SMatthew G Knepley odm = idm; 13519f074e33SMatthew G Knepley } 135210a67516SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135310a67516SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) idm, name);CHKERRQ(ierr); 135410a67516SMatthew G. Knepley ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr); 13555d80c0bfSVaclav Hapla ierr = DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE);CHKERRQ(ierr); 1356b325530aSVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL);CHKERRQ(ierr); 135727d0e99aSVaclav Hapla if (flg) {ierr = DMPlexOrientInterface_Internal(idm);CHKERRQ(ierr);} 135884699f70SSatish Balay } 135943eeeb2dSStefano Zampini { 136043eeeb2dSStefano Zampini PetscBool isper; 136143eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 136243eeeb2dSStefano Zampini const DMBoundaryType *bd; 136343eeeb2dSStefano Zampini 136443eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 136543eeeb2dSStefano Zampini ierr = DMSetPeriodicity(idm,isper,maxCell,L,bd);CHKERRQ(ierr); 136643eeeb2dSStefano Zampini } 1367827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1368827c4036SVaclav Hapla { 1369d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) idm->data; 1370827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1371827c4036SVaclav Hapla } 13729a5b13a2SMatthew G Knepley *dmInt = idm; 1373a72f3261SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 13749f074e33SMatthew G Knepley PetscFunctionReturn(0); 13759f074e33SMatthew G Knepley } 137607b0a1fcSMatthew G Knepley 137780330477SMatthew G. Knepley /*@ 137880330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 137980330477SMatthew G. Knepley 1380d083f849SBarry Smith Collective on dmA 138180330477SMatthew G. Knepley 138280330477SMatthew G. Knepley Input Parameter: 138380330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates 138480330477SMatthew G. Knepley 138580330477SMatthew G. Knepley Output Parameter: 138680330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates 138780330477SMatthew G. Knepley 138880330477SMatthew G. Knepley Level: intermediate 138980330477SMatthew G. Knepley 139080330477SMatthew G. Knepley Note: This is typically used when adding pieces other than vertices to a mesh 139180330477SMatthew G. Knepley 139265f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 139380330477SMatthew G. Knepley @*/ 139407b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 139507b0a1fcSMatthew G Knepley { 139607b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 139743eeeb2dSStefano Zampini VecType vtype; 139807b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 139907b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 14000bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 140190a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 140243eeeb2dSStefano Zampini PetscBool lc = PETSC_FALSE; 140307b0a1fcSMatthew G Knepley PetscErrorCode ierr; 140407b0a1fcSMatthew G Knepley 140507b0a1fcSMatthew G Knepley PetscFunctionBegin; 140643eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 140743eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 140876b791aaSMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 140990a8aa44SJed Brown ierr = DMGetCoordinateDim(dmA, &cdim);CHKERRQ(ierr); 141090a8aa44SJed Brown ierr = DMSetCoordinateDim(dmB, cdim);CHKERRQ(ierr); 141107b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr); 141207b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr); 141307b0a1fcSMatthew 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); 141461a622f3SMatthew G. Knepley /* Copy over discretization if it exists */ 141561a622f3SMatthew G. Knepley { 141661a622f3SMatthew G. Knepley DM cdmA, cdmB; 141761a622f3SMatthew G. Knepley PetscDS dsA, dsB; 141861a622f3SMatthew G. Knepley PetscObject objA, objB; 141961a622f3SMatthew G. Knepley PetscClassId idA, idB; 142061a622f3SMatthew G. Knepley const PetscScalar *constants; 142161a622f3SMatthew G. Knepley PetscInt cdim, Nc; 142261a622f3SMatthew G. Knepley 142361a622f3SMatthew G. Knepley ierr = DMGetCoordinateDM(dmA, &cdmA);CHKERRQ(ierr); 142461a622f3SMatthew G. Knepley ierr = DMGetCoordinateDM(dmB, &cdmB);CHKERRQ(ierr); 142561a622f3SMatthew G. Knepley ierr = DMGetField(cdmA, 0, NULL, &objA);CHKERRQ(ierr); 142661a622f3SMatthew G. Knepley ierr = DMGetField(cdmB, 0, NULL, &objB);CHKERRQ(ierr); 142761a622f3SMatthew G. Knepley ierr = PetscObjectGetClassId(objA, &idA);CHKERRQ(ierr); 142861a622f3SMatthew G. Knepley ierr = PetscObjectGetClassId(objB, &idB);CHKERRQ(ierr); 142961a622f3SMatthew G. Knepley if ((idA == PETSCFE_CLASSID) && (idA != idB)) { 143061a622f3SMatthew G. Knepley ierr = DMSetField(cdmB, 0, NULL, objA);CHKERRQ(ierr); 143161a622f3SMatthew G. Knepley ierr = DMCreateDS(cdmB);CHKERRQ(ierr); 143261a622f3SMatthew G. Knepley ierr = DMGetDS(cdmA, &dsA);CHKERRQ(ierr); 143361a622f3SMatthew G. Knepley ierr = DMGetDS(cdmB, &dsB);CHKERRQ(ierr); 143461a622f3SMatthew G. Knepley ierr = PetscDSGetCoordinateDimension(dsA, &cdim);CHKERRQ(ierr); 143561a622f3SMatthew G. Knepley ierr = PetscDSSetCoordinateDimension(dsB, cdim);CHKERRQ(ierr); 143661a622f3SMatthew G. Knepley ierr = PetscDSGetConstants(dsA, &Nc, &constants);CHKERRQ(ierr); 143761a622f3SMatthew G. Knepley ierr = PetscDSSetConstants(dsB, Nc, (PetscScalar *) constants);CHKERRQ(ierr); 143861a622f3SMatthew G. Knepley } 143961a622f3SMatthew G. Knepley } 144043eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr); 144143eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr); 144269d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr); 144369d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr); 1444972bc18aSToby Isaac if (coordSectionA == coordSectionB) PetscFunctionReturn(0); 14450bedd6beSMatthew G. Knepley ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr); 14460bedd6beSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 14470bedd6beSMatthew G. Knepley if (Nf > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf); 1448df26b574SMatthew G. Knepley if (!coordSectionB) { 1449df26b574SMatthew G. Knepley PetscInt dim; 1450df26b574SMatthew G. Knepley 1451df26b574SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr); 1452df26b574SMatthew G. Knepley ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr); 1453df26b574SMatthew G. Knepley ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr); 1454df26b574SMatthew G. Knepley ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr); 1455df26b574SMatthew G. Knepley } 145607b0a1fcSMatthew G Knepley ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); 145707b0a1fcSMatthew G Knepley ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr); 145807b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr); 145943eeeb2dSStefano Zampini ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr); 146043eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 1461367003a6SStefano 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); 146243eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 146343eeeb2dSStefano Zampini cE = vEndB; 146443eeeb2dSStefano Zampini lc = PETSC_TRUE; 146543eeeb2dSStefano Zampini } else { 146643eeeb2dSStefano Zampini cS = vStartB; 146743eeeb2dSStefano Zampini cE = vEndB; 146843eeeb2dSStefano Zampini } 146943eeeb2dSStefano Zampini ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr); 147007b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 147107b0a1fcSMatthew G Knepley ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr); 147207b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr); 147307b0a1fcSMatthew G Knepley } 147443eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 147543eeeb2dSStefano Zampini PetscInt c; 147643eeeb2dSStefano Zampini 147743eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 147843eeeb2dSStefano Zampini PetscInt dof; 147943eeeb2dSStefano Zampini 148043eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 148143eeeb2dSStefano Zampini ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr); 148243eeeb2dSStefano Zampini ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr); 148343eeeb2dSStefano Zampini } 148443eeeb2dSStefano Zampini } 148507b0a1fcSMatthew G Knepley ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); 148607b0a1fcSMatthew G Knepley ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr); 148707b0a1fcSMatthew G Knepley ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr); 14888b9ced59SLisandro Dalcin ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr); 148907b0a1fcSMatthew G Knepley ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); 149007b0a1fcSMatthew G Knepley ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr); 149143eeeb2dSStefano Zampini ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr); 149243eeeb2dSStefano Zampini ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr); 149343eeeb2dSStefano Zampini ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr); 149443eeeb2dSStefano Zampini ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr); 149507b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr); 149607b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); 149707b0a1fcSMatthew G Knepley for (v = 0; v < vEndB-vStartB; ++v) { 149843eeeb2dSStefano Zampini PetscInt offA, offB; 149943eeeb2dSStefano Zampini 150043eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr); 150143eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr); 150207b0a1fcSMatthew G Knepley for (d = 0; d < spaceDim; ++d) { 150343eeeb2dSStefano Zampini coordsB[offB+d] = coordsA[offA+d]; 150443eeeb2dSStefano Zampini } 150543eeeb2dSStefano Zampini } 150643eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 150743eeeb2dSStefano Zampini PetscInt c; 150843eeeb2dSStefano Zampini 150943eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 151043eeeb2dSStefano Zampini PetscInt dof, offA, offB; 151143eeeb2dSStefano Zampini 151243eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr); 151343eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr); 151443eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 1515580bdb30SBarry Smith ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr); 151607b0a1fcSMatthew G Knepley } 151707b0a1fcSMatthew G Knepley } 151807b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr); 151907b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); 152007b0a1fcSMatthew G Knepley ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr); 152107b0a1fcSMatthew G Knepley ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); 152207b0a1fcSMatthew G Knepley PetscFunctionReturn(0); 152307b0a1fcSMatthew G Knepley } 15245c386225SMatthew G. Knepley 15254e3744c5SMatthew G. Knepley /*@ 15264e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 15274e3744c5SMatthew G. Knepley 1528d083f849SBarry Smith Collective on dm 15294e3744c5SMatthew G. Knepley 15304e3744c5SMatthew G. Knepley Input Parameter: 15314e3744c5SMatthew G. Knepley . dm - The complete DMPlex object 15324e3744c5SMatthew G. Knepley 15334e3744c5SMatthew G. Knepley Output Parameter: 15344e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices 15354e3744c5SMatthew G. Knepley 15364e3744c5SMatthew G. Knepley Level: intermediate 15374e3744c5SMatthew G. Knepley 153895452b02SPatrick Sanan Notes: 153995452b02SPatrick Sanan It does not copy over the coordinates. 154043eeeb2dSStefano Zampini 15419ade3219SVaclav Hapla Developer Notes: 15429ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 15439ade3219SVaclav Hapla 1544a4a685f2SJacob Faibussowitsch .seealso: DMPlexInterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates() 15454e3744c5SMatthew G. Knepley @*/ 15464e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 15474e3744c5SMatthew G. Knepley { 1548827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 15494e3744c5SMatthew G. Knepley DM udm; 1550412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; 15514e3744c5SMatthew G. Knepley PetscErrorCode ierr; 15524e3744c5SMatthew G. Knepley 15534e3744c5SMatthew G. Knepley PetscFunctionBegin; 155443eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 155543eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 1556c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1557827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1558827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1559827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1560827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 15614e3744c5SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 1562595d4abbSMatthew G. Knepley *dmUnint = dm; 1563595d4abbSMatthew G. Knepley PetscFunctionReturn(0); 15644e3744c5SMatthew G. Knepley } 1565595d4abbSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1566595d4abbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 15674e3744c5SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr); 15684e3744c5SMatthew G. Knepley ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr); 1569c73cfb54SMatthew G. Knepley ierr = DMSetDimension(udm, dim);CHKERRQ(ierr); 15704e3744c5SMatthew G. Knepley ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr); 15714e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1572595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 15734e3744c5SMatthew G. Knepley 15744e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15754e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 15764e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 15774e3744c5SMatthew G. Knepley 15784e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 15794e3744c5SMatthew G. Knepley } 15804e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15814e3744c5SMatthew G. Knepley ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr); 1582595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 15834e3744c5SMatthew G. Knepley } 15844e3744c5SMatthew G. Knepley ierr = DMSetUp(udm);CHKERRQ(ierr); 1585785e854fSJed Brown ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr); 15864e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1587595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 15884e3744c5SMatthew G. Knepley 15894e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15904e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 15914e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 15924e3744c5SMatthew G. Knepley 15934e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 15944e3744c5SMatthew G. Knepley } 15954e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 15964e3744c5SMatthew G. Knepley ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr); 15974e3744c5SMatthew G. Knepley } 15984e3744c5SMatthew G. Knepley ierr = PetscFree(cone);CHKERRQ(ierr); 15994e3744c5SMatthew G. Knepley ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr); 16004e3744c5SMatthew G. Knepley ierr = DMPlexStratify(udm);CHKERRQ(ierr); 16015c7de58aSMatthew G. Knepley /* Reduce SF */ 16025c7de58aSMatthew G. Knepley { 16035c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 16045c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 16055c7de58aSMatthew G. Knepley const PetscInt *localPoints; 16065c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 16075c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 16085c7de58aSMatthew G. Knepley PetscInt vEnd, numRoots, numLeaves, l; 16095c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 16105c7de58aSMatthew G. Knepley PetscErrorCode ierr; 16115c7de58aSMatthew G. Knepley 16125c7de58aSMatthew G. Knepley /* Get original SF information */ 16135c7de58aSMatthew G. Knepley ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 16145c7de58aSMatthew G. Knepley ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr); 16155c7de58aSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr); 16165c7de58aSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 16175c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 16185c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++; 16195c7de58aSMatthew G. Knepley /* Fill in leaves */ 16205c7de58aSMatthew G. Knepley if (vEnd >= 0) { 16215c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr); 16225c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr); 16235c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 16245c7de58aSMatthew G. Knepley if (localPoints[l] < vEnd) { 16255c7de58aSMatthew G. Knepley localPointsUn[n] = localPoints[l]; 16265c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 16275c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 16285c7de58aSMatthew G. Knepley ++n; 16295c7de58aSMatthew G. Knepley } 16305c7de58aSMatthew G. Knepley } 16315c7de58aSMatthew G. Knepley if (n != numLeavesUn) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn); 16325c7de58aSMatthew G. Knepley ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr); 16335c7de58aSMatthew G. Knepley } 16345c7de58aSMatthew G. Knepley } 163543eeeb2dSStefano Zampini { 163643eeeb2dSStefano Zampini PetscBool isper; 163743eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 163843eeeb2dSStefano Zampini const DMBoundaryType *bd; 163943eeeb2dSStefano Zampini 164043eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 164143eeeb2dSStefano Zampini ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr); 164243eeeb2dSStefano Zampini } 1643827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1644827c4036SVaclav Hapla { 1645d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) udm->data; 1646827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1647827c4036SVaclav Hapla } 16484e3744c5SMatthew G. Knepley *dmUnint = udm; 16494e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 16504e3744c5SMatthew G. Knepley } 1651a7748839SVaclav Hapla 1652a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1653a7748839SVaclav Hapla { 1654a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1655a7748839SVaclav Hapla MPI_Comm comm; 1656a7748839SVaclav Hapla PetscErrorCode ierr; 1657a7748839SVaclav Hapla 1658a7748839SVaclav Hapla PetscFunctionBegin; 1659a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1660a7748839SVaclav Hapla ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1661a7748839SVaclav Hapla ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1662a7748839SVaclav Hapla 1663a7748839SVaclav Hapla if (depth == dim) { 1664a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1665a7748839SVaclav Hapla if (!dim) goto finish; 1666a7748839SVaclav Hapla 1667a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 1668a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr); 1669a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1670a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1671a7748839SVaclav Hapla if (coneSize) { 1672a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1673a7748839SVaclav Hapla goto finish; 1674a7748839SVaclav Hapla } 1675a7748839SVaclav Hapla } 1676a7748839SVaclav Hapla 1677a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1678a7748839SVaclav Hapla for (h=0; h<dim; h++) { 1679a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 1680a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1681a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1682a7748839SVaclav Hapla if (!coneSize) { 1683a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1684a7748839SVaclav Hapla goto finish; 1685a7748839SVaclav Hapla } 1686a7748839SVaclav Hapla } 1687a7748839SVaclav Hapla } 1688a7748839SVaclav Hapla } else if (depth == 1) { 1689a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1690a7748839SVaclav Hapla } else { 1691a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1692a7748839SVaclav Hapla } 1693a7748839SVaclav Hapla finish: 1694a7748839SVaclav Hapla PetscFunctionReturn(0); 1695a7748839SVaclav Hapla } 1696a7748839SVaclav Hapla 1697a7748839SVaclav Hapla /*@ 16989ade3219SVaclav Hapla DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated. 1699a7748839SVaclav Hapla 1700a7748839SVaclav Hapla Not Collective 1701a7748839SVaclav Hapla 1702a7748839SVaclav Hapla Input Parameter: 1703a7748839SVaclav Hapla . dm - The DM object 1704a7748839SVaclav Hapla 1705a7748839SVaclav Hapla Output Parameter: 1706a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1707a7748839SVaclav Hapla 1708a7748839SVaclav Hapla Level: intermediate 1709a7748839SVaclav Hapla 1710a7748839SVaclav Hapla Notes: 17119ade3219SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this is NOT collective 17129ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1713a7748839SVaclav Hapla However, DMPlexInterpolate() guarantees the result is the same on all. 17149ade3219SVaclav Hapla 1715a7748839SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED. 1716a7748839SVaclav Hapla 17179ade3219SVaclav Hapla Developer Notes: 17189ade3219SVaclav Hapla Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID. 17199ade3219SVaclav Hapla 17209ade3219SVaclav Hapla If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called. 17219ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 17229ade3219SVaclav Hapla DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL. 17239ade3219SVaclav Hapla 17249ade3219SVaclav Hapla If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated. 17259ade3219SVaclav Hapla 17269ade3219SVaclav Hapla DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL, 17279ade3219SVaclav Hapla and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 17289ade3219SVaclav Hapla 1729a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective() 1730a7748839SVaclav Hapla @*/ 1731a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1732a7748839SVaclav Hapla { 1733a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1734a7748839SVaclav Hapla PetscErrorCode ierr; 1735a7748839SVaclav Hapla 1736a7748839SVaclav Hapla PetscFunctionBegin; 1737a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1738a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1739a7748839SVaclav Hapla if (plex->interpolated < 0) { 1740a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr); 174176bd3646SJed Brown } else if (PetscDefined (USE_DEBUG)) { 1742a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1743a7748839SVaclav Hapla 1744a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr); 17457fc06600SVaclav 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]); 1746a7748839SVaclav Hapla } 1747a7748839SVaclav Hapla *interpolated = plex->interpolated; 1748a7748839SVaclav Hapla PetscFunctionReturn(0); 1749a7748839SVaclav Hapla } 1750a7748839SVaclav Hapla 1751a7748839SVaclav Hapla /*@ 17529ade3219SVaclav Hapla DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner). 1753a7748839SVaclav Hapla 17542666ff3cSVaclav Hapla Collective 1755a7748839SVaclav Hapla 1756a7748839SVaclav Hapla Input Parameter: 1757a7748839SVaclav Hapla . dm - The DM object 1758a7748839SVaclav Hapla 1759a7748839SVaclav Hapla Output Parameter: 1760a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1761a7748839SVaclav Hapla 1762a7748839SVaclav Hapla Level: intermediate 1763a7748839SVaclav Hapla 1764a7748839SVaclav Hapla Notes: 17659ade3219SVaclav Hapla Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks. 17669ade3219SVaclav Hapla 17679ade3219SVaclav Hapla This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks. 17689ade3219SVaclav Hapla 17699ade3219SVaclav Hapla Developer Notes: 17709ade3219SVaclav Hapla Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID. 17719ade3219SVaclav Hapla 17729ade3219SVaclav Hapla If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated. 17739ade3219SVaclav Hapla MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 17749ade3219SVaclav Hapla if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED, 17759ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 17769ade3219SVaclav Hapla 17779ade3219SVaclav Hapla If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective. 1778a7748839SVaclav Hapla 1779a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated() 1780a7748839SVaclav Hapla @*/ 1781a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 1782a7748839SVaclav Hapla { 1783a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1784a7748839SVaclav Hapla PetscBool debug=PETSC_FALSE; 1785a7748839SVaclav Hapla PetscErrorCode ierr; 1786a7748839SVaclav Hapla 1787a7748839SVaclav Hapla PetscFunctionBegin; 1788a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1789a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1790a7748839SVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr); 1791a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1792a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1793a7748839SVaclav Hapla MPI_Comm comm; 1794a7748839SVaclav Hapla 1795a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1796a7748839SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr); 1797ffc4695bSBarry Smith ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRMPI(ierr); 1798ffc4695bSBarry Smith ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRMPI(ierr); 1799a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1800a7748839SVaclav Hapla if (debug) { 1801a7748839SVaclav Hapla PetscMPIInt rank; 1802a7748839SVaclav Hapla 1803ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1804a7748839SVaclav Hapla ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr); 1805a7748839SVaclav Hapla ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr); 1806a7748839SVaclav Hapla } 1807a7748839SVaclav Hapla } 1808a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 1809a7748839SVaclav Hapla PetscFunctionReturn(0); 1810a7748839SVaclav Hapla } 1811