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 20999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(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 33999739cfSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(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 62439ece16SMatthew G. Knepley PetscFunctionBegin; 63439ece16SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64ba2698f1SMatthew G. Knepley if (cone) PetscValidIntPointer(cone, 3); 655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 665f80ce2aSJacob Faibussowitsch if (faceTypes) CHKERRQ(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &typesTmp)); 675f80ce2aSJacob Faibussowitsch if (faceSizes) CHKERRQ(DMGetWorkArray(dm, PetscMax(maxConeSize, maxSupportSize), MPIU_INT, &sizesTmp)); 685f80ce2aSJacob Faibussowitsch if (faces) CHKERRQ(DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp)); 69ba2698f1SMatthew G. Knepley switch (ct) { 70ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 71ba2698f1SMatthew G. Knepley if (numFaces) *numFaces = 0; 72ba2698f1SMatthew G. Knepley break; 73ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 74412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 2; 75412e9a14SMatthew G. Knepley if (faceTypes) { 76412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT; 77412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 78412e9a14SMatthew G. Knepley } 79412e9a14SMatthew G. Knepley if (faceSizes) { 80412e9a14SMatthew G. Knepley sizesTmp[0] = 1; sizesTmp[1] = 1; 81412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 82412e9a14SMatthew G. Knepley } 83c49d9212SMatthew G. Knepley if (faces) { 84c49d9212SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 85c49d9212SMatthew G. Knepley *faces = facesTmp; 86c49d9212SMatthew G. Knepley } 87412e9a14SMatthew G. Knepley break; 88412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 89c49d9212SMatthew G. Knepley if (numFaces) *numFaces = 2; 90412e9a14SMatthew G. Knepley if (faceTypes) { 91412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_POINT; typesTmp[1] = DM_POLYTOPE_POINT; 92412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 93412e9a14SMatthew G. Knepley } 94412e9a14SMatthew G. Knepley if (faceSizes) { 95412e9a14SMatthew G. Knepley sizesTmp[0] = 1; sizesTmp[1] = 1; 96412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 97412e9a14SMatthew G. Knepley } 98412e9a14SMatthew G. Knepley if (faces) { 99412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 100412e9a14SMatthew G. Knepley *faces = facesTmp; 101412e9a14SMatthew G. Knepley } 102c49d9212SMatthew G. Knepley break; 103ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 104412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 3; 105412e9a14SMatthew G. Knepley if (faceTypes) { 106412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT; 107412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 108412e9a14SMatthew G. Knepley } 109412e9a14SMatthew G. Knepley if (faceSizes) { 110412e9a14SMatthew G. Knepley sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; 111412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 112412e9a14SMatthew G. Knepley } 1139a5b13a2SMatthew G Knepley if (faces) { 1149a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1159a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1169a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[0]; 1179a5b13a2SMatthew G Knepley *faces = facesTmp; 1189a5b13a2SMatthew G Knepley } 1199f074e33SMatthew G Knepley break; 120ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 1219a5b13a2SMatthew G Knepley /* Vertices follow right hand rule */ 122412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 123412e9a14SMatthew G. Knepley if (faceTypes) { 124412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_SEGMENT; typesTmp[1] = DM_POLYTOPE_SEGMENT; typesTmp[2] = DM_POLYTOPE_SEGMENT; typesTmp[3] = DM_POLYTOPE_SEGMENT; 125412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 126412e9a14SMatthew G. Knepley } 127412e9a14SMatthew G. Knepley if (faceSizes) { 128412e9a14SMatthew G. Knepley sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2; 129412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 130412e9a14SMatthew G. Knepley } 1319a5b13a2SMatthew G Knepley if (faces) { 1329a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1339a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1349a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[3]; 1359a5b13a2SMatthew G Knepley facesTmp[6] = cone[3]; facesTmp[7] = cone[0]; 1369a5b13a2SMatthew G Knepley *faces = facesTmp; 1379a5b13a2SMatthew G Knepley } 138412e9a14SMatthew G. Knepley break; 139412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 1409a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 141412e9a14SMatthew G. Knepley if (faceTypes) { 142412e9a14SMatthew 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; 143412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 144412e9a14SMatthew G. Knepley } 145412e9a14SMatthew G. Knepley if (faceSizes) { 146412e9a14SMatthew G. Knepley sizesTmp[0] = 2; sizesTmp[1] = 2; sizesTmp[2] = 2; sizesTmp[3] = 2; 147412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 148412e9a14SMatthew G. Knepley } 149412e9a14SMatthew G. Knepley if (faces) { 150412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 151412e9a14SMatthew G. Knepley facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; 152412e9a14SMatthew G. Knepley facesTmp[4] = cone[0]; facesTmp[5] = cone[2]; 153412e9a14SMatthew G. Knepley facesTmp[6] = cone[1]; facesTmp[7] = cone[3]; 154412e9a14SMatthew G. Knepley *faces = facesTmp; 155412e9a14SMatthew G. Knepley } 1569f074e33SMatthew G Knepley break; 157ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 1582e1b13c2SMatthew G. Knepley /* Vertices of first face follow right hand rule and normal points away from last vertex */ 159412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 4; 160412e9a14SMatthew G. Knepley if (faceTypes) { 161412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; 162412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 163412e9a14SMatthew G. Knepley } 164412e9a14SMatthew G. Knepley if (faceSizes) { 165412e9a14SMatthew G. Knepley sizesTmp[0] = 3; sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; 166412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 167412e9a14SMatthew G. Knepley } 1689a5b13a2SMatthew G Knepley if (faces) { 1692e1b13c2SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; 1702e1b13c2SMatthew G. Knepley facesTmp[3] = cone[0]; facesTmp[4] = cone[3]; facesTmp[5] = cone[1]; 1712e1b13c2SMatthew G. Knepley facesTmp[6] = cone[0]; facesTmp[7] = cone[2]; facesTmp[8] = cone[3]; 1722e1b13c2SMatthew G. Knepley facesTmp[9] = cone[2]; facesTmp[10] = cone[1]; facesTmp[11] = cone[3]; 1739a5b13a2SMatthew G Knepley *faces = facesTmp; 1749a5b13a2SMatthew G Knepley } 1759a5b13a2SMatthew G Knepley break; 176ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 177e368ef20SMatthew G. Knepley /* 7--------6 178e368ef20SMatthew G. Knepley /| /| 179e368ef20SMatthew G. Knepley / | / | 180e368ef20SMatthew G. Knepley 4--------5 | 181e368ef20SMatthew G. Knepley | | | | 182e368ef20SMatthew G. Knepley | | | | 183e368ef20SMatthew G. Knepley | 1--------2 184e368ef20SMatthew G. Knepley | / | / 185e368ef20SMatthew G. Knepley |/ |/ 186e368ef20SMatthew G. Knepley 0--------3 187e368ef20SMatthew G. Knepley */ 188412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 189412e9a14SMatthew G. Knepley if (faceTypes) { 190412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; 191412e9a14SMatthew G. Knepley typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; typesTmp[5] = DM_POLYTOPE_QUADRILATERAL; 192412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 193412e9a14SMatthew G. Knepley } 194412e9a14SMatthew G. Knepley if (faceSizes) { 195412e9a14SMatthew G. Knepley sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4; 196412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 197412e9a14SMatthew G. Knepley } 1989a5b13a2SMatthew G Knepley if (faces) { 19951cfd6a4SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 20051cfd6a4SMatthew G. Knepley facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; facesTmp[6] = cone[6]; facesTmp[7] = cone[7]; /* Top */ 20151cfd6a4SMatthew G. Knepley facesTmp[8] = cone[0]; facesTmp[9] = cone[3]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; /* Front */ 20251cfd6a4SMatthew G. Knepley facesTmp[12] = cone[2]; facesTmp[13] = cone[1]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; /* Back */ 20351cfd6a4SMatthew G. Knepley facesTmp[16] = cone[3]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; /* Right */ 20451cfd6a4SMatthew G. Knepley facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[1]; /* Left */ 2059a5b13a2SMatthew G Knepley *faces = facesTmp; 2069a5b13a2SMatthew G Knepley } 20799836e0eSStefano Zampini break; 208ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 209412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 210412e9a14SMatthew G. Knepley if (faceTypes) { 211412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; 212412e9a14SMatthew G. Knepley typesTmp[2] = DM_POLYTOPE_QUADRILATERAL; typesTmp[3] = DM_POLYTOPE_QUADRILATERAL; typesTmp[4] = DM_POLYTOPE_QUADRILATERAL; 213412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 214412e9a14SMatthew G. Knepley } 215412e9a14SMatthew G. Knepley if (faceSizes) { 216412e9a14SMatthew G. Knepley sizesTmp[0] = 3; sizesTmp[1] = 3; 217412e9a14SMatthew G. Knepley sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; 218412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 219412e9a14SMatthew G. Knepley } 220ba2698f1SMatthew G. Knepley if (faces) { 221412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; /* Bottom */ 222412e9a14SMatthew G. Knepley facesTmp[3] = cone[3]; facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; /* Top */ 223412e9a14SMatthew G. Knepley facesTmp[6] = cone[0]; facesTmp[7] = cone[2]; facesTmp[8] = cone[4]; facesTmp[9] = cone[3]; /* Back left */ 224412e9a14SMatthew G. Knepley facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[5]; facesTmp[13] = cone[4]; /* Front */ 225412e9a14SMatthew G. Knepley facesTmp[14] = cone[1]; facesTmp[15] = cone[0]; facesTmp[16] = cone[3]; facesTmp[17] = cone[5]; /* Back right */ 226ba2698f1SMatthew G. Knepley *faces = facesTmp; 22799836e0eSStefano Zampini } 22899836e0eSStefano Zampini break; 229ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 230412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 5; 231412e9a14SMatthew G. Knepley if (faceTypes) { 232412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_TRIANGLE; typesTmp[1] = DM_POLYTOPE_TRIANGLE; 233412e9a14SMatthew G. Knepley typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; 234412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 235412e9a14SMatthew G. Knepley } 236412e9a14SMatthew G. Knepley if (faceSizes) { 237412e9a14SMatthew G. Knepley sizesTmp[0] = 3; sizesTmp[1] = 3; 238412e9a14SMatthew G. Knepley sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; 239412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 240412e9a14SMatthew G. Knepley } 24199836e0eSStefano Zampini if (faces) { 242412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; /* Bottom */ 243412e9a14SMatthew G. Knepley facesTmp[3] = cone[3]; facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; /* Top */ 244412e9a14SMatthew G. Knepley facesTmp[6] = cone[0]; facesTmp[7] = cone[1]; facesTmp[8] = cone[3]; facesTmp[9] = cone[4]; /* Back left */ 245412e9a14SMatthew G. Knepley facesTmp[10] = cone[1]; facesTmp[11] = cone[2]; facesTmp[12] = cone[4]; facesTmp[13] = cone[5]; /* Back right */ 246412e9a14SMatthew G. Knepley facesTmp[14] = cone[2]; facesTmp[15] = cone[0]; facesTmp[16] = cone[5]; facesTmp[17] = cone[3]; /* Front */ 24799836e0eSStefano Zampini *faces = facesTmp; 24899836e0eSStefano Zampini } 249412e9a14SMatthew G. Knepley break; 250412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 251412e9a14SMatthew G. Knepley /* 7--------6 252412e9a14SMatthew G. Knepley /| /| 253412e9a14SMatthew G. Knepley / | / | 254412e9a14SMatthew G. Knepley 4--------5 | 255412e9a14SMatthew G. Knepley | | | | 256412e9a14SMatthew G. Knepley | | | | 257412e9a14SMatthew G. Knepley | 3--------2 258412e9a14SMatthew G. Knepley | / | / 259412e9a14SMatthew G. Knepley |/ |/ 260412e9a14SMatthew G. Knepley 0--------1 261412e9a14SMatthew G. Knepley */ 262412e9a14SMatthew G. Knepley if (numFaces) *numFaces = 6; 263412e9a14SMatthew G. Knepley if (faceTypes) { 264412e9a14SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; typesTmp[1] = DM_POLYTOPE_QUADRILATERAL; typesTmp[2] = DM_POLYTOPE_SEG_PRISM_TENSOR; 265412e9a14SMatthew G. Knepley typesTmp[3] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[4] = DM_POLYTOPE_SEG_PRISM_TENSOR; typesTmp[5] = DM_POLYTOPE_SEG_PRISM_TENSOR; 266412e9a14SMatthew G. Knepley *faceTypes = typesTmp; 267412e9a14SMatthew G. Knepley } 268412e9a14SMatthew G. Knepley if (faceSizes) { 269412e9a14SMatthew G. Knepley sizesTmp[0] = 4; sizesTmp[1] = 4; sizesTmp[2] = 4; sizesTmp[3] = 4; sizesTmp[4] = 4; sizesTmp[5] = 4; 270412e9a14SMatthew G. Knepley *faceSizes = sizesTmp; 271412e9a14SMatthew G. Knepley } 272412e9a14SMatthew G. Knepley if (faces) { 273412e9a14SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 274412e9a14SMatthew G. Knepley facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; facesTmp[6] = cone[6]; facesTmp[7] = cone[7]; /* Top */ 275412e9a14SMatthew G. Knepley facesTmp[8] = cone[0]; facesTmp[9] = cone[1]; facesTmp[10] = cone[4]; facesTmp[11] = cone[5]; /* Front */ 276412e9a14SMatthew G. Knepley facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[5]; facesTmp[15] = cone[6]; /* Right */ 277412e9a14SMatthew G. Knepley facesTmp[16] = cone[2]; facesTmp[17] = cone[3]; facesTmp[18] = cone[6]; facesTmp[19] = cone[7]; /* Back */ 278412e9a14SMatthew G. Knepley facesTmp[20] = cone[3]; facesTmp[21] = cone[0]; facesTmp[22] = cone[7]; facesTmp[23] = cone[4]; /* Left */ 279412e9a14SMatthew G. Knepley *faces = facesTmp; 280412e9a14SMatthew G. Knepley } 28199836e0eSStefano Zampini break; 282da9060c4SMatthew G. Knepley case DM_POLYTOPE_PYRAMID: 283da9060c4SMatthew G. Knepley /* 284da9060c4SMatthew G. Knepley 4---- 285da9060c4SMatthew G. Knepley |\-\ \----- 286da9060c4SMatthew G. Knepley | \ -\ \ 287da9060c4SMatthew G. Knepley | 1--\-----2 288da9060c4SMatthew G. Knepley | / \ / 289da9060c4SMatthew G. Knepley |/ \ / 290da9060c4SMatthew G. Knepley 0--------3 291da9060c4SMatthew G. Knepley */ 292da9060c4SMatthew G. Knepley if (numFaces) *numFaces = 5; 293da9060c4SMatthew G. Knepley if (faceTypes) { 294da9060c4SMatthew G. Knepley typesTmp[0] = DM_POLYTOPE_QUADRILATERAL; 295da9060c4SMatthew G. Knepley typesTmp[1] = DM_POLYTOPE_TRIANGLE; typesTmp[2] = DM_POLYTOPE_TRIANGLE; typesTmp[3] = DM_POLYTOPE_TRIANGLE; typesTmp[4] = DM_POLYTOPE_TRIANGLE; 296da9060c4SMatthew G. Knepley *faceTypes = typesTmp; 297da9060c4SMatthew G. Knepley } 298da9060c4SMatthew G. Knepley if (faceSizes) { 299da9060c4SMatthew G. Knepley sizesTmp[0] = 4; 300da9060c4SMatthew G. Knepley sizesTmp[1] = 3; sizesTmp[2] = 3; sizesTmp[3] = 3; sizesTmp[4] = 3; 301da9060c4SMatthew G. Knepley *faceSizes = sizesTmp; 302da9060c4SMatthew G. Knepley } 303da9060c4SMatthew G. Knepley if (faces) { 304da9060c4SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 305da9060c4SMatthew G. Knepley facesTmp[4] = cone[0]; facesTmp[5] = cone[3]; facesTmp[6] = cone[4]; /* Front */ 306da9060c4SMatthew G. Knepley facesTmp[7] = cone[3]; facesTmp[8] = cone[2]; facesTmp[9] = cone[4]; /* Right */ 307da9060c4SMatthew G. Knepley facesTmp[10] = cone[2]; facesTmp[11] = cone[1]; facesTmp[12] = cone[4]; /* Back */ 308da9060c4SMatthew G. Knepley facesTmp[13] = cone[1]; facesTmp[14] = cone[0]; facesTmp[15] = cone[4]; /* Left */ 309da9060c4SMatthew G. Knepley *faces = facesTmp; 310da9060c4SMatthew G. Knepley } 311da9060c4SMatthew G. Knepley break; 31298921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]); 31399836e0eSStefano Zampini } 31499836e0eSStefano Zampini PetscFunctionReturn(0); 31599836e0eSStefano Zampini } 31699836e0eSStefano Zampini 317412e9a14SMatthew G. Knepley PetscErrorCode DMPlexRestoreRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, const DMPolytopeType *faceTypes[], const PetscInt *faceSizes[], const PetscInt *faces[]) 31899836e0eSStefano Zampini { 31999836e0eSStefano Zampini PetscFunctionBegin; 3205f80ce2aSJacob Faibussowitsch if (faceTypes) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceTypes)); 3215f80ce2aSJacob Faibussowitsch if (faceSizes) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faceSizes)); 3225f80ce2aSJacob Faibussowitsch if (faces) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces)); 32399836e0eSStefano Zampini PetscFunctionReturn(0); 32499836e0eSStefano Zampini } 32599836e0eSStefano Zampini 3269a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */ 3279a5b13a2SMatthew G Knepley static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm) 3289f074e33SMatthew G Knepley { 329412e9a14SMatthew G. Knepley DMLabel ctLabel; 3309a5b13a2SMatthew G Knepley PetscHashIJKL faceTable; 331412e9a14SMatthew G. Knepley PetscInt faceTypeNum[DM_NUM_POLYTOPES]; 3329318fe57SMatthew G. Knepley PetscInt depth, d, pStart, Np, cStart, cEnd, c, fStart, fEnd; 3339f074e33SMatthew G Knepley 3349f074e33SMatthew G Knepley PetscFunctionBegin; 3355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 3365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLCreate(&faceTable)); 3375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(faceTypeNum, DM_NUM_POLYTOPES)); 3385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, cellDepth, &cStart, &cEnd)); 339412e9a14SMatthew G. Knepley /* Number new faces and save face vertices in hash table */ 3405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, depth > cellDepth ? cellDepth : 0, NULL, &fStart)); 341412e9a14SMatthew G. Knepley fEnd = fStart; 342412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 343412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 344412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 345ba2698f1SMatthew G. Knepley DMPolytopeType ct; 346412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 34799836e0eSStefano Zampini 3485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, c, &ct)); 3495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 3505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 351412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 352412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 353412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 354412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 3559a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 356e8f14785SLisandro Dalcin PetscHashIter iter; 357e8f14785SLisandro Dalcin PetscBool missing; 3589f074e33SMatthew G Knepley 3595f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 360412e9a14SMatthew G. Knepley key.i = face[0]; 361412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 362412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 363412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 3645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(faceSize, (PetscInt *) &key)); 3655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 366e9fa77a1SMatthew G. Knepley if (missing) { 3675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLIterSet(faceTable, iter, fEnd++)); 368412e9a14SMatthew G. Knepley ++faceTypeNum[faceType]; 369e9fa77a1SMatthew G. Knepley } 3709a5b13a2SMatthew G Knepley } 3715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 37299836e0eSStefano Zampini } 373412e9a14SMatthew G. Knepley /* We need to number faces contiguously among types */ 374412e9a14SMatthew G. Knepley { 375412e9a14SMatthew G. Knepley PetscInt faceTypeStart[DM_NUM_POLYTOPES], ct, numFT = 0; 37699836e0eSStefano Zampini 377412e9a14SMatthew G. Knepley for (ct = 0; ct < DM_NUM_POLYTOPES; ++ct) {if (faceTypeNum[ct]) ++numFT; faceTypeStart[ct] = 0;} 378412e9a14SMatthew G. Knepley if (numFT > 1) { 3795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLClear(faceTable)); 380412e9a14SMatthew G. Knepley faceTypeStart[0] = fStart; 381412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) faceTypeStart[ct] = faceTypeStart[ct-1] + faceTypeNum[ct-1]; 382412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 383412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 384412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 385ba2698f1SMatthew G. Knepley DMPolytopeType ct; 386412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 38799836e0eSStefano Zampini 3885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, c, &ct)); 3895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 3905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 391412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 392412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 393412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 394412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 39599836e0eSStefano Zampini PetscHashIJKLKey key; 39699836e0eSStefano Zampini PetscHashIter iter; 39799836e0eSStefano Zampini PetscBool missing; 39899836e0eSStefano Zampini 3995f80ce2aSJacob Faibussowitsch PetscCheck(faceSize <= 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %" PetscInt_FMT " > 4", faceSize); 400412e9a14SMatthew G. Knepley key.i = face[0]; 401412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 402412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 403412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 4045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(faceSize, (PetscInt *) &key)); 4055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 4065f80ce2aSJacob Faibussowitsch if (missing) CHKERRQ(PetscHashIJKLIterSet(faceTable, iter, faceTypeStart[faceType]++)); 40799836e0eSStefano Zampini } 4085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 40999836e0eSStefano Zampini } 410412e9a14SMatthew G. Knepley for (ct = 1; ct < DM_NUM_POLYTOPES; ++ct) { 4112c71b3e2SJacob Faibussowitsch PetscCheckFalse(faceTypeStart[ct] != faceTypeStart[ct-1] + faceTypeNum[ct],PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent numbering for cell type %s, %D != %D + %D", DMPolytopeTypes[ct], faceTypeStart[ct], faceTypeStart[ct-1], faceTypeNum[ct]); 4129a5b13a2SMatthew G Knepley } 4139a5b13a2SMatthew G Knepley } 414412e9a14SMatthew G. Knepley } 415412e9a14SMatthew G. Knepley /* Add new points, always at the end of the numbering */ 4165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &Np)); 4175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(idm, pStart, Np + (fEnd - fStart))); 4189a5b13a2SMatthew G Knepley /* Set cone sizes */ 419412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 4205f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(idm, "celltype")); 4215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellTypeLabel(idm, &ctLabel)); 4229a5b13a2SMatthew G Knepley for (d = 0; d <= depth; ++d) { 423412e9a14SMatthew G. Knepley DMPolytopeType ct; 424412e9a14SMatthew G. Knepley PetscInt coneSize, pStart, pEnd, p; 4259f074e33SMatthew G Knepley 426412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 4275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 428412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 4305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(idm, p, coneSize)); 4315f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, p, &ct)); 4325f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(idm, p, ct)); 4339f074e33SMatthew G Knepley } 4349f074e33SMatthew G Knepley } 435412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 436412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 437412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 438412e9a14SMatthew G. Knepley DMPolytopeType ct; 439412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 440412e9a14SMatthew G. Knepley 4415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, c, &ct)); 4425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 4435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 4445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(idm, c, ct)); 4455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(idm, c, numFaces)); 446412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 447412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 448412e9a14SMatthew G. Knepley const DMPolytopeType faceType = faceTypes[cf]; 449412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 450412e9a14SMatthew G. Knepley PetscHashIJKLKey key; 451412e9a14SMatthew G. Knepley PetscHashIter iter; 452412e9a14SMatthew G. Knepley PetscBool missing; 453412e9a14SMatthew G. Knepley PetscInt f; 454412e9a14SMatthew G. Knepley 4552c71b3e2SJacob Faibussowitsch PetscCheckFalse(faceSize > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize); 456412e9a14SMatthew G. Knepley key.i = face[0]; 457412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 458412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 459412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 4605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(faceSize, (PetscInt *) &key)); 4615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 462*28b400f6SJacob Faibussowitsch PetscCheck(!missing,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing face (cell %D, lf %D)", c, cf); 4635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLIterGet(faceTable, iter, &f)); 4645f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(idm, f, faceSize)); 4655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(idm, f, faceType)); 466412e9a14SMatthew G. Knepley } 4675f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 4689f074e33SMatthew G Knepley } 4695f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(idm)); 470412e9a14SMatthew G. Knepley /* Initialize cones so we do not need the bash table to tell us that a cone has been set */ 471412e9a14SMatthew G. Knepley { 472412e9a14SMatthew G. Knepley PetscSection cs; 473412e9a14SMatthew G. Knepley PetscInt *cones, csize; 4749a5b13a2SMatthew G Knepley 4755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSection(idm, &cs)); 4765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCones(idm, &cones)); 4775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(cs, &csize)); 478412e9a14SMatthew G. Knepley for (c = 0; c < csize; ++c) cones[c] = -1; 479412e9a14SMatthew G. Knepley } 480412e9a14SMatthew G. Knepley /* Set cones */ 481412e9a14SMatthew G. Knepley for (d = 0; d <= depth; ++d) { 482412e9a14SMatthew G. Knepley const PetscInt *cone; 483412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 484412e9a14SMatthew G. Knepley 485412e9a14SMatthew G. Knepley if (d == cellDepth) continue; 4865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 487412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4885f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 4895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(idm, p, cone)); 4905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm, p, &cone)); 4915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeOrientation(idm, p, cone)); 4929f074e33SMatthew G Knepley } 4939a5b13a2SMatthew G Knepley } 494412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 495412e9a14SMatthew G. Knepley const PetscInt *cone, *faceSizes, *faces; 496412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 497ba2698f1SMatthew G. Knepley DMPolytopeType ct; 498412e9a14SMatthew G. Knepley PetscInt numFaces, cf, foff = 0; 49999836e0eSStefano Zampini 5005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, c, &ct)); 5015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 5025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 503412e9a14SMatthew G. Knepley for (cf = 0; cf < numFaces; foff += faceSizes[cf], ++cf) { 504412e9a14SMatthew G. Knepley DMPolytopeType faceType = faceTypes[cf]; 505412e9a14SMatthew G. Knepley const PetscInt faceSize = faceSizes[cf]; 506412e9a14SMatthew G. Knepley const PetscInt *face = &faces[foff]; 507412e9a14SMatthew G. Knepley const PetscInt *fcone; 5089a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 509e8f14785SLisandro Dalcin PetscHashIter iter; 510e8f14785SLisandro Dalcin PetscBool missing; 511412e9a14SMatthew G. Knepley PetscInt f; 5129f074e33SMatthew G Knepley 5132c71b3e2SJacob Faibussowitsch PetscCheckFalse(faceSize > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not support faces of size %D > 4", faceSize); 514412e9a14SMatthew G. Knepley key.i = face[0]; 515412e9a14SMatthew G. Knepley key.j = faceSize > 1 ? face[1] : PETSC_MAX_INT; 516412e9a14SMatthew G. Knepley key.k = faceSize > 2 ? face[2] : PETSC_MAX_INT; 517412e9a14SMatthew G. Knepley key.l = faceSize > 3 ? face[3] : PETSC_MAX_INT; 5185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(faceSize, (PetscInt *) &key)); 5195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLPut(faceTable, key, &iter, &missing)); 5205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLIterGet(faceTable, iter, &f)); 5215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInsertCone(idm, c, cf, f)); 5225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(idm, f, &fcone)); 5235f80ce2aSJacob Faibussowitsch if (fcone[0] < 0) CHKERRQ(DMPlexSetCone(idm, f, face)); 524412e9a14SMatthew G. Knepley { 525412e9a14SMatthew G. Knepley const PetscInt *cone; 526412e9a14SMatthew G. Knepley PetscInt coneSize, ornt; 527a74221b0SStefano Zampini 5285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(idm, f, &coneSize)); 5295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(idm, f, &cone)); 5302c71b3e2SJacob Faibussowitsch PetscCheckFalse(coneSize != faceSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %D for face %D should be %D", coneSize, f, faceSize); 531d89e6e46SMatthew G. Knepley /* Notice that we have to use vertices here because the lower dimensional faces have not been created yet */ 5325f80ce2aSJacob Faibussowitsch CHKERRQ(DMPolytopeGetVertexOrientation(faceType, cone, face, &ornt)); 5335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInsertConeOrientation(idm, c, cf, ornt)); 53499836e0eSStefano Zampini } 53599836e0eSStefano Zampini } 5365f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, cone, &numFaces, &faceTypes, &faceSizes, &faces)); 53799836e0eSStefano Zampini } 5385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLDestroy(&faceTable)); 5395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(idm)); 5405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(idm)); 5419f074e33SMatthew G Knepley PetscFunctionReturn(0); 5429f074e33SMatthew G Knepley } 5439f074e33SMatthew G Knepley 544f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) 545f80536cbSVaclav Hapla { 546f80536cbSVaclav Hapla PetscInt nleaves; 547f80536cbSVaclav Hapla PetscInt nranks; 548a0d42dbcSVaclav Hapla const PetscMPIInt *ranks=NULL; 549a0d42dbcSVaclav Hapla const PetscInt *roffset=NULL, *rmine=NULL, *rremote=NULL; 550f80536cbSVaclav Hapla PetscInt n, o, r; 551f80536cbSVaclav Hapla 552f80536cbSVaclav Hapla PetscFunctionBegin; 5535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote)); 554f80536cbSVaclav Hapla nleaves = roffset[nranks]; 5555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(nleaves, rmine1, nleaves, rremote1)); 556f80536cbSVaclav Hapla for (r=0; r<nranks; r++) { 557f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 558f80536cbSVaclav Hapla - to unify order with the other side */ 559f80536cbSVaclav Hapla o = roffset[r]; 560f80536cbSVaclav Hapla n = roffset[r+1] - o; 5615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&(*rmine1)[o], &rmine[o], n)); 5625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&(*rremote1)[o], &rremote[o], n)); 5635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o])); 564f80536cbSVaclav Hapla } 565f80536cbSVaclav Hapla PetscFunctionReturn(0); 566f80536cbSVaclav Hapla } 567f80536cbSVaclav Hapla 56827d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm) 5692e745bdaSMatthew G. Knepley { 570d89e6e46SMatthew G. Knepley PetscSF sf; 571d89e6e46SMatthew G. Knepley const PetscInt *locals; 572d89e6e46SMatthew G. Knepley const PetscSFNode *remotes; 573d89e6e46SMatthew G. Knepley const PetscMPIInt *ranks; 574d89e6e46SMatthew G. Knepley const PetscInt *roffset; 575d89e6e46SMatthew G. Knepley PetscInt *rmine1, *rremote1; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 576d89e6e46SMatthew G. Knepley PetscInt nroots, p, nleaves, nranks, r, maxConeSize = 0; 577d89e6e46SMatthew G. Knepley PetscInt (*roots)[4], (*leaves)[4], mainCone[4]; 578d89e6e46SMatthew G. Knepley PetscMPIInt (*rootsRanks)[4], (*leavesRanks)[4]; 5792e745bdaSMatthew G. Knepley MPI_Comm comm; 58027d0e99aSVaclav Hapla PetscMPIInt rank, size; 5812e745bdaSMatthew G. Knepley PetscInt debug = 0; 5822e745bdaSMatthew G. Knepley 5832e745bdaSMatthew G. Knepley PetscFunctionBegin; 5845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 5855f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 5865f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 5875f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 5885f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(dm, NULL, "-before_orient_interface_dm_view")); 5895f80ce2aSJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) CHKERRQ(DMPlexCheckPointSF(dm)); 5905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes)); 591d89e6e46SMatthew G. Knepley if (nroots < 0) PetscFunctionReturn(0); 5925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetUp(sf)); 5935f80ce2aSJacob Faibussowitsch CHKERRQ(SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1)); 594d89e6e46SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 595d89e6e46SMatthew G. Knepley PetscInt coneSize; 5965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, locals[p], &coneSize)); 597d89e6e46SMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 598d89e6e46SMatthew G. Knepley } 5992c71b3e2SJacob Faibussowitsch PetscCheckFalse(maxConeSize > 4,comm, PETSC_ERR_SUP, "This method does not support cones of size %D", maxConeSize); 6005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks)); 6019e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 602d89e6e46SMatthew G. Knepley const PetscInt *cone; 603d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0; 604d89e6e46SMatthew G. Knepley 6055f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 6065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 607d89e6e46SMatthew G. Knepley /* Ignore vertices */ 60827d0e99aSVaclav Hapla if (coneSize < 2) { 609d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 61027d0e99aSVaclav Hapla roots[p][c] = -1; 61127d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 61227d0e99aSVaclav Hapla } 61327d0e99aSVaclav Hapla continue; 61427d0e99aSVaclav Hapla } 6152e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 616d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); c++) { 6175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(cone[c], nleaves, locals, &ind0)); 6188a650c75SVaclav Hapla if (ind0 < 0) { 6198a650c75SVaclav Hapla roots[p][c] = cone[c]; 6208a650c75SVaclav Hapla rootsRanks[p][c] = rank; 621c8148b97SVaclav Hapla } else { 6228a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 6238a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 6248a650c75SVaclav Hapla } 6252e745bdaSMatthew G. Knepley } 626d89e6e46SMatthew G. Knepley for (c = coneSize; c < 4; c++) { 627d89e6e46SMatthew G. Knepley roots[p][c] = -1; 628d89e6e46SMatthew G. Knepley rootsRanks[p][c] = -1; 629d89e6e46SMatthew G. Knepley } 6302e745bdaSMatthew G. Knepley } 6319e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 632d89e6e46SMatthew G. Knepley PetscInt c; 633d89e6e46SMatthew G. Knepley for (c = 0; c < 4; c++) { 6348ccb905dSVaclav Hapla leaves[p][c] = -2; 6358ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 6368ccb905dSVaclav Hapla } 637c8148b97SVaclav Hapla } 6385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 6395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 6405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sf, MPIU_4INT, roots, leaves, MPI_REPLACE)); 6415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sf, MPI_4INT, rootsRanks, leavesRanks, MPI_REPLACE)); 642d89e6e46SMatthew G. Knepley if (debug) { 6435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedFlush(comm, NULL)); 6445f80ce2aSJacob Faibussowitsch if (!rank) CHKERRQ(PetscSynchronizedPrintf(comm, "Referenced roots\n")); 645d89e6e46SMatthew G. Knepley } 6465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL)); 6479e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 648d89e6e46SMatthew G. Knepley DMPolytopeType ct; 649d89e6e46SMatthew G. Knepley const PetscInt *cone; 650d89e6e46SMatthew G. Knepley PetscInt coneSize, c, ind0, o; 651d89e6e46SMatthew G. Knepley 652d89e6e46SMatthew G. Knepley if (leaves[p][0] < 0) continue; /* Ignore vertices */ 6535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, p, &ct)); 6545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 6555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 656d89e6e46SMatthew G. Knepley if (debug) { 6575f80ce2aSJacob Faibussowitsch CHKERRQ(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)]", 658d89e6e46SMatthew G. Knepley rank, p, cone[0], cone[1], cone[2], cone[3], 659d89e6e46SMatthew 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], 6605f80ce2aSJacob Faibussowitsch leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1], leavesRanks[p][2], leaves[p][2], leavesRanks[p][3], leaves[p][3])); 661d89e6e46SMatthew G. Knepley } 662d89e6e46SMatthew G. Knepley if (leavesRanks[p][0] != rootsRanks[p][0] || leaves[p][0] != roots[p][0] || 663d89e6e46SMatthew G. Knepley leavesRanks[p][1] != rootsRanks[p][1] || leaves[p][1] != roots[p][1] || 664d89e6e46SMatthew G. Knepley leavesRanks[p][2] != rootsRanks[p][2] || leaves[p][2] != roots[p][2] || 665d89e6e46SMatthew G. Knepley leavesRanks[p][3] != rootsRanks[p][3] || leaves[p][3] != roots[p][3]) { 666d89e6e46SMatthew G. Knepley /* Translate these leaves to my cone points; mainCone means desired order p's cone points */ 667d89e6e46SMatthew G. Knepley for (c = 0; c < PetscMin(coneSize, 4); ++c) { 668d89e6e46SMatthew G. Knepley PetscInt rS, rN; 669d89e6e46SMatthew G. Knepley 67027d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 671d89e6e46SMatthew G. Knepley /* A local leaf is just taken as it is */ 6729dddd249SSatish Balay mainCone[c] = leaves[p][c]; 67327d0e99aSVaclav Hapla continue; 67427d0e99aSVaclav Hapla } 675f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 676f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 6775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindMPIInt((PetscMPIInt) leavesRanks[p][c], nranks, ranks, &r)); 6782c71b3e2SJacob Faibussowitsch PetscCheckFalse(r < 0,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]); 6792c71b3e2SJacob Faibussowitsch PetscCheckFalse(ranks[r] < 0 || ranks[r] >= size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%D c=%D commsize=%d: ranks[%D] = %d makes no sense", p, c, size, r, ranks[r]); 680f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 681d89e6e46SMatthew G. Knepley rS = roffset[r]; 682d89e6e46SMatthew G. Knepley rN = roffset[r+1] - rS; 6835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(leaves[p][c], rN, &rremote1[rS], &ind0)); 6842c71b3e2SJacob Faibussowitsch PetscCheckFalse(ind0 < 0,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]); 685f80536cbSVaclav Hapla /* Get the corresponding local point */ 6865f80ce2aSJacob Faibussowitsch mainCone[c] = rmine1[rS + ind0]; 687f80536cbSVaclav Hapla } 6885f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, " mainCone=[%4D %4D %4D %4D]\n", mainCone[0], mainCone[1], mainCone[2], mainCone[3])); 68927d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 6905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPolytopeGetOrientation(ct, cone, mainCone, &o)); 6915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexOrientPoint(dm, p, o)); 6925f80ce2aSJacob Faibussowitsch } else if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, " ==\n")); 69323aaf07bSVaclav Hapla } 69427d0e99aSVaclav Hapla if (debug) { 6955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedFlush(comm, NULL)); 6965f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Barrier(comm)); 6972e745bdaSMatthew G. Knepley } 6985f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(dm, NULL, "-after_orient_interface_dm_view")); 6995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(roots, leaves, rootsRanks, leavesRanks)); 7005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(rmine1, rremote1)); 7012e745bdaSMatthew G. Knepley PetscFunctionReturn(0); 7022e745bdaSMatthew G. Knepley } 7032e745bdaSMatthew G. Knepley 7042e72742cSMatthew 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[]) 7057bffde78SMichael Lange { 7062e72742cSMatthew G. Knepley PetscInt idx; 7072e72742cSMatthew G. Knepley PetscMPIInt rank; 7082e72742cSMatthew G. Knepley PetscBool flg; 7097bffde78SMichael Lange 7107bffde78SMichael Lange PetscFunctionBegin; 7115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL, NULL, opt, &flg)); 7122e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 7135f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 7145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 7155f80ce2aSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]%s %D %s %D\n", rank, idxname, idx, valname, a[idx])); 7165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedFlush(comm, NULL)); 7172e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7182e72742cSMatthew G. Knepley } 7192e72742cSMatthew G. Knepley 7202e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) 7212e72742cSMatthew G. Knepley { 7222e72742cSMatthew G. Knepley PetscInt idx; 7232e72742cSMatthew G. Knepley PetscMPIInt rank; 7242e72742cSMatthew G. Knepley PetscBool flg; 7252e72742cSMatthew G. Knepley 7262e72742cSMatthew G. Knepley PetscFunctionBegin; 7275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL, NULL, opt, &flg)); 7282e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 7295f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 7305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name)); 7312e72742cSMatthew G. Knepley if (idxname) { 7325f80ce2aSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]%s %D rank %D index %D\n", rank, idxname, idx, a[idx].rank, a[idx].index)); 7332e72742cSMatthew G. Knepley } else { 7345f80ce2aSJacob Faibussowitsch for (idx = 0; idx < n; ++idx) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d]rank %D index %D\n", rank, a[idx].rank, a[idx].index)); 7352e72742cSMatthew G. Knepley } 7365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedFlush(comm, NULL)); 7372e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7382e72742cSMatthew G. Knepley } 7392e72742cSMatthew G. Knepley 7405f80ce2aSJacob Faibussowitsch static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint, PetscBool *mapFailed) 7412e72742cSMatthew G. Knepley { 7423be36e83SMatthew G. Knepley PetscSF sf; 7433be36e83SMatthew G. Knepley const PetscInt *locals; 7443be36e83SMatthew G. Knepley PetscMPIInt rank; 7452e72742cSMatthew G. Knepley 7462e72742cSMatthew G. Knepley PetscFunctionBegin; 7475f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 7485f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 7495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sf, NULL, NULL, &locals, NULL)); 7505f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 7512e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 7522e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 7532e72742cSMatthew G. Knepley } else { 7542e72742cSMatthew G. Knepley PetscHashIJKey key; 7553be36e83SMatthew G. Knepley PetscInt l; 7562e72742cSMatthew G. Knepley 7572e72742cSMatthew G. Knepley key.i = remotePoint.index; 7582e72742cSMatthew G. Knepley key.j = remotePoint.rank; 7595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJGet(remotehash, key, &l)); 7603be36e83SMatthew G. Knepley if (l >= 0) { 7613be36e83SMatthew G. Knepley *localPoint = locals[l]; 7625f80ce2aSJacob Faibussowitsch } else if (mapFailed) *mapFailed = PETSC_TRUE; 7632e72742cSMatthew G. Knepley } 7642e72742cSMatthew G. Knepley PetscFunctionReturn(0); 7652e72742cSMatthew G. Knepley } 7662e72742cSMatthew G. Knepley 7675f80ce2aSJacob Faibussowitsch static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint, PetscBool *mapFailed) 7683be36e83SMatthew G. Knepley { 7693be36e83SMatthew G. Knepley PetscSF sf; 7703be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 7713be36e83SMatthew G. Knepley const PetscSFNode *remotes; 7723be36e83SMatthew G. Knepley PetscInt Nl, l; 7733be36e83SMatthew G. Knepley PetscMPIInt rank; 7743be36e83SMatthew G. Knepley 7753be36e83SMatthew G. Knepley PetscFunctionBegin; 7765f80ce2aSJacob Faibussowitsch if (mapFailed) *mapFailed = PETSC_FALSE; 7775f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 7785f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 7795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes)); 7803be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 7815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeBegin(sf, &rootdegree)); 7825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeEnd(sf, &rootdegree)); 7833be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 7845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(localPoint, Nl, locals, &l)); 7855f80ce2aSJacob Faibussowitsch if (l < 0) {if (mapFailed) *mapFailed = PETSC_TRUE;} 7865f80ce2aSJacob Faibussowitsch else *remotePoint = remotes[l]; 7873be36e83SMatthew G. Knepley PetscFunctionReturn(0); 7883be36e83SMatthew G. Knepley owned: 7893be36e83SMatthew G. Knepley remotePoint->rank = rank; 7903be36e83SMatthew G. Knepley remotePoint->index = localPoint; 7913be36e83SMatthew G. Knepley PetscFunctionReturn(0); 7923be36e83SMatthew G. Knepley } 7933be36e83SMatthew G. Knepley 7943be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) 7953be36e83SMatthew G. Knepley { 7963be36e83SMatthew G. Knepley PetscSF sf; 7973be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 7983be36e83SMatthew G. Knepley PetscInt Nl, idx; 7993be36e83SMatthew G. Knepley 8003be36e83SMatthew G. Knepley PetscFunctionBegin; 8013be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 8025f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 8035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL)); 8043be36e83SMatthew G. Knepley if (Nl < 0) PetscFunctionReturn(0); 8055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(p, Nl, locals, &idx)); 8063be36e83SMatthew G. Knepley if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);} 8075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeBegin(sf, &rootdegree)); 8085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeEnd(sf, &rootdegree)); 8093be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 8103be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8113be36e83SMatthew G. Knepley } 8123be36e83SMatthew G. Knepley 8133be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) 8143be36e83SMatthew G. Knepley { 8153be36e83SMatthew G. Knepley const PetscInt *cone; 8163be36e83SMatthew G. Knepley PetscInt coneSize, c; 8173be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 8183be36e83SMatthew G. Knepley 8193be36e83SMatthew G. Knepley PetscFunctionBegin; 8205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 8215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 8223be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8233be36e83SMatthew G. Knepley PetscBool pointShared; 8243be36e83SMatthew G. Knepley 8255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointIsShared(dm, cone[c], &pointShared)); 8263be36e83SMatthew G. Knepley cShared = (PetscBool) (cShared && pointShared); 8273be36e83SMatthew G. Knepley } 8283be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 8293be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8303be36e83SMatthew G. Knepley } 8313be36e83SMatthew G. Knepley 8323be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) 8333be36e83SMatthew G. Knepley { 8343be36e83SMatthew G. Knepley const PetscInt *cone; 8353be36e83SMatthew G. Knepley PetscInt coneSize, c; 8363be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 8373be36e83SMatthew G. Knepley 8383be36e83SMatthew G. Knepley PetscFunctionBegin; 8395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 8405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 8413be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 8423be36e83SMatthew G. Knepley PetscSFNode rcp; 8435f80ce2aSJacob Faibussowitsch PetscBool mapFailed; 8443be36e83SMatthew G. Knepley 8455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMapToGlobalPoint(dm, cone[c], &rcp, &mapFailed)); 8465f80ce2aSJacob Faibussowitsch if (mapFailed) { 8473be36e83SMatthew G. Knepley cmin = missing; 8483be36e83SMatthew G. Knepley } else { 8493be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 8503be36e83SMatthew G. Knepley } 8513be36e83SMatthew G. Knepley } 8523be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 8533be36e83SMatthew G. Knepley PetscFunctionReturn(0); 8543be36e83SMatthew G. Knepley } 8553be36e83SMatthew G. Knepley 8563be36e83SMatthew G. Knepley /* 8573be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 8583be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 8593be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 8603be36e83SMatthew G. Knepley */ 8613be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) 8623be36e83SMatthew G. Knepley { 8633be36e83SMatthew G. Knepley MPI_Comm comm; 8643be36e83SMatthew G. Knepley const PetscInt *support; 865cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height; 8663be36e83SMatthew G. Knepley PetscMPIInt rank; 8673be36e83SMatthew G. Knepley 8683be36e83SMatthew G. Knepley PetscFunctionBegin; 8695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 8705f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 8715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetOverlap(dm, &overlap)); 8725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight)); 8735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPointHeight(dm, p, &height)); 874cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight+1) { 875cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */ 8765f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Skipping face %D to avoid adding cell to hashmap since this is nonoverlapping mesh\n", rank, p)); 877cf4dc471SVaclav Hapla PetscFunctionReturn(0); 878cf4dc471SVaclav Hapla } 8795f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize)); 8805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, p, &support)); 8815f80ce2aSJacob Faibussowitsch if (candidates) CHKERRQ(PetscSectionGetOffset(candidateSection, p, &off)); 8823be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8833be36e83SMatthew G. Knepley const PetscInt face = support[s]; 8843be36e83SMatthew G. Knepley const PetscInt *cone; 8853be36e83SMatthew G. Knepley PetscSFNode cpmin={-1,-1}, rp={-1,-1}; 8863be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 8873be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 8883be36e83SMatthew G. Knepley PetscHashIJKey key; 8893be36e83SMatthew G. Knepley 8903be36e83SMatthew G. Knepley /* Only add point once */ 8915f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Support face %D\n", rank, face)); 8923be36e83SMatthew G. Knepley key.i = p; 8933be36e83SMatthew G. Knepley key.j = face; 8945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJGet(faceHash, key, &f)); 8953be36e83SMatthew G. Knepley if (f >= 0) continue; 8965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexConeIsShared(dm, face, &isShared)); 8975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeMinimum(dm, face, &cpmin)); 8985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMapToGlobalPoint(dm, p, &rp, NULL)); 8993be36e83SMatthew G. Knepley if (debug) { 9005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Face point %D is shared: %d\n", rank, face, (int) isShared)); 9015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Global point (%D, %D) Min Cone Point (%D, %D)\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index)); 9023be36e83SMatthew G. Knepley } 9033be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 9045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJSet(faceHash, key, p)); 9053be36e83SMatthew G. Knepley if (candidates) { 9065f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Adding shared face %D at idx %D\n[%d] ", rank, face, idx, rank)); 9075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, face, &coneSize)); 9085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, face, &cone)); 9093be36e83SMatthew G. Knepley candidates[off+idx].rank = -1; 9103be36e83SMatthew G. Knepley candidates[off+idx++].index = coneSize-1; 9113be36e83SMatthew G. Knepley candidates[off+idx].rank = rank; 9123be36e83SMatthew G. Knepley candidates[off+idx++].index = face; 9133be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9143be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 9153be36e83SMatthew G. Knepley 9163be36e83SMatthew G. Knepley if (cp == p) continue; 9175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx], NULL)); 9185f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index)); 9193be36e83SMatthew G. Knepley ++idx; 9203be36e83SMatthew G. Knepley } 9215f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "\n")); 9223be36e83SMatthew G. Knepley } else { 9233be36e83SMatthew G. Knepley /* Add cone size to section */ 9245f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %D\n", rank, face)); 9255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, face, &coneSize)); 9265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJSet(faceHash, key, p)); 9275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(candidateSection, p, coneSize+1)); 9283be36e83SMatthew G. Knepley } 9293be36e83SMatthew G. Knepley } 9303be36e83SMatthew G. Knepley } 9313be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9323be36e83SMatthew G. Knepley } 9333be36e83SMatthew G. Knepley 9342e72742cSMatthew G. Knepley /*@ 9352e72742cSMatthew G. Knepley DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation 9362e72742cSMatthew G. Knepley 937d083f849SBarry Smith Collective on dm 9382e72742cSMatthew G. Knepley 9392e72742cSMatthew G. Knepley Input Parameters: 9402e72742cSMatthew G. Knepley + dm - The interpolated DM 9412e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points 9422e72742cSMatthew G. Knepley 9432e72742cSMatthew G. Knepley Output Parameter: 9442e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points 9452e72742cSMatthew G. Knepley 946f0cfc026SVaclav Hapla Level: developer 9472e72742cSMatthew G. Knepley 9482e72742cSMatthew 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 9492e72742cSMatthew G. Knepley 9502e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate() 9512e72742cSMatthew G. Knepley @*/ 952e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 9532e72742cSMatthew G. Knepley { 9543be36e83SMatthew G. Knepley MPI_Comm comm; 9553be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 9563be36e83SMatthew G. Knepley PetscHMapI claimshash; 9573be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 9583be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 9592e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 9602e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 9613be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 9623be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 9633be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 964f0cfc026SVaclav Hapla PetscMPIInt rank; 9652e72742cSMatthew G. Knepley 9662e72742cSMatthew G. Knepley PetscFunctionBegin; 967f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 968064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 9695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsDistributed(dm, &flg)); 970f0cfc026SVaclav Hapla if (!flg) PetscFunctionReturn(0); 9713be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 9725f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dm, pointSF)); 9735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 9745f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 9755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetOverlap(dm, &ov)); 976*28b400f6SJacob Faibussowitsch PetscCheck(!ov,comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 9775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug)); 9785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view")); 9795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view")); 9805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0)); 9813be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 9825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints)); 9832c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nr < 0,comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 9845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJCreate(&remoteHash)); 9853be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 9863be36e83SMatthew G. Knepley PetscHashIJKey key; 9872e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 9882e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 9895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJSet(remoteHash, key, l)); 9907bffde78SMichael Lange } 99166aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 9925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 9935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9945f80ce2aSJacob Faibussowitsch CHKERRQ(IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree)); 9953be36e83SMatthew G. Knepley /* 9963be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 9973be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 9983be36e83SMatthew G. Knepley \begin{itemize} 9993be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 10003be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 10013be36e83SMatthew G. Knepley \end{itemize} 10023be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 10033be36e83SMatthew 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 10043be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 10053be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 10063be36e83SMatthew G. Knepley */ 10073be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 10083be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 10093be36e83SMatthew G. Knepley The array holds candidate shared faces, each face is refered to by the leaf point */ 10105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &candidateSection)); 10115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(candidateSection, 0, Nr)); 10127bffde78SMichael Lange { 10133be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 10142e72742cSMatthew G. Knepley 10155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJCreate(&faceHash)); 10163be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 10173be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 10182e72742cSMatthew G. Knepley 10195f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %D\n", rank, p)); 10205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug)); 10212e72742cSMatthew G. Knepley } 10225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJClear(faceHash)); 10235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(candidateSection)); 10245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(candidateSection, &candidatesSize)); 10255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(candidatesSize, &candidates)); 10263be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 10273be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 10282e72742cSMatthew G. Knepley 10295f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %D\n", rank, p)); 10305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug)); 10312e72742cSMatthew G. Knepley } 10325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJDestroy(&faceHash)); 10335f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedFlush(comm, NULL)); 10347bffde78SMichael Lange } 10355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) candidateSection, "Candidate Section")); 10365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view")); 10375f80ce2aSJacob Faibussowitsch CHKERRQ(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates)); 10383be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 10392e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 10407bffde78SMichael Lange { 10417bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 10427bffde78SMichael Lange PetscInt *remoteOffsets; 10432e72742cSMatthew G. Knepley 10445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetMultiSF(pointSF, &sfMulti)); 10455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateInverseSF(sfMulti, &sfInverse)); 10465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &candidateRemoteSection)); 10475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection)); 10485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates)); 10495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize)); 10505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(candidatesRemoteSize, &candidatesRemote)); 10515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE)); 10525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote,MPI_REPLACE)); 10535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfInverse)); 10545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfCandidates)); 10555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsets)); 10562e72742cSMatthew G. Knepley 10575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section")); 10585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view")); 10595f80ce2aSJacob Faibussowitsch CHKERRQ(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote)); 10607bffde78SMichael Lange } 10613be36e83SMatthew 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 */ 10627bffde78SMichael Lange { 10633be36e83SMatthew G. Knepley PetscHashIJKLRemote faceTable; 10643be36e83SMatthew G. Knepley PetscInt idx, idx2; 10653be36e83SMatthew G. Knepley 10665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemoteCreate(&faceTable)); 10672e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 10683be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 10692e72742cSMatthew G. Knepley PetscInt deg; 10703be36e83SMatthew G. Knepley 10712e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 10722e72742cSMatthew G. Knepley PetscInt offset, dof, d; 10732e72742cSMatthew G. Knepley 10745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(candidateRemoteSection, idx, &dof)); 10755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(candidateRemoteSection, idx, &offset)); 10763be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 10772e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 10783be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 10793be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 10803be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx+1]; 10813be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 10823be36e83SMatthew G. Knepley PetscSFNode fcp0; 10833be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 10842e72742cSMatthew G. Knepley const PetscInt *join = NULL; 10853be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 10863be36e83SMatthew G. Knepley PetscHashIter iter; 10875f80ce2aSJacob Faibussowitsch PetscBool missing,mapToLocalPointFailed = PETSC_FALSE; 10882e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 10892e72742cSMatthew G. Knepley 10905f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(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)); 10912c71b3e2SJacob Faibussowitsch PetscCheckFalse(Np > 4,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); 10923be36e83SMatthew G. Knepley fcp0.rank = rank; 10933be36e83SMatthew G. Knepley fcp0.index = r; 10943be36e83SMatthew G. Knepley d += Np; 10953be36e83SMatthew G. Knepley /* Put remote face in hash table */ 10963be36e83SMatthew G. Knepley key.i = fcp0; 10973be36e83SMatthew G. Knepley key.j = fcone[0]; 10983be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 10993be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 11005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortSFNode(Np, (PetscSFNode *) &key)); 11015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing)); 11023be36e83SMatthew G. Knepley if (missing) { 11035f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Setting remote face (%D, %D)\n", rank, rface.index, rface.rank)); 11045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemoteIterSet(faceTable, iter, rface)); 11053be36e83SMatthew G. Knepley } else { 11063be36e83SMatthew G. Knepley PetscSFNode oface; 11073be36e83SMatthew G. Knepley 11085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface)); 11093be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 11105f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank)); 11115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemoteIterSet(faceTable, iter, rface)); 11123be36e83SMatthew G. Knepley } 11133be36e83SMatthew G. Knepley } 11143be36e83SMatthew G. Knepley /* Check for local face */ 11152e72742cSMatthew G. Knepley points[0] = r; 11163be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 11175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p], &mapToLocalPointFailed)); 11185f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) break; /* We got a point not in our overlap */ 11195f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking local candidate %D\n", rank, points[p])); 11207bffde78SMichael Lange } 11215f80ce2aSJacob Faibussowitsch if (mapToLocalPointFailed) continue; 11225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetJoin(dm, Np, points, &joinSize, &join)); 11237bffde78SMichael Lange if (joinSize == 1) { 11243be36e83SMatthew G. Knepley PetscSFNode lface; 11253be36e83SMatthew G. Knepley PetscSFNode oface; 11263be36e83SMatthew G. Knepley 11273be36e83SMatthew G. Knepley /* Always replace with local face */ 11283be36e83SMatthew G. Knepley lface.rank = rank; 11293be36e83SMatthew G. Knepley lface.index = join[0]; 11305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemoteIterGet(faceTable, iter, &oface)); 11315f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing (%D, %D) with local face (%D, %D)\n", rank, oface.index, oface.rank, lface.index, lface.rank)); 11325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemoteIterSet(faceTable, iter, lface)); 11337bffde78SMichael Lange } 11345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreJoin(dm, Np, points, &joinSize, &join)); 11353be36e83SMatthew G. Knepley } 11363be36e83SMatthew G. Knepley } 11373be36e83SMatthew G. Knepley /* Put back faces for this root */ 11383be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 11393be36e83SMatthew G. Knepley PetscInt offset, dof, d; 11403be36e83SMatthew G. Knepley 11415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(candidateRemoteSection, idx2, &dof)); 11425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(candidateRemoteSection, idx2, &offset)); 11433be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 11443be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 11453be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 11463be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 11473be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 11483be36e83SMatthew G. Knepley PetscSFNode fcp0; 11493be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 11503be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 11513be36e83SMatthew G. Knepley PetscHashIter iter; 11523be36e83SMatthew G. Knepley PetscBool missing; 11533be36e83SMatthew G. Knepley 11545f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Entering face at (%D, %D)\n", rank, r, idx)); 11552c71b3e2SJacob Faibussowitsch PetscCheckFalse(Np > 4,PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np); 11563be36e83SMatthew G. Knepley fcp0.rank = rank; 11573be36e83SMatthew G. Knepley fcp0.index = r; 11583be36e83SMatthew G. Knepley d += Np; 11593be36e83SMatthew G. Knepley /* Find remote face in hash table */ 11603be36e83SMatthew G. Knepley key.i = fcp0; 11613be36e83SMatthew G. Knepley key.j = fcone[0]; 11623be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 11633be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 11645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortSFNode(Np, (PetscSFNode *) &key)); 11655f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(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)); 11665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemotePut(faceTable, key, &iter, &missing)); 1167*28b400f6SJacob Faibussowitsch PetscCheck(!missing,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an associated face", r, idx2); 11685f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx])); 11697bffde78SMichael Lange } 11707bffde78SMichael Lange } 11717bffde78SMichael Lange } 11725f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL)); 11735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHashIJKLRemoteDestroy(&faceTable)); 11747bffde78SMichael Lange } 11753be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 11767bffde78SMichael Lange { 11777bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 11787bffde78SMichael Lange PetscSFNode *remotePointsNew; 11792e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 11803be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 11812e72742cSMatthew G. Knepley 11823be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 11835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetMultiSF(pointSF, &sfMulti)); 11845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &claimSection)); 11855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection)); 11865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims)); 11875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(claimSection, &claimsSize)); 11885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(claimsSize, &claims)); 11893be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 11905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE)); 11915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims,MPI_REPLACE)); 11925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfClaims)); 11935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsets)); 11945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) claimSection, "Claim Section")); 11955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view")); 11965f80ce2aSJacob Faibussowitsch CHKERRQ(SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims)); 11973be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 11983be36e83SMatthew 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 */ 11995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapICreate(&claimshash)); 12003be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 12013be36e83SMatthew G. Knepley PetscInt dof, off, d; 12022e72742cSMatthew G. Knepley 12035f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %D\n", rank, r)); 12045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(candidateSection, r, &dof)); 12055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(candidateSection, r, &off)); 12062e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 12073be36e83SMatthew G. Knepley if (claims[off+d].rank >= 0) { 12083be36e83SMatthew G. Knepley const PetscInt faceInd = off+d; 12093be36e83SMatthew G. Knepley const PetscInt Np = candidates[off+d].index; 12102e72742cSMatthew G. Knepley const PetscInt *join = NULL; 12112e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 12122e72742cSMatthew G. Knepley 12135f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Found claim for remote point (%D, %D)\n", rank, claims[faceInd].rank, claims[faceInd].index)); 12143be36e83SMatthew G. Knepley points[0] = r; 12155f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[0])); 12163be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 12175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1], NULL)); 12185f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[c+1])); 12192e72742cSMatthew G. Knepley } 12205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetJoin(dm, Np+1, points, &joinSize, &join)); 12212e72742cSMatthew G. Knepley if (joinSize == 1) { 12223be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 12235f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %D for non-remote partner\n", rank, join[0])); 12243be36e83SMatthew G. Knepley } else { 12255f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Found local face %D\n", rank, join[0])); 12265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapISet(claimshash, join[0], faceInd)); 12272e72742cSMatthew G. Knepley } 12283be36e83SMatthew G. Knepley } else { 12295f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank)); 12303be36e83SMatthew G. Knepley } 12315f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join)); 12323be36e83SMatthew G. Knepley } else { 12335f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] No claim for point %D\n", rank, r)); 12343be36e83SMatthew G. Knepley d += claims[off+d].index+1; 12357bffde78SMichael Lange } 12367bffde78SMichael Lange } 12373be36e83SMatthew G. Knepley } 12385f80ce2aSJacob Faibussowitsch if (debug) CHKERRQ(PetscSynchronizedFlush(comm, NULL)); 12393be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 12405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIGetSize(claimshash, &NlNew)); 12415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 12425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Nl + NlNew, &localPointsNew)); 12435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Nl + NlNew, &remotePointsNew)); 12443be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 12453be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 12463be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 12473be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 12487bffde78SMichael Lange } 12493be36e83SMatthew G. Knepley p = Nl; 12505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIGetKeys(claimshash, &p, localPointsNew)); 12513be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 12525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(NlNew, &localPointsNew[Nl])); 12533be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 12543be36e83SMatthew G. Knepley PetscInt off; 12555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIGet(claimshash, localPointsNew[p], &off)); 12562c71b3e2SJacob Faibussowitsch PetscCheckFalse(claims[off].rank < 0 || claims[off].index < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %D, (%D, %D)", localPointsNew[p], claims[off].rank, claims[off].index); 12573be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 12587bffde78SMichael Lange } 12595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(comm, &sfPointNew)); 12605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 12615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetUp(sfPointNew)); 12625f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(dm, sfPointNew)); 12635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view")); 12645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfPointNew)); 12655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIDestroy(&claimshash)); 12667bffde78SMichael Lange } 12675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIJDestroy(&remoteHash)); 12685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&candidateSection)); 12695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&candidateRemoteSection)); 12705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&claimSection)); 12715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(candidates)); 12725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(candidatesRemote)); 12735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(claims)); 12745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0)); 12757bffde78SMichael Lange PetscFunctionReturn(0); 12767bffde78SMichael Lange } 12777bffde78SMichael Lange 1278248eb259SVaclav Hapla /*@ 127980330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 128080330477SMatthew G. Knepley 1281d083f849SBarry Smith Collective on dm 128280330477SMatthew G. Knepley 1283e56d480eSMatthew G. Knepley Input Parameters: 1284e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices 128510a67516SMatthew G. Knepley - dmInt - The interpolated DM 128680330477SMatthew G. Knepley 128780330477SMatthew G. Knepley Output Parameter: 12884e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object 128980330477SMatthew G. Knepley 129080330477SMatthew G. Knepley Level: intermediate 129180330477SMatthew G. Knepley 129295452b02SPatrick Sanan Notes: 129395452b02SPatrick Sanan It does not copy over the coordinates. 129443eeeb2dSStefano Zampini 12959ade3219SVaclav Hapla Developer Notes: 12969ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL. 12979ade3219SVaclav Hapla 1298a4a685f2SJacob Faibussowitsch .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates() 129980330477SMatthew G. Knepley @*/ 13009f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 13019f074e33SMatthew G Knepley { 1302a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 13039a5b13a2SMatthew G Knepley DM idm, odm = dm; 13047bffde78SMichael Lange PetscSF sfPoint; 13052e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 130610a67516SMatthew G. Knepley const char *name; 1307b325530aSVaclav Hapla PetscBool flg=PETSC_TRUE; 13089f074e33SMatthew G Knepley 13099f074e33SMatthew G Knepley PetscFunctionBegin; 131010a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 131110a67516SMatthew G. Knepley PetscValidPointer(dmInt, 2); 13125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0)); 13135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 13145f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 13155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated(dm, &interpolated)); 13162c71b3e2SJacob Faibussowitsch PetscCheckFalse(interpolated == DMPLEX_INTERPOLATED_PARTIAL,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1317827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 13185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dm)); 131976b791aaSMatthew G. Knepley idm = dm; 1320b21b8912SMatthew G. Knepley } else { 13219a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 13229a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 13235f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PetscObjectComm((PetscObject)dm), &idm)); 13245f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(idm, DMPLEX)); 13255f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(idm, dim)); 13267bffde78SMichael Lange if (depth > 0) { 13275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolateFaces_Internal(odm, 1, idm)); 13285f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(odm, &sfPoint)); 132994488200SVaclav Hapla { 13303be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 133194488200SVaclav Hapla PetscInt nroots; 13325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 13335f80ce2aSJacob Faibussowitsch if (nroots >= 0) CHKERRQ(DMPlexInterpolatePointSF(idm, sfPoint)); 133494488200SVaclav Hapla } 13357bffde78SMichael Lange } 13365f80ce2aSJacob Faibussowitsch if (odm != dm) CHKERRQ(DMDestroy(&odm)); 13379a5b13a2SMatthew G Knepley odm = idm; 13389f074e33SMatthew G Knepley } 13395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) dm, &name)); 13405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) idm, name)); 13415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopyCoordinates(dm, idm)); 13425f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_FAIL)); 13435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL)); 13445f80ce2aSJacob Faibussowitsch if (flg) CHKERRQ(DMPlexOrientInterface_Internal(idm)); 134584699f70SSatish Balay } 1346827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1347827c4036SVaclav Hapla { 1348d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) idm->data; 1349827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1350827c4036SVaclav Hapla } 13515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, idm)); 13529a5b13a2SMatthew G Knepley *dmInt = idm; 13535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0)); 13549f074e33SMatthew G Knepley PetscFunctionReturn(0); 13559f074e33SMatthew G Knepley } 135607b0a1fcSMatthew G Knepley 135780330477SMatthew G. Knepley /*@ 135880330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 135980330477SMatthew G. Knepley 1360d083f849SBarry Smith Collective on dmA 136180330477SMatthew G. Knepley 136280330477SMatthew G. Knepley Input Parameter: 136380330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates 136480330477SMatthew G. Knepley 136580330477SMatthew G. Knepley Output Parameter: 136680330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates 136780330477SMatthew G. Knepley 136880330477SMatthew G. Knepley Level: intermediate 136980330477SMatthew G. Knepley 137080330477SMatthew G. Knepley Note: This is typically used when adding pieces other than vertices to a mesh 137180330477SMatthew G. Knepley 137265f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 137380330477SMatthew G. Knepley @*/ 137407b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 137507b0a1fcSMatthew G Knepley { 137607b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 137743eeeb2dSStefano Zampini VecType vtype; 137807b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 137907b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 13800bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 138190a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 138243eeeb2dSStefano Zampini PetscBool lc = PETSC_FALSE; 138307b0a1fcSMatthew G Knepley 138407b0a1fcSMatthew G Knepley PetscFunctionBegin; 138543eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 138643eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 138776b791aaSMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 13885f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dmA, &cdim)); 13895f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(dmB, cdim)); 13905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA)); 13915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB)); 13922c71b3e2SJacob Faibussowitsch PetscCheckFalse((vEndA-vStartA) != (vEndB-vStartB),PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %d != %d in the second DM", vEndA-vStartA, vEndB-vStartB); 139361a622f3SMatthew G. Knepley /* Copy over discretization if it exists */ 139461a622f3SMatthew G. Knepley { 139561a622f3SMatthew G. Knepley DM cdmA, cdmB; 139661a622f3SMatthew G. Knepley PetscDS dsA, dsB; 139761a622f3SMatthew G. Knepley PetscObject objA, objB; 139861a622f3SMatthew G. Knepley PetscClassId idA, idB; 139961a622f3SMatthew G. Knepley const PetscScalar *constants; 140061a622f3SMatthew G. Knepley PetscInt cdim, Nc; 140161a622f3SMatthew G. Knepley 14025f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmA, &cdmA)); 14035f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmB, &cdmB)); 14045f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetField(cdmA, 0, NULL, &objA)); 14055f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetField(cdmB, 0, NULL, &objB)); 14065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(objA, &idA)); 14075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(objB, &idB)); 140861a622f3SMatthew G. Knepley if ((idA == PETSCFE_CLASSID) && (idA != idB)) { 14095f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(cdmB, 0, NULL, objA)); 14105f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(cdmB)); 14115f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdmA, &dsA)); 14125f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(cdmB, &dsB)); 14135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetCoordinateDimension(dsA, &cdim)); 14145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetCoordinateDimension(dsB, cdim)); 14155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetConstants(dsA, &Nc, &constants)); 14165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetConstants(dsB, Nc, (PetscScalar *) constants)); 141761a622f3SMatthew G. Knepley } 141861a622f3SMatthew G. Knepley } 14195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA)); 14205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB)); 14215f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dmA, &coordSectionA)); 14225f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dmB, &coordSectionB)); 1423972bc18aSToby Isaac if (coordSectionA == coordSectionB) PetscFunctionReturn(0); 14245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(coordSectionA, &Nf)); 14250bedd6beSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 14262c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nf > 1,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf); 1427df26b574SMatthew G. Knepley if (!coordSectionB) { 1428df26b574SMatthew G. Knepley PetscInt dim; 1429df26b574SMatthew G. Knepley 14305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB)); 14315f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dmA, &dim)); 14325f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateSection(dmB, dim, coordSectionB)); 14335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject) coordSectionB)); 1434df26b574SMatthew G. Knepley } 14355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSectionB, 1)); 14365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim)); 14375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim)); 14385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(coordSectionA, &cS, &cE)); 143943eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 14402c71b3e2SJacob Faibussowitsch PetscCheckFalse((cEndA-cStartA) != (cEndB-cStartB),PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %D != %D in the second DM", cEndA-cStartA, cEndB-cStartB); 144143eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 144243eeeb2dSStefano Zampini cE = vEndB; 144343eeeb2dSStefano Zampini lc = PETSC_TRUE; 144443eeeb2dSStefano Zampini } else { 144543eeeb2dSStefano Zampini cS = vStartB; 144643eeeb2dSStefano Zampini cE = vEndB; 144743eeeb2dSStefano Zampini } 14485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSectionB, cS, cE)); 144907b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 14505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSectionB, v, spaceDim)); 14515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim)); 145207b0a1fcSMatthew G Knepley } 145343eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 145443eeeb2dSStefano Zampini PetscInt c; 145543eeeb2dSStefano Zampini 145643eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 145743eeeb2dSStefano Zampini PetscInt dof; 145843eeeb2dSStefano Zampini 14595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(coordSectionA, c + cStartA, &dof)); 14605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSectionB, c + cStartB, dof)); 14615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof)); 146243eeeb2dSStefano Zampini } 146343eeeb2dSStefano Zampini } 14645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSectionB)); 14655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(coordSectionB, &coordSizeB)); 14665f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dmA, &coordinatesA)); 14675f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinatesB)); 14685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinatesB, "coordinates")); 14695f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE)); 14705f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetBlockSize(coordinatesA, &d)); 14715f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinatesB, d)); 14725f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetType(coordinatesA, &vtype)); 14735f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(coordinatesB, vtype)); 14745f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinatesA, &coordsA)); 14755f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinatesB, &coordsB)); 147607b0a1fcSMatthew G Knepley for (v = 0; v < vEndB-vStartB; ++v) { 147743eeeb2dSStefano Zampini PetscInt offA, offB; 147843eeeb2dSStefano Zampini 14795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSectionA, v + vStartA, &offA)); 14805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSectionB, v + vStartB, &offB)); 148107b0a1fcSMatthew G Knepley for (d = 0; d < spaceDim; ++d) { 148243eeeb2dSStefano Zampini coordsB[offB+d] = coordsA[offA+d]; 148343eeeb2dSStefano Zampini } 148443eeeb2dSStefano Zampini } 148543eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 148643eeeb2dSStefano Zampini PetscInt c; 148743eeeb2dSStefano Zampini 148843eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 148943eeeb2dSStefano Zampini PetscInt dof, offA, offB; 149043eeeb2dSStefano Zampini 14915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSectionA, c + cStartA, &offA)); 14925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSectionB, c + cStartB, &offB)); 14935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(coordSectionA, c + cStartA, &dof)); 14945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(coordsB + offB,coordsA + offA,dof)); 149507b0a1fcSMatthew G Knepley } 149607b0a1fcSMatthew G Knepley } 14975f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinatesA, &coordsA)); 14985f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinatesB, &coordsB)); 14995f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dmB, coordinatesB)); 15005f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinatesB)); 150107b0a1fcSMatthew G Knepley PetscFunctionReturn(0); 150207b0a1fcSMatthew G Knepley } 15035c386225SMatthew G. Knepley 15044e3744c5SMatthew G. Knepley /*@ 15054e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 15064e3744c5SMatthew G. Knepley 1507d083f849SBarry Smith Collective on dm 15084e3744c5SMatthew G. Knepley 15094e3744c5SMatthew G. Knepley Input Parameter: 15104e3744c5SMatthew G. Knepley . dm - The complete DMPlex object 15114e3744c5SMatthew G. Knepley 15124e3744c5SMatthew G. Knepley Output Parameter: 15134e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices 15144e3744c5SMatthew G. Knepley 15154e3744c5SMatthew G. Knepley Level: intermediate 15164e3744c5SMatthew G. Knepley 151795452b02SPatrick Sanan Notes: 151895452b02SPatrick Sanan It does not copy over the coordinates. 151943eeeb2dSStefano Zampini 15209ade3219SVaclav Hapla Developer Notes: 15219ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 15229ade3219SVaclav Hapla 1523a4a685f2SJacob Faibussowitsch .seealso: DMPlexInterpolate(), DMPlexCreateFromCellListPetsc(), DMPlexCopyCoordinates() 15244e3744c5SMatthew G. Knepley @*/ 15254e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 15264e3744c5SMatthew G. Knepley { 1527827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 15284e3744c5SMatthew G. Knepley DM udm; 1529412e9a14SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; 15304e3744c5SMatthew G. Knepley 15314e3744c5SMatthew G. Knepley PetscFunctionBegin; 153243eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 153343eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 15345f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 15355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated(dm, &interpolated)); 15362c71b3e2SJacob Faibussowitsch PetscCheckFalse(interpolated == DMPLEX_INTERPOLATED_PARTIAL,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1537827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1538827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 15395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dm)); 1540595d4abbSMatthew G. Knepley *dmUnint = dm; 1541595d4abbSMatthew G. Knepley PetscFunctionReturn(0); 15424e3744c5SMatthew G. Knepley } 15435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 15445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 15455f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &udm)); 15465f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(udm, DMPLEX)); 15475f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(udm, dim)); 15485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(udm, cStart, vEnd)); 15494e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1550595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 15514e3744c5SMatthew G. Knepley 15525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 15534e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 15544e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 15554e3744c5SMatthew G. Knepley 15564e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 15574e3744c5SMatthew G. Knepley } 15585f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 15595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(udm, c, coneSize)); 1560595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 15614e3744c5SMatthew G. Knepley } 15625f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(udm)); 15635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxConeSize, &cone)); 15644e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1565595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 15664e3744c5SMatthew G. Knepley 15675f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 15684e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 15694e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 15704e3744c5SMatthew G. Knepley 15714e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 15724e3744c5SMatthew G. Knepley } 15735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 15745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(udm, c, cone)); 15754e3744c5SMatthew G. Knepley } 15765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cone)); 15775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(udm)); 15785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(udm)); 15795c7de58aSMatthew G. Knepley /* Reduce SF */ 15805c7de58aSMatthew G. Knepley { 15815c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 15825c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 15835c7de58aSMatthew G. Knepley const PetscInt *localPoints; 15845c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 15855c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 15865c7de58aSMatthew G. Knepley PetscInt vEnd, numRoots, numLeaves, l; 15875c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 15885c7de58aSMatthew G. Knepley 15895c7de58aSMatthew G. Knepley /* Get original SF information */ 15905f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 15915f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(udm, &sfPointUn)); 15925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, 0, NULL, &vEnd)); 15935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 15945c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 15955c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++; 15965c7de58aSMatthew G. Knepley /* Fill in leaves */ 15975c7de58aSMatthew G. Knepley if (vEnd >= 0) { 15985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numLeavesUn, &remotePointsUn)); 15995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numLeavesUn, &localPointsUn)); 16005c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 16015c7de58aSMatthew G. Knepley if (localPoints[l] < vEnd) { 16025c7de58aSMatthew G. Knepley localPointsUn[n] = localPoints[l]; 16035c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 16045c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 16055c7de58aSMatthew G. Knepley ++n; 16065c7de58aSMatthew G. Knepley } 16075c7de58aSMatthew G. Knepley } 16082c71b3e2SJacob Faibussowitsch PetscCheckFalse(n != numLeavesUn,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn); 16095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER)); 16105c7de58aSMatthew G. Knepley } 16115c7de58aSMatthew G. Knepley } 1612827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1613827c4036SVaclav Hapla { 1614d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) udm->data; 1615827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1616827c4036SVaclav Hapla } 16175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, udm)); 16184e3744c5SMatthew G. Knepley *dmUnint = udm; 16194e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 16204e3744c5SMatthew G. Knepley } 1621a7748839SVaclav Hapla 1622a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1623a7748839SVaclav Hapla { 1624a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1625a7748839SVaclav Hapla MPI_Comm comm; 1626a7748839SVaclav Hapla 1627a7748839SVaclav Hapla PetscFunctionBegin; 16285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 16295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 16305f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 1631a7748839SVaclav Hapla 1632a7748839SVaclav Hapla if (depth == dim) { 1633a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1634a7748839SVaclav Hapla if (!dim) goto finish; 1635a7748839SVaclav Hapla 1636a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 16375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd)); 1638a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 16395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 1640a7748839SVaclav Hapla if (coneSize) { 1641a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1642a7748839SVaclav Hapla goto finish; 1643a7748839SVaclav Hapla } 1644a7748839SVaclav Hapla } 1645a7748839SVaclav Hapla 1646a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1647a7748839SVaclav Hapla for (h=0; h<dim; h++) { 16485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 1649a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 16505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 1651a7748839SVaclav Hapla if (!coneSize) { 1652a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1653a7748839SVaclav Hapla goto finish; 1654a7748839SVaclav Hapla } 1655a7748839SVaclav Hapla } 1656a7748839SVaclav Hapla } 1657a7748839SVaclav Hapla } else if (depth == 1) { 1658a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1659a7748839SVaclav Hapla } else { 1660a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1661a7748839SVaclav Hapla } 1662a7748839SVaclav Hapla finish: 1663a7748839SVaclav Hapla PetscFunctionReturn(0); 1664a7748839SVaclav Hapla } 1665a7748839SVaclav Hapla 1666a7748839SVaclav Hapla /*@ 16679ade3219SVaclav Hapla DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated. 1668a7748839SVaclav Hapla 1669a7748839SVaclav Hapla Not Collective 1670a7748839SVaclav Hapla 1671a7748839SVaclav Hapla Input Parameter: 1672a7748839SVaclav Hapla . dm - The DM object 1673a7748839SVaclav Hapla 1674a7748839SVaclav Hapla Output Parameter: 1675a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1676a7748839SVaclav Hapla 1677a7748839SVaclav Hapla Level: intermediate 1678a7748839SVaclav Hapla 1679a7748839SVaclav Hapla Notes: 16809ade3219SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this is NOT collective 16819ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1682a7748839SVaclav Hapla However, DMPlexInterpolate() guarantees the result is the same on all. 16839ade3219SVaclav Hapla 1684a7748839SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED. 1685a7748839SVaclav Hapla 16869ade3219SVaclav Hapla Developer Notes: 16879ade3219SVaclav Hapla Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID. 16889ade3219SVaclav Hapla 16899ade3219SVaclav Hapla If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called. 16909ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 16919ade3219SVaclav Hapla DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL. 16929ade3219SVaclav Hapla 16939ade3219SVaclav Hapla If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated. 16949ade3219SVaclav Hapla 16959ade3219SVaclav Hapla DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL, 16969ade3219SVaclav Hapla and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 16979ade3219SVaclav Hapla 1698a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective() 1699a7748839SVaclav Hapla @*/ 1700a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1701a7748839SVaclav Hapla { 1702a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1703a7748839SVaclav Hapla 1704a7748839SVaclav Hapla PetscFunctionBegin; 1705a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1706a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1707a7748839SVaclav Hapla if (plex->interpolated < 0) { 17085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated_Internal(dm, &plex->interpolated)); 170976bd3646SJed Brown } else if (PetscDefined (USE_DEBUG)) { 1710a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1711a7748839SVaclav Hapla 17125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated_Internal(dm, &flg)); 17132c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg != plex->interpolated,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]); 1714a7748839SVaclav Hapla } 1715a7748839SVaclav Hapla *interpolated = plex->interpolated; 1716a7748839SVaclav Hapla PetscFunctionReturn(0); 1717a7748839SVaclav Hapla } 1718a7748839SVaclav Hapla 1719a7748839SVaclav Hapla /*@ 17209ade3219SVaclav Hapla DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner). 1721a7748839SVaclav Hapla 17222666ff3cSVaclav Hapla Collective 1723a7748839SVaclav Hapla 1724a7748839SVaclav Hapla Input Parameter: 1725a7748839SVaclav Hapla . dm - The DM object 1726a7748839SVaclav Hapla 1727a7748839SVaclav Hapla Output Parameter: 1728a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1729a7748839SVaclav Hapla 1730a7748839SVaclav Hapla Level: intermediate 1731a7748839SVaclav Hapla 1732a7748839SVaclav Hapla Notes: 17339ade3219SVaclav Hapla Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks. 17349ade3219SVaclav Hapla 17359ade3219SVaclav Hapla This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks. 17369ade3219SVaclav Hapla 17379ade3219SVaclav Hapla Developer Notes: 17389ade3219SVaclav Hapla Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID. 17399ade3219SVaclav Hapla 17409ade3219SVaclav Hapla If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated. 17419ade3219SVaclav Hapla MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 17429ade3219SVaclav Hapla if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED, 17439ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 17449ade3219SVaclav Hapla 17459ade3219SVaclav Hapla If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective. 1746a7748839SVaclav Hapla 1747a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated() 1748a7748839SVaclav Hapla @*/ 1749a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 1750a7748839SVaclav Hapla { 1751a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1752a7748839SVaclav Hapla PetscBool debug=PETSC_FALSE; 1753a7748839SVaclav Hapla 1754a7748839SVaclav Hapla PetscFunctionBegin; 1755a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1756a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 17575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL)); 1758a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1759a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1760a7748839SVaclav Hapla MPI_Comm comm; 1761a7748839SVaclav Hapla 17625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 17635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsInterpolated(dm, &plex->interpolatedCollective)); 17645f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm)); 17655f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm)); 1766a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1767a7748839SVaclav Hapla if (debug) { 1768a7748839SVaclav Hapla PetscMPIInt rank; 1769a7748839SVaclav Hapla 17705f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 17715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective])); 17725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 1773a7748839SVaclav Hapla } 1774a7748839SVaclav Hapla } 1775a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 1776a7748839SVaclav Hapla PetscFunctionReturn(0); 1777a7748839SVaclav Hapla } 1778