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 5a7748839SVaclav Hapla const char * const DMPlexInterpolatedFlags[] = {"none", "partial", "mixed", "full", "DMPlexInterpolatedFlag", "DMPLEX_INTERPOLATED_", 0}; 6a7748839SVaclav Hapla 7e8f14785SLisandro Dalcin /* HashIJKL */ 8e8f14785SLisandro Dalcin 9e8f14785SLisandro Dalcin #include <petsc/private/hashmap.h> 10e8f14785SLisandro Dalcin 11e8f14785SLisandro Dalcin typedef struct _PetscHashIJKLKey { PetscInt i, j, k, l; } PetscHashIJKLKey; 12e8f14785SLisandro Dalcin 13e8f14785SLisandro Dalcin #define PetscHashIJKLKeyHash(key) \ 14e8f14785SLisandro Dalcin PetscHashCombine(PetscHashCombine(PetscHashInt((key).i),PetscHashInt((key).j)), \ 15e8f14785SLisandro Dalcin PetscHashCombine(PetscHashInt((key).k),PetscHashInt((key).l))) 16e8f14785SLisandro Dalcin 17e8f14785SLisandro Dalcin #define PetscHashIJKLKeyEqual(k1,k2) \ 18e8f14785SLisandro Dalcin (((k1).i==(k2).i) ? ((k1).j==(k2).j) ? ((k1).k==(k2).k) ? ((k1).l==(k2).l) : 0 : 0 : 0) 19e8f14785SLisandro Dalcin 20e8f14785SLisandro Dalcin PETSC_HASH_MAP(HashIJKL, PetscHashIJKLKey, PetscInt, PetscHashIJKLKeyHash, PetscHashIJKLKeyEqual, -1) 21e8f14785SLisandro Dalcin 223be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1}; 233be36e83SMatthew G. Knepley 243be36e83SMatthew G. Knepley typedef struct _PetscHashIJKLRemoteKey { PetscSFNode i, j, k, l; } PetscHashIJKLRemoteKey; 253be36e83SMatthew G. Knepley 263be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \ 273be36e83SMatthew G. Knepley PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index),PetscHashInt((key).j.rank + (key).j.index)), \ 283be36e83SMatthew G. Knepley PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index),PetscHashInt((key).l.rank + (key).l.index))) 293be36e83SMatthew G. Knepley 303be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyEqual(k1,k2) \ 313be36e83SMatthew G. Knepley (((k1).i.rank==(k2).i.rank) ? ((k1).i.index==(k2).i.index) ? ((k1).j.rank==(k2).j.rank) ? ((k1).j.index==(k2).j.index) ? ((k1).k.rank==(k2).k.rank) ? ((k1).k.index==(k2).k.index) ? ((k1).l.rank==(k2).l.rank) ? ((k1).l.index==(k2).l.index) : 0 : 0 : 0 : 0 : 0 : 0 : 0) 323be36e83SMatthew G. Knepley 333be36e83SMatthew G. Knepley PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode) 343be36e83SMatthew G. Knepley 353be36e83SMatthew G. Knepley static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[]) 363be36e83SMatthew G. Knepley { 373be36e83SMatthew G. Knepley PetscInt i; 383be36e83SMatthew G. Knepley 393be36e83SMatthew G. Knepley PetscFunctionBegin; 403be36e83SMatthew G. Knepley for (i = 1; i < n; ++i) { 413be36e83SMatthew G. Knepley PetscSFNode x = A[i]; 423be36e83SMatthew G. Knepley PetscInt j; 433be36e83SMatthew G. Knepley 443be36e83SMatthew G. Knepley for (j = i-1; j >= 0; --j) { 453be36e83SMatthew G. Knepley if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break; 463be36e83SMatthew G. Knepley A[j+1] = A[j]; 473be36e83SMatthew G. Knepley } 483be36e83SMatthew G. Knepley A[j+1] = x; 493be36e83SMatthew G. Knepley } 503be36e83SMatthew G. Knepley PetscFunctionReturn(0); 513be36e83SMatthew G. Knepley } 529f074e33SMatthew G Knepley 539f074e33SMatthew G Knepley /* 549a5b13a2SMatthew G Knepley DMPlexGetFaces_Internal - Gets groups of vertices that correspond to faces for the given cell 55cd921712SStefano Zampini This assumes that the mesh is not interpolated from the depth of point p to the vertices 569f074e33SMatthew G Knepley */ 57ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetFaces_Internal(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 589f074e33SMatthew G Knepley { 599f074e33SMatthew G Knepley const PetscInt *cone = NULL; 60ba2698f1SMatthew G. Knepley DMPolytopeType ct; 619f074e33SMatthew G Knepley PetscErrorCode ierr; 629f074e33SMatthew G Knepley 639f074e33SMatthew G Knepley PetscFunctionBegin; 649f074e33SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 65ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 669f074e33SMatthew G Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 67ba2698f1SMatthew G. Knepley ierr = DMPlexGetRawFaces_Internal(dm, ct, cone, numFaces, faceSize, faces);CHKERRQ(ierr); 68439ece16SMatthew G. Knepley PetscFunctionReturn(0); 69439ece16SMatthew G. Knepley } 70439ece16SMatthew G. Knepley 71439ece16SMatthew G. Knepley /* 72439ece16SMatthew G. Knepley DMPlexRestoreFaces_Internal - Restores the array 73439ece16SMatthew G. Knepley */ 74ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexRestoreFaces_Internal(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 75439ece16SMatthew G. Knepley { 76439ece16SMatthew G. Knepley PetscErrorCode ierr; 77439ece16SMatthew G. Knepley 78439ece16SMatthew G. Knepley PetscFunctionBegin; 79cd921712SStefano Zampini if (faces) { ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces);CHKERRQ(ierr); } 80439ece16SMatthew G. Knepley PetscFunctionReturn(0); 81439ece16SMatthew G. Knepley } 82439ece16SMatthew G. Knepley 83439ece16SMatthew G. Knepley /* 84439ece16SMatthew G. Knepley DMPlexGetRawFaces_Internal - Gets groups of vertices that correspond to faces for the given cone 85439ece16SMatthew G. Knepley */ 86ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 87439ece16SMatthew G. Knepley { 88439ece16SMatthew G. Knepley PetscInt *facesTmp; 89439ece16SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 90439ece16SMatthew G. Knepley PetscErrorCode ierr; 91439ece16SMatthew G. Knepley 92439ece16SMatthew G. Knepley PetscFunctionBegin; 93439ece16SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94ba2698f1SMatthew G. Knepley if (cone) PetscValidIntPointer(cone, 3); 95439ece16SMatthew G. Knepley ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 9669291d52SBarry Smith if (faces) {ierr = DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp);CHKERRQ(ierr);} 97ba2698f1SMatthew G. Knepley switch (ct) { 98ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 99ba2698f1SMatthew G. Knepley if (numFaces) *numFaces = 0; 100ba2698f1SMatthew G. Knepley if (faceSize) *faceSize = 0; 101ba2698f1SMatthew G. Knepley break; 102ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 103c49d9212SMatthew G. Knepley if (faces) { 104c49d9212SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 105c49d9212SMatthew G. Knepley *faces = facesTmp; 106c49d9212SMatthew G. Knepley } 107c49d9212SMatthew G. Knepley if (numFaces) *numFaces = 2; 108c49d9212SMatthew G. Knepley if (faceSize) *faceSize = 1; 109c49d9212SMatthew G. Knepley break; 110ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 1119a5b13a2SMatthew G Knepley if (faces) { 1129a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1139a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1149a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[0]; 1159a5b13a2SMatthew G Knepley *faces = facesTmp; 1169a5b13a2SMatthew G Knepley } 1179a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 3; 1189a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 2; 1199f074e33SMatthew G Knepley break; 120ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 1219a5b13a2SMatthew G Knepley /* Vertices follow right hand rule */ 1229a5b13a2SMatthew G Knepley if (faces) { 1239a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1249a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1259a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[3]; 1269a5b13a2SMatthew G Knepley facesTmp[6] = cone[3]; facesTmp[7] = cone[0]; 1279a5b13a2SMatthew G Knepley *faces = facesTmp; 1289a5b13a2SMatthew G Knepley } 1299a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 1309a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 2; 1319f074e33SMatthew G Knepley break; 132ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 1332e1b13c2SMatthew G. Knepley /* Vertices of first face follow right hand rule and normal points away from last vertex */ 1349a5b13a2SMatthew G Knepley if (faces) { 1352e1b13c2SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; 1362e1b13c2SMatthew G. Knepley facesTmp[3] = cone[0]; facesTmp[4] = cone[3]; facesTmp[5] = cone[1]; 1372e1b13c2SMatthew G. Knepley facesTmp[6] = cone[0]; facesTmp[7] = cone[2]; facesTmp[8] = cone[3]; 1382e1b13c2SMatthew G. Knepley facesTmp[9] = cone[2]; facesTmp[10] = cone[1]; facesTmp[11] = cone[3]; 1399a5b13a2SMatthew G Knepley *faces = facesTmp; 1409a5b13a2SMatthew G Knepley } 1419a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 1429a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 3; 1439a5b13a2SMatthew G Knepley break; 144ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 145e368ef20SMatthew G. Knepley /* 7--------6 146e368ef20SMatthew G. Knepley /| /| 147e368ef20SMatthew G. Knepley / | / | 148e368ef20SMatthew G. Knepley 4--------5 | 149e368ef20SMatthew G. Knepley | | | | 150e368ef20SMatthew G. Knepley | | | | 151e368ef20SMatthew G. Knepley | 1--------2 152e368ef20SMatthew G. Knepley | / | / 153e368ef20SMatthew G. Knepley |/ |/ 154e368ef20SMatthew G. Knepley 0--------3 155e368ef20SMatthew G. Knepley */ 1569a5b13a2SMatthew G Knepley if (faces) { 15751cfd6a4SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 15851cfd6a4SMatthew G. Knepley facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; facesTmp[6] = cone[6]; facesTmp[7] = cone[7]; /* Top */ 15951cfd6a4SMatthew G. Knepley facesTmp[8] = cone[0]; facesTmp[9] = cone[3]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; /* Front */ 16051cfd6a4SMatthew G. Knepley facesTmp[12] = cone[2]; facesTmp[13] = cone[1]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; /* Back */ 16151cfd6a4SMatthew G. Knepley facesTmp[16] = cone[3]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; /* Right */ 16251cfd6a4SMatthew G. Knepley facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[1]; /* Left */ 1639a5b13a2SMatthew G Knepley *faces = facesTmp; 1649a5b13a2SMatthew G Knepley } 1659a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 6; 1669a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 4; 1679f074e33SMatthew G Knepley break; 168ba2698f1SMatthew G. Knepley default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]); 1699f074e33SMatthew G Knepley } 1709f074e33SMatthew G Knepley PetscFunctionReturn(0); 1719f074e33SMatthew G Knepley } 1729f074e33SMatthew G Knepley 17399836e0eSStefano Zampini /* 17499836e0eSStefano Zampini DMPlexGetRawFacesHybrid_Internal - Gets groups of vertices that correspond to faces for the given cone using hybrid ordering (prisms) 17599836e0eSStefano Zampini */ 176ba2698f1SMatthew G. Knepley static PetscErrorCode DMPlexGetRawFacesHybrid_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[]) 17799836e0eSStefano Zampini { 17899836e0eSStefano Zampini PetscInt *facesTmp; 17999836e0eSStefano Zampini PetscInt maxConeSize, maxSupportSize; 18099836e0eSStefano Zampini PetscErrorCode ierr; 18199836e0eSStefano Zampini 18299836e0eSStefano Zampini PetscFunctionBegin; 18399836e0eSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 184ba2698f1SMatthew G. Knepley if (cone) PetscValidIntPointer(cone, 3); 18599836e0eSStefano Zampini ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 18699836e0eSStefano Zampini if (faces) {ierr = DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp);CHKERRQ(ierr);} 187ba2698f1SMatthew G. Knepley switch (ct) { 188ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 18999836e0eSStefano Zampini if (faces) { 19099836e0eSStefano Zampini facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 19199836e0eSStefano Zampini *faces = facesTmp; 19299836e0eSStefano Zampini } 19399836e0eSStefano Zampini if (numFaces) *numFaces = 2; 19499836e0eSStefano Zampini if (numFacesNotH) *numFacesNotH = 2; 19599836e0eSStefano Zampini if (faceSize) *faceSize = 1; 19699836e0eSStefano Zampini break; 197ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 198ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 19999836e0eSStefano Zampini if (faces) { 20099836e0eSStefano Zampini facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 20199836e0eSStefano Zampini facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; 20299836e0eSStefano Zampini facesTmp[4] = cone[0]; facesTmp[5] = cone[2]; 20399836e0eSStefano Zampini facesTmp[6] = cone[1]; facesTmp[7] = cone[3]; 20499836e0eSStefano Zampini *faces = facesTmp; 20599836e0eSStefano Zampini } 20699836e0eSStefano Zampini if (numFaces) *numFaces = 4; 20799836e0eSStefano Zampini if (numFacesNotH) *numFacesNotH = 2; 20899836e0eSStefano Zampini if (faceSize) *faceSize = 2; 20999836e0eSStefano Zampini break; 210ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 211ba2698f1SMatthew G. Knepley if (faces) { 212ba2698f1SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[2]; facesTmp[2] = cone[1]; facesTmp[3] = -1; /* Bottom */ 213ba2698f1SMatthew G. Knepley facesTmp[4] = cone[3]; facesTmp[5] = cone[4]; facesTmp[6] = cone[5]; facesTmp[7] = -1; /* Top */ 214ba2698f1SMatthew G. Knepley facesTmp[8] = cone[0]; facesTmp[9] = cone[1]; facesTmp[10] = cone[4]; facesTmp[11] = cone[3]; /* Back left */ 215ba2698f1SMatthew G. Knepley facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[5]; facesTmp[15] = cone[4]; /* Back right */ 216ba2698f1SMatthew G. Knepley facesTmp[16] = cone[2]; facesTmp[17] = cone[0]; facesTmp[18] = cone[3]; facesTmp[19] = cone[5]; /* Front */ 217ba2698f1SMatthew G. Knepley *faces = facesTmp; 21899836e0eSStefano Zampini } 219ba2698f1SMatthew G. Knepley if (numFaces) *numFaces = 5; 220ba2698f1SMatthew G. Knepley if (numFacesNotH) *numFacesNotH = 2; 221ba2698f1SMatthew G. Knepley if (faceSize) *faceSize = -4; 22299836e0eSStefano Zampini break; 223ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 22499836e0eSStefano Zampini if (faces) { 22599836e0eSStefano Zampini facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = -1; /* Bottom */ 22699836e0eSStefano Zampini facesTmp[4] = cone[3]; facesTmp[5] = cone[4]; facesTmp[6] = cone[5]; facesTmp[7] = -1; /* Top */ 22799836e0eSStefano Zampini facesTmp[8] = cone[0]; facesTmp[9] = cone[1]; facesTmp[10] = cone[3]; facesTmp[11] = cone[4]; /* Back left */ 22899836e0eSStefano Zampini facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[4]; facesTmp[15] = cone[5]; /* Back right */ 22999836e0eSStefano Zampini facesTmp[16] = cone[2]; facesTmp[17] = cone[0]; facesTmp[18] = cone[5]; facesTmp[19] = cone[3]; /* Front */ 23099836e0eSStefano Zampini *faces = facesTmp; 23199836e0eSStefano Zampini } 23299836e0eSStefano Zampini if (numFaces) *numFaces = 5; 23399836e0eSStefano Zampini if (numFacesNotH) *numFacesNotH = 2; 23499836e0eSStefano Zampini if (faceSize) *faceSize = -4; 23599836e0eSStefano Zampini break; 236ba2698f1SMatthew G. Knepley default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No face description for cell type %s", DMPolytopeTypes[ct]); 23799836e0eSStefano Zampini } 23899836e0eSStefano Zampini PetscFunctionReturn(0); 23999836e0eSStefano Zampini } 24099836e0eSStefano Zampini 241ba2698f1SMatthew G. Knepley static PetscErrorCode DMPlexRestoreRawFacesHybrid_Internal(DM dm, DMPolytopeType ct, const PetscInt cone[], PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[]) 24299836e0eSStefano Zampini { 24399836e0eSStefano Zampini PetscErrorCode ierr; 24499836e0eSStefano Zampini 24599836e0eSStefano Zampini PetscFunctionBegin; 24699836e0eSStefano Zampini if (faces) { ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces);CHKERRQ(ierr); } 24799836e0eSStefano Zampini PetscFunctionReturn(0); 24899836e0eSStefano Zampini } 24999836e0eSStefano Zampini 250ba2698f1SMatthew G. Knepley static PetscErrorCode DMPlexGetFacesHybrid_Internal(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[]) 25199836e0eSStefano Zampini { 25299836e0eSStefano Zampini const PetscInt *cone = NULL; 253ba2698f1SMatthew G. Knepley DMPolytopeType ct; 25499836e0eSStefano Zampini PetscErrorCode ierr; 25599836e0eSStefano Zampini 25699836e0eSStefano Zampini PetscFunctionBegin; 25799836e0eSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 258ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 25999836e0eSStefano Zampini ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 260ba2698f1SMatthew G. Knepley ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, numFaces, numFacesNotH, faceSize, faces);CHKERRQ(ierr); 26199836e0eSStefano Zampini PetscFunctionReturn(0); 26299836e0eSStefano Zampini } 26399836e0eSStefano Zampini 2649a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */ 2659a5b13a2SMatthew G Knepley static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm) 2669f074e33SMatthew G Knepley { 267d4efc6f1SMatthew G. Knepley DMLabel subpointMap; 2689a5b13a2SMatthew G Knepley PetscHashIJKL faceTable; 2699a5b13a2SMatthew G Knepley PetscInt *pStart, *pEnd; 2709a5b13a2SMatthew G Knepley PetscInt cellDim, depth, faceDepth = cellDepth, numPoints = 0, faceSizeAll = 0, face, c, d; 271e9fa77a1SMatthew G. Knepley PetscInt coneSizeH = 0, faceSizeAllH = 0, faceSizeAllT = 0, numCellFacesH = 0, faceT = 0, faceH, pMax = -1, dim, outerloop; 27299836e0eSStefano Zampini PetscInt cMax, fMax, eMax, vMax; 2739f074e33SMatthew G Knepley PetscErrorCode ierr; 2749f074e33SMatthew G Knepley 2759f074e33SMatthew G Knepley PetscFunctionBegin; 276c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &cellDim);CHKERRQ(ierr); 277d4efc6f1SMatthew G. Knepley /* HACK: I need a better way to determine face dimension, or an alternative to GetFaces() */ 278d4efc6f1SMatthew G. Knepley ierr = DMPlexGetSubpointMap(dm, &subpointMap);CHKERRQ(ierr); 279d4efc6f1SMatthew G. Knepley if (subpointMap) ++cellDim; 2809a5b13a2SMatthew G Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2819a5b13a2SMatthew G Knepley ++depth; 2829a5b13a2SMatthew G Knepley ++cellDepth; 2839a5b13a2SMatthew G Knepley cellDim -= depth - cellDepth; 284dcca6d9dSJed Brown ierr = PetscMalloc2(depth+1,&pStart,depth+1,&pEnd);CHKERRQ(ierr); 2859a5b13a2SMatthew G Knepley for (d = depth-1; d >= faceDepth; --d) { 2869a5b13a2SMatthew G Knepley ierr = DMPlexGetDepthStratum(dm, d, &pStart[d+1], &pEnd[d+1]);CHKERRQ(ierr); 2879f074e33SMatthew G Knepley } 2889a5b13a2SMatthew G Knepley ierr = DMPlexGetDepthStratum(dm, -1, NULL, &pStart[faceDepth]);CHKERRQ(ierr); 2899a5b13a2SMatthew G Knepley pEnd[faceDepth] = pStart[faceDepth]; 2909a5b13a2SMatthew G Knepley for (d = faceDepth-1; d >= 0; --d) { 2919a5b13a2SMatthew G Knepley ierr = DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d]);CHKERRQ(ierr); 2929f074e33SMatthew G Knepley } 29399836e0eSStefano Zampini cMax = fMax = eMax = vMax = PETSC_DETERMINE; 29499836e0eSStefano Zampini ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 29599836e0eSStefano Zampini if (cellDim == dim) { 29699836e0eSStefano Zampini ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 29799836e0eSStefano Zampini pMax = cMax; 29899836e0eSStefano Zampini } else if (cellDim == dim -1) { 29999836e0eSStefano Zampini ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);CHKERRQ(ierr); 30099836e0eSStefano Zampini pMax = fMax; 30199836e0eSStefano Zampini } 30299836e0eSStefano Zampini pMax = pMax < 0 ? pEnd[cellDepth] : pMax; 30399836e0eSStefano Zampini if (pMax < pEnd[cellDepth]) { 30499836e0eSStefano Zampini const PetscInt *cellFaces, *cone; 305ba2698f1SMatthew G. Knepley DMPolytopeType ct; 30699836e0eSStefano Zampini PetscInt numCellFacesT, faceSize, cf; 3079f074e33SMatthew G Knepley 308e9fa77a1SMatthew G. Knepley /* First get normal cell face size (we now allow hybrid cells to meet normal cells on either hybrid or normal faces */ 309ba2698f1SMatthew G. Knepley if (pStart[cellDepth] < pMax) {ierr = DMPlexGetFaces_Internal(dm, pStart[cellDepth], NULL, &faceSizeAll, NULL);CHKERRQ(ierr);} 310e9fa77a1SMatthew G. Knepley 311ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, pMax, &ct);CHKERRQ(ierr); 31299836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, pMax, &coneSizeH);CHKERRQ(ierr); 31399836e0eSStefano Zampini ierr = DMPlexGetCone(dm, pMax, &cone);CHKERRQ(ierr); 314ba2698f1SMatthew G. Knepley ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFacesH, &numCellFacesT, &faceSize, &cellFaces);CHKERRQ(ierr); 31599836e0eSStefano Zampini if (faceSize < 0) { 31699836e0eSStefano Zampini PetscInt *sizes, minv, maxv; 31799836e0eSStefano Zampini 31899836e0eSStefano Zampini /* count vertices of hybrid and non-hybrid faces */ 31999836e0eSStefano Zampini ierr = PetscCalloc1(numCellFacesH, &sizes);CHKERRQ(ierr); 32099836e0eSStefano Zampini for (cf = 0; cf < numCellFacesT; ++cf) { /* These are the non-hybrid faces */ 32199836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[-cf*faceSize]; 32299836e0eSStefano Zampini PetscInt f; 32399836e0eSStefano Zampini 32499836e0eSStefano Zampini for (f = 0; f < -faceSize; ++f) sizes[cf] += (cellFace[f] >= 0 ? 1 : 0); 32599836e0eSStefano Zampini } 32699836e0eSStefano Zampini ierr = PetscSortInt(numCellFacesT, sizes);CHKERRQ(ierr); 32799836e0eSStefano Zampini minv = sizes[0]; 32899836e0eSStefano Zampini maxv = sizes[PetscMax(numCellFacesT-1, 0)]; 32999836e0eSStefano Zampini if (minv != maxv) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Different number of vertices for non-hybrid face %D != %D", minv, maxv); 330e9fa77a1SMatthew G. Knepley faceSizeAllT = minv; 331580bdb30SBarry Smith ierr = PetscArrayzero(sizes, numCellFacesH);CHKERRQ(ierr); 33299836e0eSStefano Zampini for (cf = numCellFacesT; cf < numCellFacesH; ++cf) { /* These are the hybrid faces */ 33399836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[-cf*faceSize]; 33499836e0eSStefano Zampini PetscInt f; 33599836e0eSStefano Zampini 33699836e0eSStefano Zampini for (f = 0; f < -faceSize; ++f) sizes[cf-numCellFacesT] += (cellFace[f] >= 0 ? 1 : 0); 33799836e0eSStefano Zampini } 33899836e0eSStefano Zampini ierr = PetscSortInt(numCellFacesH - numCellFacesT, sizes);CHKERRQ(ierr); 33999836e0eSStefano Zampini minv = sizes[0]; 34099836e0eSStefano Zampini maxv = sizes[PetscMax(numCellFacesH - numCellFacesT-1, 0)]; 34199836e0eSStefano Zampini ierr = PetscFree(sizes);CHKERRQ(ierr); 34299836e0eSStefano Zampini if (minv != maxv) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Different number of vertices for hybrid face %D != %D", minv, maxv); 34399836e0eSStefano Zampini faceSizeAllH = minv; 3445ebdaad1SMatthew G. Knepley if (!faceSizeAll) faceSizeAll = faceSizeAllT; 34599836e0eSStefano Zampini } else { /* the size of the faces in hybrid cells is the same */ 346e9fa77a1SMatthew G. Knepley faceSizeAll = faceSizeAllH = faceSizeAllT = faceSize; 34799836e0eSStefano Zampini } 348ba2698f1SMatthew G. Knepley ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, ct, cone, &numCellFacesH, &numCellFacesT, &faceSize, &cellFaces);CHKERRQ(ierr); 34999836e0eSStefano Zampini } else if (pEnd[cellDepth] > pStart[cellDepth]) { 350ba2698f1SMatthew G. Knepley ierr = DMPlexGetFaces_Internal(dm, pStart[cellDepth], NULL, &faceSizeAll, NULL);CHKERRQ(ierr); 351a1bcd873SMatthew G. Knepley faceSizeAllH = faceSizeAllT = faceSizeAll; 35299836e0eSStefano Zampini } 35399836e0eSStefano Zampini if (faceSizeAll > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSizeAll); 35499836e0eSStefano Zampini 355b135d7daSStefano Zampini /* With hybrid grids, we first iterate on hybrid cells and start numbering the non-hybrid faces 35699836e0eSStefano Zampini Then, faces for non-hybrid cells are numbered. 35799836e0eSStefano Zampini This is to guarantee consistent orientations (all 0) of all the points in the cone of the hybrid cells */ 35899836e0eSStefano Zampini ierr = PetscHashIJKLCreate(&faceTable);CHKERRQ(ierr); 35999836e0eSStefano Zampini for (outerloop = 0, face = pStart[faceDepth]; outerloop < 2; outerloop++) { 36099836e0eSStefano Zampini PetscInt start, end; 36199836e0eSStefano Zampini 36299836e0eSStefano Zampini start = outerloop == 0 ? pMax : pStart[cellDepth]; 36399836e0eSStefano Zampini end = outerloop == 0 ? pEnd[cellDepth] : pMax; 36499836e0eSStefano Zampini for (c = start; c < end; ++c) { 36599836e0eSStefano Zampini const PetscInt *cellFaces; 366e9fa77a1SMatthew G. Knepley PetscInt numCellFaces, faceSize, faceSizeInc, faceSizeCheck, cf; 36799836e0eSStefano Zampini 36899836e0eSStefano Zampini if (c < pMax) { 369ba2698f1SMatthew G. Knepley ierr = DMPlexGetFaces_Internal(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 3709a5b13a2SMatthew G Knepley if (faceSize != faceSizeAll) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent face for cell %D of size %D != %D", c, faceSize, faceSizeAll); 371e9fa77a1SMatthew G. Knepley faceSizeCheck = faceSizeAll; 37299836e0eSStefano Zampini } else { /* Hybrid cell */ 37399836e0eSStefano Zampini const PetscInt *cone; 374ba2698f1SMatthew G. Knepley DMPolytopeType ct; 37599836e0eSStefano Zampini PetscInt numCellFacesN, coneSize; 37699836e0eSStefano Zampini 377ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 37899836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 37999836e0eSStefano Zampini if (coneSize != coneSizeH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid coneSize %D != %D", coneSize, coneSizeH); 38099836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 381ba2698f1SMatthew G. Knepley ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 38299836e0eSStefano Zampini if (numCellFaces != numCellFacesH) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected numCellFaces %D != %D for hybrid cell %D", numCellFaces, numCellFacesH, c); 38399836e0eSStefano Zampini faceSize = PetscMax(faceSize, -faceSize); 38499836e0eSStefano Zampini if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSize); 38599836e0eSStefano Zampini numCellFaces = numCellFacesN; /* process only non-hybrid faces */ 386e9fa77a1SMatthew G. Knepley faceSizeCheck = faceSizeAllT; 38799836e0eSStefano Zampini } 38899836e0eSStefano Zampini faceSizeInc = faceSize; 3899f074e33SMatthew G Knepley for (cf = 0; cf < numCellFaces; ++cf) { 39099836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[cf*faceSizeInc]; 39199836e0eSStefano Zampini PetscInt faceSizeH = faceSize; 3929a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 393e8f14785SLisandro Dalcin PetscHashIter iter; 394e8f14785SLisandro Dalcin PetscBool missing; 3959f074e33SMatthew G Knepley 39699836e0eSStefano Zampini if (faceSizeInc == 2) { 3979a5b13a2SMatthew G Knepley key.i = PetscMin(cellFace[0], cellFace[1]); 3989a5b13a2SMatthew G Knepley key.j = PetscMax(cellFace[0], cellFace[1]); 39999836e0eSStefano Zampini key.k = PETSC_MAX_INT; 40099836e0eSStefano Zampini key.l = PETSC_MAX_INT; 4019a5b13a2SMatthew G Knepley } else { 40299836e0eSStefano Zampini key.i = cellFace[0]; 40399836e0eSStefano Zampini key.j = cellFace[1]; 40499836e0eSStefano Zampini key.k = cellFace[2]; 40599836e0eSStefano Zampini key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT; 406302440fdSBarry Smith ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 4079f074e33SMatthew G Knepley } 40899836e0eSStefano Zampini /* this check is redundant for non-hybrid meshes */ 409e9fa77a1SMatthew G. Knepley if (faceSizeH != faceSizeCheck) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected number of vertices for face %D of point %D -> %D != %D", cf, c, faceSizeH, faceSizeCheck); 410e8f14785SLisandro Dalcin ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 411e9fa77a1SMatthew G. Knepley if (missing) { 412e9fa77a1SMatthew G. Knepley ierr = PetscHashIJKLIterSet(faceTable, iter, face++);CHKERRQ(ierr); 413e9fa77a1SMatthew G. Knepley if (c >= pMax) ++faceT; 414e9fa77a1SMatthew G. Knepley } 4159a5b13a2SMatthew G Knepley } 41699836e0eSStefano Zampini if (c < pMax) { 417ba2698f1SMatthew G. Knepley ierr = DMPlexRestoreFaces_Internal(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 41899836e0eSStefano Zampini } else { 419ba2698f1SMatthew G. Knepley ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, DM_POLYTOPE_UNKNOWN, NULL, NULL, NULL, NULL, &cellFaces);CHKERRQ(ierr); 42099836e0eSStefano Zampini } 42199836e0eSStefano Zampini } 42299836e0eSStefano Zampini } 42399836e0eSStefano Zampini pEnd[faceDepth] = face; 42499836e0eSStefano Zampini 42599836e0eSStefano Zampini /* Second pass for hybrid meshes: number hybrid faces */ 42699836e0eSStefano Zampini for (c = pMax; c < pEnd[cellDepth]; ++c) { 42799836e0eSStefano Zampini const PetscInt *cellFaces, *cone; 428ba2698f1SMatthew G. Knepley DMPolytopeType ct; 429ba2698f1SMatthew G. Knepley PetscInt numCellFaces, numCellFacesN, faceSize, cf; 43099836e0eSStefano Zampini 431ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 43299836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 433ba2698f1SMatthew G. Knepley ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 43499836e0eSStefano Zampini if (numCellFaces != numCellFacesH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid numCellFaces %D != %D", numCellFaces, numCellFacesH); 43599836e0eSStefano Zampini faceSize = PetscMax(faceSize, -faceSize); 43699836e0eSStefano Zampini for (cf = numCellFacesN; cf < numCellFaces; ++cf) { /* These are the hybrid faces */ 43799836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[cf*faceSize]; 43899836e0eSStefano Zampini PetscHashIJKLKey key; 43999836e0eSStefano Zampini PetscHashIter iter; 44099836e0eSStefano Zampini PetscBool missing; 44199836e0eSStefano Zampini PetscInt faceSizeH = faceSize; 44299836e0eSStefano Zampini 44399836e0eSStefano Zampini if (faceSize == 2) { 44499836e0eSStefano Zampini key.i = PetscMin(cellFace[0], cellFace[1]); 44599836e0eSStefano Zampini key.j = PetscMax(cellFace[0], cellFace[1]); 44699836e0eSStefano Zampini key.k = PETSC_MAX_INT; 44799836e0eSStefano Zampini key.l = PETSC_MAX_INT; 44899836e0eSStefano Zampini } else { 44999836e0eSStefano Zampini key.i = cellFace[0]; 45099836e0eSStefano Zampini key.j = cellFace[1]; 45199836e0eSStefano Zampini key.k = cellFace[2]; 45299836e0eSStefano Zampini key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT; 45399836e0eSStefano Zampini ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 45499836e0eSStefano Zampini } 45599836e0eSStefano Zampini if (faceSizeH != faceSizeAllH) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected number of vertices for hybrid face %D of point %D -> %D != %D", cf, c, faceSizeH, faceSizeAllH); 45699836e0eSStefano Zampini ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 45799836e0eSStefano Zampini if (missing) {ierr = PetscHashIJKLIterSet(faceTable, iter, face++);CHKERRQ(ierr);} 45899836e0eSStefano Zampini } 459ba2698f1SMatthew G. Knepley ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 46099836e0eSStefano Zampini } 46199836e0eSStefano Zampini faceH = face - pEnd[faceDepth]; 46299836e0eSStefano Zampini if (faceH) { 46399836e0eSStefano Zampini if (fMax == PETSC_DETERMINE) fMax = pEnd[faceDepth]; 46499836e0eSStefano Zampini else if (eMax == PETSC_DETERMINE) eMax = pEnd[faceDepth]; 46599836e0eSStefano Zampini else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of unassigned hybrid facets %D for cellDim %D and dimension %D", faceH, cellDim, dim); 4669a5b13a2SMatthew G Knepley } 4679a5b13a2SMatthew G Knepley pEnd[faceDepth] = face; 4689a5b13a2SMatthew G Knepley ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr); 4699a5b13a2SMatthew G Knepley /* Count new points */ 4709a5b13a2SMatthew G Knepley for (d = 0; d <= depth; ++d) { 4719a5b13a2SMatthew G Knepley numPoints += pEnd[d]-pStart[d]; 4729a5b13a2SMatthew G Knepley } 4739a5b13a2SMatthew G Knepley ierr = DMPlexSetChart(idm, 0, numPoints);CHKERRQ(ierr); 4749a5b13a2SMatthew G Knepley /* Set cone sizes */ 4759a5b13a2SMatthew G Knepley for (d = 0; d <= depth; ++d) { 4769a5b13a2SMatthew G Knepley PetscInt coneSize, p; 4779f074e33SMatthew G Knepley 4789a5b13a2SMatthew G Knepley if (d == faceDepth) { 479e9fa77a1SMatthew G. Knepley /* Now we have two cases: */ 480e9fa77a1SMatthew G. Knepley if (faceSizeAll == faceSizeAllT) { 4819a5b13a2SMatthew G Knepley /* I see no way to do this if we admit faces of different shapes */ 48299836e0eSStefano Zampini for (p = pStart[d]; p < pEnd[d]-faceH; ++p) { 4839a5b13a2SMatthew G Knepley ierr = DMPlexSetConeSize(idm, p, faceSizeAll);CHKERRQ(ierr); 4849a5b13a2SMatthew G Knepley } 48599836e0eSStefano Zampini for (p = pEnd[d]-faceH; p < pEnd[d]; ++p) { 48699836e0eSStefano Zampini ierr = DMPlexSetConeSize(idm, p, faceSizeAllH);CHKERRQ(ierr); 48799836e0eSStefano Zampini } 488e9fa77a1SMatthew G. Knepley } else if (faceSizeAll == faceSizeAllH) { 489e9fa77a1SMatthew G. Knepley for (p = pStart[d]; p < pStart[d]+faceT; ++p) { 490e9fa77a1SMatthew G. Knepley ierr = DMPlexSetConeSize(idm, p, faceSizeAllT);CHKERRQ(ierr); 491e9fa77a1SMatthew G. Knepley } 492e9fa77a1SMatthew G. Knepley for (p = pStart[d]+faceT; p < pEnd[d]-faceH; ++p) { 493e9fa77a1SMatthew G. Knepley ierr = DMPlexSetConeSize(idm, p, faceSizeAll);CHKERRQ(ierr); 494e9fa77a1SMatthew G. Knepley } 495e9fa77a1SMatthew G. Knepley for (p = pEnd[d]-faceH; p < pEnd[d]; ++p) { 496e9fa77a1SMatthew G. Knepley ierr = DMPlexSetConeSize(idm, p, faceSizeAllH);CHKERRQ(ierr); 497e9fa77a1SMatthew G. Knepley } 498e9fa77a1SMatthew G. Knepley } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent faces sizes N: %D T: %D H: %D", faceSizeAll, faceSizeAllT, faceSizeAllH); 499a014044eSMatthew G Knepley } else if (d == cellDepth) { 500a014044eSMatthew G Knepley for (p = pStart[d]; p < pEnd[d]; ++p) { 501a014044eSMatthew G Knepley /* Number of cell faces may be different from number of cell vertices*/ 50299836e0eSStefano Zampini if (p < pMax) { 503ba2698f1SMatthew G. Knepley ierr = DMPlexGetFaces_Internal(dm, p, &coneSize, NULL, NULL);CHKERRQ(ierr); 50499836e0eSStefano Zampini } else { 505ba2698f1SMatthew G. Knepley ierr = DMPlexGetFacesHybrid_Internal(dm, p, &coneSize, NULL, NULL, NULL);CHKERRQ(ierr); 50699836e0eSStefano Zampini } 507a014044eSMatthew G Knepley ierr = DMPlexSetConeSize(idm, p, coneSize);CHKERRQ(ierr); 508a014044eSMatthew G Knepley } 5099a5b13a2SMatthew G Knepley } else { 5109a5b13a2SMatthew G Knepley for (p = pStart[d]; p < pEnd[d]; ++p) { 5119a5b13a2SMatthew G Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5129a5b13a2SMatthew G Knepley ierr = DMPlexSetConeSize(idm, p, coneSize);CHKERRQ(ierr); 5139f074e33SMatthew G Knepley } 5149f074e33SMatthew G Knepley } 5159f074e33SMatthew G Knepley } 5169f074e33SMatthew G Knepley ierr = DMSetUp(idm);CHKERRQ(ierr); 5179f074e33SMatthew G Knepley /* Get face cones from subsets of cell vertices */ 51899836e0eSStefano Zampini if (faceSizeAll > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSizeAll); 5199a5b13a2SMatthew G Knepley ierr = PetscHashIJKLCreate(&faceTable);CHKERRQ(ierr); 5209a5b13a2SMatthew G Knepley for (d = depth; d > cellDepth; --d) { 5219a5b13a2SMatthew G Knepley const PetscInt *cone; 5229a5b13a2SMatthew G Knepley PetscInt p; 5239a5b13a2SMatthew G Knepley 5249a5b13a2SMatthew G Knepley for (p = pStart[d]; p < pEnd[d]; ++p) { 5259a5b13a2SMatthew G Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5269a5b13a2SMatthew G Knepley ierr = DMPlexSetCone(idm, p, cone);CHKERRQ(ierr); 5279a5b13a2SMatthew G Knepley ierr = DMPlexGetConeOrientation(dm, p, &cone);CHKERRQ(ierr); 5289a5b13a2SMatthew G Knepley ierr = DMPlexSetConeOrientation(idm, p, cone);CHKERRQ(ierr); 5299f074e33SMatthew G Knepley } 5309a5b13a2SMatthew G Knepley } 53199836e0eSStefano Zampini for (outerloop = 0, face = pStart[faceDepth]; outerloop < 2; outerloop++) { 53299836e0eSStefano Zampini PetscInt start, end; 5339f074e33SMatthew G Knepley 53499836e0eSStefano Zampini start = outerloop == 0 ? pMax : pStart[cellDepth]; 53599836e0eSStefano Zampini end = outerloop == 0 ? pEnd[cellDepth] : pMax; 53699836e0eSStefano Zampini for (c = start; c < end; ++c) { 53799836e0eSStefano Zampini const PetscInt *cellFaces; 53899836e0eSStefano Zampini PetscInt numCellFaces, faceSize, faceSizeInc, cf; 53999836e0eSStefano Zampini 54099836e0eSStefano Zampini if (c < pMax) { 541ba2698f1SMatthew G. Knepley ierr = DMPlexGetFaces_Internal(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 5429a5b13a2SMatthew G Knepley if (faceSize != faceSizeAll) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent face for cell %D of size %D != %D", c, faceSize, faceSizeAll); 54399836e0eSStefano Zampini } else { 54499836e0eSStefano Zampini const PetscInt *cone; 545ba2698f1SMatthew G. Knepley DMPolytopeType ct; 54699836e0eSStefano Zampini PetscInt numCellFacesN, coneSize; 54799836e0eSStefano Zampini 548ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 54999836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 55099836e0eSStefano Zampini if (coneSize != coneSizeH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid coneSize %D != %D", coneSize, coneSizeH); 55199836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 552ba2698f1SMatthew G. Knepley ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 55399836e0eSStefano Zampini if (numCellFaces != numCellFacesH) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected numCellFaces %D != %D for hybrid cell %D", numCellFaces, numCellFacesH, c); 55499836e0eSStefano Zampini faceSize = PetscMax(faceSize, -faceSize); 55599836e0eSStefano Zampini if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSize); 55699836e0eSStefano Zampini numCellFaces = numCellFacesN; /* process only non-hybrid faces */ 55799836e0eSStefano Zampini } 55899836e0eSStefano Zampini faceSizeInc = faceSize; 5599f074e33SMatthew G Knepley for (cf = 0; cf < numCellFaces; ++cf) { 56099836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[cf*faceSizeInc]; 5619a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 562e8f14785SLisandro Dalcin PetscHashIter iter; 563e8f14785SLisandro Dalcin PetscBool missing; 5649f074e33SMatthew G Knepley 56599836e0eSStefano Zampini if (faceSizeInc == 2) { 5669a5b13a2SMatthew G Knepley key.i = PetscMin(cellFace[0], cellFace[1]); 5679a5b13a2SMatthew G Knepley key.j = PetscMax(cellFace[0], cellFace[1]); 56899836e0eSStefano Zampini key.k = PETSC_MAX_INT; 56999836e0eSStefano Zampini key.l = PETSC_MAX_INT; 5709a5b13a2SMatthew G Knepley } else { 571e8f14785SLisandro Dalcin key.i = cellFace[0]; 572e8f14785SLisandro Dalcin key.j = cellFace[1]; 573e8f14785SLisandro Dalcin key.k = cellFace[2]; 57499836e0eSStefano Zampini key.l = faceSizeInc > 3 ? (cellFace[3] < 0 ? faceSize = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT; 57599836e0eSStefano Zampini ierr = PetscSortInt(faceSizeInc, (PetscInt *) &key);CHKERRQ(ierr); 5769f074e33SMatthew G Knepley } 577e8f14785SLisandro Dalcin ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 578735a0255SMatthew G. Knepley if (missing) { 5799a5b13a2SMatthew G Knepley ierr = DMPlexSetCone(idm, face, cellFace);CHKERRQ(ierr); 580e8f14785SLisandro Dalcin ierr = PetscHashIJKLIterSet(faceTable, iter, face);CHKERRQ(ierr); 581735a0255SMatthew G. Knepley ierr = DMPlexInsertCone(idm, c, cf, face++);CHKERRQ(ierr); 5829a5b13a2SMatthew G Knepley } else { 5839a5b13a2SMatthew G Knepley const PetscInt *cone; 584735a0255SMatthew G. Knepley PetscInt coneSize, ornt, i, j, f; 5859f074e33SMatthew G Knepley 586e8f14785SLisandro Dalcin ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr); 5879a5b13a2SMatthew G Knepley ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 5882e1b13c2SMatthew G. Knepley /* Orient face: Do not allow reverse orientation at the first vertex */ 5899f074e33SMatthew G Knepley ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 5909f074e33SMatthew G Knepley ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 5919a5b13a2SMatthew G Knepley if (coneSize != faceSize) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %D for face %D should be %D", coneSize, f, faceSize); 5929a5b13a2SMatthew G Knepley /* - First find the initial vertex */ 5939a5b13a2SMatthew G Knepley for (i = 0; i < faceSize; ++i) if (cellFace[0] == cone[i]) break; 5949a5b13a2SMatthew G Knepley /* - Try forward comparison */ 5959a5b13a2SMatthew G Knepley for (j = 0; j < faceSize; ++j) if (cellFace[j] != cone[(i+j)%faceSize]) break; 5969a5b13a2SMatthew G Knepley if (j == faceSize) { 5979a5b13a2SMatthew G Knepley if ((faceSize == 2) && (i == 1)) ornt = -2; 5989a5b13a2SMatthew G Knepley else ornt = i; 5999a5b13a2SMatthew G Knepley } else { 6009a5b13a2SMatthew G Knepley /* - Try backward comparison */ 6019a5b13a2SMatthew G Knepley for (j = 0; j < faceSize; ++j) if (cellFace[j] != cone[(i+faceSize-j)%faceSize]) break; 6022e1b13c2SMatthew G. Knepley if (j == faceSize) { 6032e1b13c2SMatthew G. Knepley if (i == 0) ornt = -faceSize; 604dc1a705cSMatthew G. Knepley else ornt = -i; 605e9fa77a1SMatthew G. Knepley } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not determine orientation of face %D in cell %D", f, c); 6069a5b13a2SMatthew G Knepley } 6079a5b13a2SMatthew G Knepley ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr); 6089f074e33SMatthew G Knepley } 6099f074e33SMatthew G Knepley } 61099836e0eSStefano Zampini if (c < pMax) { 611ba2698f1SMatthew G. Knepley ierr = DMPlexRestoreFaces_Internal(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 61299836e0eSStefano Zampini } else { 613ba2698f1SMatthew G. Knepley ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, DM_POLYTOPE_UNKNOWN, NULL, NULL, NULL, NULL, &cellFaces);CHKERRQ(ierr); 6149f074e33SMatthew G Knepley } 61599836e0eSStefano Zampini } 61699836e0eSStefano Zampini } 61799836e0eSStefano Zampini /* Second pass for hybrid meshes: orient hybrid faces */ 61899836e0eSStefano Zampini for (c = pMax; c < pEnd[cellDepth]; ++c) { 61999836e0eSStefano Zampini const PetscInt *cellFaces, *cone; 620ba2698f1SMatthew G. Knepley DMPolytopeType ct; 621ba2698f1SMatthew G. Knepley PetscInt numCellFaces, numCellFacesN, faceSize, coneSize, cf; 62299836e0eSStefano Zampini 623ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 62499836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 62599836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 626ba2698f1SMatthew G. Knepley ierr = DMPlexGetRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 62799836e0eSStefano Zampini if (numCellFaces != numCellFacesH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid numCellFaces %D != %D", numCellFaces, numCellFacesH); 62899836e0eSStefano Zampini faceSize = PetscMax(faceSize, -faceSize); 62999836e0eSStefano Zampini for (cf = numCellFacesN; cf < numCellFaces; ++cf) { /* These are the hybrid faces */ 63099836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[cf*faceSize]; 63199836e0eSStefano Zampini PetscHashIJKLKey key; 63299836e0eSStefano Zampini PetscHashIter iter; 63399836e0eSStefano Zampini PetscBool missing; 63499836e0eSStefano Zampini PetscInt faceSizeH = faceSize; 63599836e0eSStefano Zampini 63699836e0eSStefano Zampini if (faceSize == 2) { 63799836e0eSStefano Zampini key.i = PetscMin(cellFace[0], cellFace[1]); 63899836e0eSStefano Zampini key.j = PetscMax(cellFace[0], cellFace[1]); 63999836e0eSStefano Zampini key.k = PETSC_MAX_INT; 64099836e0eSStefano Zampini key.l = PETSC_MAX_INT; 64199836e0eSStefano Zampini } else { 64299836e0eSStefano Zampini key.i = cellFace[0]; 64399836e0eSStefano Zampini key.j = cellFace[1]; 64499836e0eSStefano Zampini key.k = cellFace[2]; 64599836e0eSStefano Zampini key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT; 64699836e0eSStefano Zampini ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 64799836e0eSStefano Zampini } 64899836e0eSStefano Zampini if (faceSizeH != faceSizeAllH) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected number of vertices for hybrid face %D of point %D -> %D != %D", cf, c, faceSizeH, faceSizeAllH); 64999836e0eSStefano Zampini ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 65099836e0eSStefano Zampini if (missing) { 65199836e0eSStefano Zampini ierr = DMPlexSetCone(idm, face, cellFace);CHKERRQ(ierr); 65299836e0eSStefano Zampini ierr = PetscHashIJKLIterSet(faceTable, iter, face);CHKERRQ(ierr); 65399836e0eSStefano Zampini ierr = DMPlexInsertCone(idm, c, cf, face++);CHKERRQ(ierr); 65499836e0eSStefano Zampini } else { 655e9fa77a1SMatthew G. Knepley PetscInt fv[4] = {0, 1, 2, 3}; 65699836e0eSStefano Zampini const PetscInt *cone; 65799836e0eSStefano Zampini PetscInt coneSize, ornt, i, j, f; 658a74221b0SStefano Zampini PetscBool q2h = PETSC_FALSE; 65999836e0eSStefano Zampini 66099836e0eSStefano Zampini ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr); 66199836e0eSStefano Zampini ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 66299836e0eSStefano Zampini /* Orient face: Do not allow reverse orientation at the first vertex */ 66399836e0eSStefano Zampini ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 66499836e0eSStefano Zampini ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 66599836e0eSStefano Zampini if (coneSize != faceSizeH) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of face vertices %D for face %D should be %D", coneSize, f, faceSizeH); 666e9fa77a1SMatthew G. Knepley /* Hybrid faces are stored as tensor products of edges, so to compare them to normal faces, we have to flip */ 667a74221b0SStefano Zampini if (faceSize == 4 && c >= pMax && faceSizeAll != faceSizeAllT && f < pEnd[faceDepth] - faceH) {q2h = PETSC_TRUE; fv[2] = 3; fv[3] = 2;} 66899836e0eSStefano Zampini /* - First find the initial vertex */ 669e9fa77a1SMatthew G. Knepley for (i = 0; i < faceSizeH; ++i) if (cellFace[fv[0]] == cone[i]) break; 670a74221b0SStefano Zampini if (q2h) { /* Matt's case: hybrid faces meeting with non-hybrid faces. This is a case that is not (and will not be) supported in general by the refinements */ 67199836e0eSStefano Zampini /* - Try forward comparison */ 672e9fa77a1SMatthew G. Knepley for (j = 0; j < faceSizeH; ++j) if (cellFace[fv[j]] != cone[(i+j)%faceSizeH]) break; 67399836e0eSStefano Zampini if (j == faceSizeH) { 67499836e0eSStefano Zampini if ((faceSizeH == 2) && (i == 1)) ornt = -2; 67599836e0eSStefano Zampini else ornt = i; 67699836e0eSStefano Zampini } else { 67799836e0eSStefano Zampini /* - Try backward comparison */ 678e9fa77a1SMatthew G. Knepley for (j = 0; j < faceSizeH; ++j) if (cellFace[fv[j]] != cone[(i+faceSizeH-j)%faceSizeH]) break; 67999836e0eSStefano Zampini if (j == faceSizeH) { 68099836e0eSStefano Zampini if (i == 0) ornt = -faceSizeH; 68199836e0eSStefano Zampini else ornt = -i; 682e9fa77a1SMatthew G. Knepley } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not determine orientation of face %D in cell %D", f, c); 68399836e0eSStefano Zampini } 684a74221b0SStefano Zampini } else { 685a74221b0SStefano Zampini /* when matching hybrid faces in 3D, only few cases are possible. 686a74221b0SStefano Zampini Face traversal however can no longer follow the usual convention, this seems a serious issue to me */ 687a74221b0SStefano Zampini PetscInt tquad_map[4][4] = { {PETSC_MIN_INT, 0,PETSC_MIN_INT,PETSC_MIN_INT}, 688a74221b0SStefano Zampini { -1,PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT}, 689a74221b0SStefano Zampini {PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT, 1}, 690a74221b0SStefano Zampini {PETSC_MIN_INT,PETSC_MIN_INT, -2,PETSC_MIN_INT} }; 691a74221b0SStefano Zampini PetscInt i2; 692a74221b0SStefano Zampini 693a74221b0SStefano Zampini /* find the second vertex */ 694a74221b0SStefano Zampini for (i2 = 0; i2 < faceSizeH; ++i2) if (cellFace[fv[1]] == cone[i2]) break; 695a74221b0SStefano Zampini switch (faceSizeH) { 696a74221b0SStefano Zampini case 2: 697a74221b0SStefano Zampini ornt = i ? -2 : 0; 698a74221b0SStefano Zampini break; 699a74221b0SStefano Zampini case 4: 700a74221b0SStefano Zampini ornt = tquad_map[i][i2]; 701a74221b0SStefano Zampini break; 702a74221b0SStefano Zampini default: 703a74221b0SStefano Zampini SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unhandled face size %D for face %D in cell %D", faceSizeH, f, c); 704a74221b0SStefano Zampini 705a74221b0SStefano Zampini } 706a74221b0SStefano Zampini } 70799836e0eSStefano Zampini ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr); 70899836e0eSStefano Zampini } 70999836e0eSStefano Zampini } 710ba2698f1SMatthew G. Knepley ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, ct, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 71199836e0eSStefano Zampini } 71299836e0eSStefano Zampini if (face != pEnd[faceDepth]) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-pStart[faceDepth], pEnd[faceDepth]-pStart[faceDepth]); 713c907b753SJed Brown ierr = PetscFree2(pStart,pEnd);CHKERRQ(ierr); 7149a5b13a2SMatthew G Knepley ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr); 7156551a8c7SMatthew G. Knepley ierr = PetscFree2(pStart,pEnd);CHKERRQ(ierr); 71699836e0eSStefano Zampini ierr = DMPlexSetHybridBounds(idm, cMax, fMax, eMax, vMax);CHKERRQ(ierr); 7179a5b13a2SMatthew G Knepley ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 7189a5b13a2SMatthew G Knepley ierr = DMPlexStratify(idm);CHKERRQ(ierr); 7199f074e33SMatthew G Knepley PetscFunctionReturn(0); 7209f074e33SMatthew G Knepley } 7219f074e33SMatthew G Knepley 722f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) 723f80536cbSVaclav Hapla { 724f80536cbSVaclav Hapla PetscInt nleaves; 725f80536cbSVaclav Hapla PetscInt nranks; 726a0d42dbcSVaclav Hapla const PetscMPIInt *ranks=NULL; 727a0d42dbcSVaclav Hapla const PetscInt *roffset=NULL, *rmine=NULL, *rremote=NULL; 728f80536cbSVaclav Hapla PetscInt n, o, r; 729f80536cbSVaclav Hapla PetscErrorCode ierr; 730f80536cbSVaclav Hapla 731f80536cbSVaclav Hapla PetscFunctionBegin; 732dec1416fSJunchao Zhang ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote);CHKERRQ(ierr); 733f80536cbSVaclav Hapla nleaves = roffset[nranks]; 734f80536cbSVaclav Hapla ierr = PetscMalloc2(nleaves, rmine1, nleaves, rremote1);CHKERRQ(ierr); 735f80536cbSVaclav Hapla for (r=0; r<nranks; r++) { 736f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 737f80536cbSVaclav Hapla - to unify order with the other side */ 738f80536cbSVaclav Hapla o = roffset[r]; 739f80536cbSVaclav Hapla n = roffset[r+1] - o; 740580bdb30SBarry Smith ierr = PetscArraycpy(&(*rmine1)[o], &rmine[o], n);CHKERRQ(ierr); 741580bdb30SBarry Smith ierr = PetscArraycpy(&(*rremote1)[o], &rremote[o], n);CHKERRQ(ierr); 742f80536cbSVaclav Hapla ierr = PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]);CHKERRQ(ierr); 743f80536cbSVaclav Hapla } 744f80536cbSVaclav Hapla PetscFunctionReturn(0); 745f80536cbSVaclav Hapla } 746f80536cbSVaclav Hapla 74727d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm) 7482e745bdaSMatthew G. Knepley { 74927d0e99aSVaclav Hapla /* Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */ 75027d0e99aSVaclav Hapla PetscInt masterCone[2]; 751cae7fe92SVaclav Hapla PetscInt (*roots)[2], (*leaves)[2]; 7528a650c75SVaclav Hapla PetscMPIInt (*rootsRanks)[2], (*leavesRanks)[2]; 75327d0e99aSVaclav Hapla 75427d0e99aSVaclav Hapla PetscSF sf=NULL; 755a0d42dbcSVaclav Hapla const PetscInt *locals=NULL; 756a0d42dbcSVaclav Hapla const PetscSFNode *remotes=NULL; 7578a650c75SVaclav Hapla PetscInt nroots, nleaves, p, c; 758f80536cbSVaclav Hapla PetscInt nranks, n, o, r; 759a0d42dbcSVaclav Hapla const PetscMPIInt *ranks=NULL; 760a0d42dbcSVaclav Hapla const PetscInt *roffset=NULL; 761a0d42dbcSVaclav Hapla PetscInt *rmine1=NULL, *rremote1=NULL; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 762a0d42dbcSVaclav Hapla const PetscInt *cone=NULL; 763adeface4SVaclav Hapla PetscInt coneSize, ind0; 7642e745bdaSMatthew G. Knepley MPI_Comm comm; 76527d0e99aSVaclav Hapla PetscMPIInt rank,size; 7662e745bdaSMatthew G. Knepley PetscInt debug = 0; 7672e745bdaSMatthew G. Knepley PetscErrorCode ierr; 7682e745bdaSMatthew G. Knepley 7692e745bdaSMatthew G. Knepley PetscFunctionBegin; 770df6a9fadSVaclav Hapla ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7712e745bdaSMatthew G. Knepley ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes);CHKERRQ(ierr); 7723ede9f65SMatthew G. Knepley if (nroots < 0) PetscFunctionReturn(0); 773f80536cbSVaclav Hapla ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 774dec1416fSJunchao Zhang ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL);CHKERRQ(ierr); 775dc21a0bfSVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-before_fix_dm_view");CHKERRQ(ierr); 77627d0e99aSVaclav Hapla #if defined(PETSC_USE_DEBUG) 777dc21a0bfSVaclav Hapla ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 778dc21a0bfSVaclav Hapla #endif 779f80536cbSVaclav Hapla ierr = SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1);CHKERRQ(ierr); 7808a650c75SVaclav Hapla ierr = PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks);CHKERRQ(ierr); 7812e745bdaSMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 7822e745bdaSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 78327d0e99aSVaclav Hapla ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 7849e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 7859e24d8a0SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 7869e24d8a0SVaclav Hapla ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 78727d0e99aSVaclav Hapla if (coneSize < 2) { 78827d0e99aSVaclav Hapla for (c = 0; c < 2; c++) { 78927d0e99aSVaclav Hapla roots[p][c] = -1; 79027d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 79127d0e99aSVaclav Hapla } 79227d0e99aSVaclav Hapla continue; 79327d0e99aSVaclav Hapla } 7942e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 7958a650c75SVaclav Hapla for (c = 0; c < 2; c++) { 7968a650c75SVaclav Hapla ierr = PetscFindInt(cone[c], nleaves, locals, &ind0);CHKERRQ(ierr); 7978a650c75SVaclav Hapla if (ind0 < 0) { 7988a650c75SVaclav Hapla roots[p][c] = cone[c]; 7998a650c75SVaclav Hapla rootsRanks[p][c] = rank; 800c8148b97SVaclav Hapla } else { 8018a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 8028a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 8038a650c75SVaclav Hapla } 8042e745bdaSMatthew G. Knepley } 8052e745bdaSMatthew G. Knepley } 8069e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 8078ccb905dSVaclav Hapla for (c = 0; c < 2; c++) { 8088ccb905dSVaclav Hapla leaves[p][c] = -2; 8098ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 8108ccb905dSVaclav Hapla } 811c8148b97SVaclav Hapla } 8122e745bdaSMatthew G. Knepley ierr = PetscSFBcastBegin(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr); 8138a650c75SVaclav Hapla ierr = PetscSFBcastBegin(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr); 8142e745bdaSMatthew G. Knepley ierr = PetscSFBcastEnd(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr); 8158a650c75SVaclav Hapla ierr = PetscSFBcastEnd(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr); 816c8148b97SVaclav Hapla if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 81727d0e99aSVaclav Hapla if (debug && rank == 0) {ierr = PetscSynchronizedPrintf(comm, "Referenced roots\n");CHKERRQ(ierr);} 8189e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 8199e24d8a0SVaclav Hapla if (leaves[p][0] < 0) continue; 8209e24d8a0SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8219e24d8a0SVaclav Hapla ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 82227d0e99aSVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] %4D: cone=[%4D %4D] roots=[(%d,%4D) (%d,%4D)] leaves=[(%d,%4D) (%d,%4D)]", rank, p, cone[0], cone[1], rootsRanks[p][0], roots[p][0], rootsRanks[p][1], roots[p][1], leavesRanks[p][0], leaves[p][0], leavesRanks[p][1], leaves[p][1]);CHKERRQ(ierr);} 82382f5c0aeSVaclav Hapla if ((leaves[p][0] != roots[p][0]) || (leaves[p][1] != roots[p][1]) || (leavesRanks[p][0] != rootsRanks[p][0]) || (leavesRanks[p][1] != rootsRanks[p][1])) { 82427d0e99aSVaclav Hapla /* Translate these two leaves to my cone points; masterCone means desired order p's cone points */ 825f80536cbSVaclav Hapla for (c = 0; c < 2; c++) { 82627d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 82727d0e99aSVaclav Hapla /* A local leave is just taken as it is */ 82827d0e99aSVaclav Hapla masterCone[c] = leaves[p][c]; 82927d0e99aSVaclav Hapla continue; 83027d0e99aSVaclav Hapla } 831f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 832f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 833f80536cbSVaclav Hapla ierr = PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r);CHKERRQ(ierr); 83427d0e99aSVaclav Hapla if (PetscUnlikely(r < 0)) SETERRQ7(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leave (%d,%D): leave rank not found among remote ranks",p,c,cone[c],rootsRanks[p][c],roots[p][c],leavesRanks[p][c],leaves[p][c]); 83527d0e99aSVaclav Hapla if (PetscUnlikely(ranks[r] < 0 || ranks[r] >= size)) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_PLIB, "p=%D c=%D commsize=%d: ranks[%D] = %d makes no sense",p,c,size,r,ranks[r]); 836f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 837f80536cbSVaclav Hapla o = roffset[r]; 838f80536cbSVaclav Hapla n = roffset[r+1] - o; 839f80536cbSVaclav Hapla ierr = PetscFindInt(leaves[p][c], n, &rremote1[o], &ind0);CHKERRQ(ierr); 84027d0e99aSVaclav Hapla if (PetscUnlikely(ind0 < 0)) SETERRQ7(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D cone[%D]=%D root (%d,%D) leave (%d,%D): corresponding remote point not found - it seems there is missing connection in point SF!",p,c,cone[c],rootsRanks[p][c],roots[p][c],leavesRanks[p][c],leaves[p][c]); 841f80536cbSVaclav Hapla /* Get the corresponding local point */ 842f80536cbSVaclav Hapla masterCone[c] = rmine1[o+ind0];CHKERRQ(ierr); 843f80536cbSVaclav Hapla } 84427d0e99aSVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(comm, " masterCone=[%4D %4D]\n", masterCone[0], masterCone[1]);CHKERRQ(ierr);} 84527d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 846f80536cbSVaclav Hapla /* Vaclav's note: Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */ 847f80536cbSVaclav Hapla ierr = DMPlexOrientCell(dm, p, 2, masterCone);CHKERRQ(ierr); 84827d0e99aSVaclav Hapla } else if (debug) {ierr = PetscSynchronizedPrintf(comm, " ==\n");CHKERRQ(ierr);} 84923aaf07bSVaclav Hapla } 85027d0e99aSVaclav Hapla if (debug) { 85127d0e99aSVaclav Hapla ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 85227d0e99aSVaclav Hapla ierr = MPI_Barrier(comm);CHKERRQ(ierr); 8532e745bdaSMatthew G. Knepley } 854adeface4SVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-after_fix_dm_view");CHKERRQ(ierr); 8558a650c75SVaclav Hapla ierr = PetscFree4(roots, leaves, rootsRanks, leavesRanks);CHKERRQ(ierr); 8567c7bb832SVaclav Hapla ierr = PetscFree2(rmine1, rremote1);CHKERRQ(ierr); 8572e745bdaSMatthew G. Knepley PetscFunctionReturn(0); 8582e745bdaSMatthew G. Knepley } 8592e745bdaSMatthew G. Knepley 8602e72742cSMatthew 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[]) 8617bffde78SMichael Lange { 8622e72742cSMatthew G. Knepley PetscInt idx; 8632e72742cSMatthew G. Knepley PetscMPIInt rank; 8642e72742cSMatthew G. Knepley PetscBool flg; 8657bffde78SMichael Lange PetscErrorCode ierr; 8667bffde78SMichael Lange 8677bffde78SMichael Lange PetscFunctionBegin; 8682e72742cSMatthew G. Knepley ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr); 8692e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 8702e72742cSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 8712e72742cSMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr); 8722e72742cSMatthew G. Knepley for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]%s %D %s %D\n", rank, idxname, idx, valname, a[idx]);CHKERRQ(ierr);} 8732e72742cSMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 8742e72742cSMatthew G. Knepley PetscFunctionReturn(0); 8752e72742cSMatthew G. Knepley } 8762e72742cSMatthew G. Knepley 8772e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) 8782e72742cSMatthew G. Knepley { 8792e72742cSMatthew G. Knepley PetscInt idx; 8802e72742cSMatthew G. Knepley PetscMPIInt rank; 8812e72742cSMatthew G. Knepley PetscBool flg; 8822e72742cSMatthew G. Knepley PetscErrorCode ierr; 8832e72742cSMatthew G. Knepley 8842e72742cSMatthew G. Knepley PetscFunctionBegin; 8852e72742cSMatthew G. Knepley ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr); 8862e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 8872e72742cSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 8882e72742cSMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr); 8892e72742cSMatthew G. Knepley if (idxname) { 8902e72742cSMatthew G. Knepley for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]%s %D rank %D index %D\n", rank, idxname, idx, a[idx].rank, a[idx].index);CHKERRQ(ierr);} 8912e72742cSMatthew G. Knepley } else { 8922e72742cSMatthew G. Knepley for (idx = 0; idx < n; ++idx) {ierr = PetscSynchronizedPrintf(comm, "[%d]rank %D index %D\n", rank, a[idx].rank, a[idx].index);CHKERRQ(ierr);} 8932e72742cSMatthew G. Knepley } 8942e72742cSMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 8952e72742cSMatthew G. Knepley PetscFunctionReturn(0); 8962e72742cSMatthew G. Knepley } 8972e72742cSMatthew G. Knepley 8983be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint) 8992e72742cSMatthew G. Knepley { 9003be36e83SMatthew G. Knepley PetscSF sf; 9013be36e83SMatthew G. Knepley const PetscInt *locals; 9023be36e83SMatthew G. Knepley PetscMPIInt rank; 9032e72742cSMatthew G. Knepley PetscErrorCode ierr; 9042e72742cSMatthew G. Knepley 9052e72742cSMatthew G. Knepley PetscFunctionBegin; 9063be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 9073be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 9083be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, NULL, &locals, NULL);CHKERRQ(ierr); 9092e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 9102e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 9112e72742cSMatthew G. Knepley } else { 9122e72742cSMatthew G. Knepley PetscHashIJKey key; 9133be36e83SMatthew G. Knepley PetscInt l; 9142e72742cSMatthew G. Knepley 9152e72742cSMatthew G. Knepley key.i = remotePoint.index; 9162e72742cSMatthew G. Knepley key.j = remotePoint.rank; 9173be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(remotehash, key, &l);CHKERRQ(ierr); 9183be36e83SMatthew G. Knepley if (l >= 0) { 9193be36e83SMatthew G. Knepley *localPoint = locals[l]; 9202e72742cSMatthew G. Knepley } else PetscFunctionReturn(1); 9212e72742cSMatthew G. Knepley } 9222e72742cSMatthew G. Knepley PetscFunctionReturn(0); 9232e72742cSMatthew G. Knepley } 9242e72742cSMatthew G. Knepley 9253be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint) 9263be36e83SMatthew G. Knepley { 9273be36e83SMatthew G. Knepley PetscSF sf; 9283be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 9293be36e83SMatthew G. Knepley const PetscSFNode *remotes; 9303be36e83SMatthew G. Knepley PetscInt Nl, l; 9313be36e83SMatthew G. Knepley PetscMPIInt rank; 9323be36e83SMatthew G. Knepley PetscErrorCode ierr; 9333be36e83SMatthew G. Knepley 9343be36e83SMatthew G. Knepley PetscFunctionBegin; 9353be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 9363be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 9373be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes);CHKERRQ(ierr); 9383be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 9393be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 9403be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 9413be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 9423be36e83SMatthew G. Knepley ierr = PetscFindInt(localPoint, Nl, locals, &l);CHKERRQ(ierr); 9433be36e83SMatthew G. Knepley if (l < 0) PetscFunctionReturn(1); 9443be36e83SMatthew G. Knepley *remotePoint = remotes[l]; 9453be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9463be36e83SMatthew G. Knepley owned: 9473be36e83SMatthew G. Knepley remotePoint->rank = rank; 9483be36e83SMatthew G. Knepley remotePoint->index = localPoint; 9493be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9503be36e83SMatthew G. Knepley } 9513be36e83SMatthew G. Knepley 9523be36e83SMatthew G. Knepley 9533be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) 9543be36e83SMatthew G. Knepley { 9553be36e83SMatthew G. Knepley PetscSF sf; 9563be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 9573be36e83SMatthew G. Knepley PetscInt Nl, idx; 9583be36e83SMatthew G. Knepley PetscErrorCode ierr; 9593be36e83SMatthew G. Knepley 9603be36e83SMatthew G. Knepley PetscFunctionBegin; 9613be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 9623be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 9633be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL);CHKERRQ(ierr); 9643be36e83SMatthew G. Knepley if (Nl < 0) PetscFunctionReturn(0); 9653be36e83SMatthew G. Knepley ierr = PetscFindInt(p, Nl, locals, &idx);CHKERRQ(ierr); 9663be36e83SMatthew G. Knepley if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);} 9673be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 9683be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 9693be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 9703be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9713be36e83SMatthew G. Knepley } 9723be36e83SMatthew G. Knepley 9733be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) 9743be36e83SMatthew G. Knepley { 9753be36e83SMatthew G. Knepley const PetscInt *cone; 9763be36e83SMatthew G. Knepley PetscInt coneSize, c; 9773be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 9783be36e83SMatthew G. Knepley PetscErrorCode ierr; 9793be36e83SMatthew G. Knepley 9803be36e83SMatthew G. Knepley PetscFunctionBegin; 9813be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 9823be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 9833be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9843be36e83SMatthew G. Knepley PetscBool pointShared; 9853be36e83SMatthew G. Knepley 9863be36e83SMatthew G. Knepley ierr = DMPlexPointIsShared(dm, cone[c], &pointShared);CHKERRQ(ierr); 9873be36e83SMatthew G. Knepley cShared = (PetscBool) (cShared && pointShared); 9883be36e83SMatthew G. Knepley } 9893be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 9903be36e83SMatthew G. Knepley PetscFunctionReturn(0); 9913be36e83SMatthew G. Knepley } 9923be36e83SMatthew G. Knepley 9933be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) 9943be36e83SMatthew G. Knepley { 9953be36e83SMatthew G. Knepley const PetscInt *cone; 9963be36e83SMatthew G. Knepley PetscInt coneSize, c; 9973be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 9983be36e83SMatthew G. Knepley PetscErrorCode ierr; 9993be36e83SMatthew G. Knepley 10003be36e83SMatthew G. Knepley PetscFunctionBegin; 10013be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 10023be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 10033be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10043be36e83SMatthew G. Knepley PetscSFNode rcp; 10053be36e83SMatthew G. Knepley 10063be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cone[c], &rcp); 10073be36e83SMatthew G. Knepley if (ierr) { 10083be36e83SMatthew G. Knepley cmin = missing; 10093be36e83SMatthew G. Knepley } else { 10103be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 10113be36e83SMatthew G. Knepley } 10123be36e83SMatthew G. Knepley } 10133be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 10143be36e83SMatthew G. Knepley PetscFunctionReturn(0); 10153be36e83SMatthew G. Knepley } 10163be36e83SMatthew G. Knepley 10173be36e83SMatthew G. Knepley /* 10183be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 10193be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 10203be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 10213be36e83SMatthew G. Knepley */ 10223be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) 10233be36e83SMatthew G. Knepley { 10243be36e83SMatthew G. Knepley MPI_Comm comm; 10253be36e83SMatthew G. Knepley const PetscInt *support; 1026*cf4dc471SVaclav Hapla PetscInt supportSize, s, off = 0, idx = 0, overlap, cellHeight, height; 10273be36e83SMatthew G. Knepley PetscMPIInt rank; 10283be36e83SMatthew G. Knepley PetscErrorCode ierr; 10293be36e83SMatthew G. Knepley 10303be36e83SMatthew G. Knepley PetscFunctionBegin; 10313be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 10323be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1033*cf4dc471SVaclav Hapla ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 1034*cf4dc471SVaclav Hapla ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1035*cf4dc471SVaclav Hapla ierr = DMPlexGetPointHeight(dm, p, &height);CHKERRQ(ierr); 1036*cf4dc471SVaclav Hapla if (!overlap && height <= cellHeight+1) { 1037*cf4dc471SVaclav Hapla /* cells can't be shared for non-overlapping meshes */ 1038*cf4dc471SVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Skipping face %D to avoid adding cell to hashmap since this is nonoverlapping mesh\n", rank, p);CHKERRQ(ierr);} 1039*cf4dc471SVaclav Hapla PetscFunctionReturn(0); 1040*cf4dc471SVaclav Hapla } 10413be36e83SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 10423be36e83SMatthew G. Knepley ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 10433be36e83SMatthew G. Knepley if (candidates) {ierr = PetscSectionGetOffset(candidateSection, p, &off);CHKERRQ(ierr);} 10443be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 10453be36e83SMatthew G. Knepley const PetscInt face = support[s]; 10463be36e83SMatthew G. Knepley const PetscInt *cone; 10473be36e83SMatthew G. Knepley PetscSFNode cpmin={-1,-1}, rp={-1,-1}; 10483be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 10493be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 10503be36e83SMatthew G. Knepley PetscHashIJKey key; 10513be36e83SMatthew G. Knepley 10523be36e83SMatthew G. Knepley /* Only add point once */ 10533be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Support face %D\n", rank, face);CHKERRQ(ierr);} 10543be36e83SMatthew G. Knepley key.i = p; 10553be36e83SMatthew G. Knepley key.j = face; 10563be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(faceHash, key, &f);CHKERRQ(ierr); 10573be36e83SMatthew G. Knepley if (f >= 0) continue; 10583be36e83SMatthew G. Knepley ierr = DMPlexConeIsShared(dm, face, &isShared);CHKERRQ(ierr); 10593be36e83SMatthew G. Knepley ierr = DMPlexGetConeMinimum(dm, face, &cpmin);CHKERRQ(ierr); 10603be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, p, &rp);CHKERRQ(ierr); 10613be36e83SMatthew G. Knepley if (debug) { 10623be36e83SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] Face point %D is shared: %d\n", rank, face, (int) isShared);CHKERRQ(ierr); 10633be36e83SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] Global point (%D, %D) Min Cone Point (%D, %D)\n", rank, rp.rank, rp.index, cpmin.rank, cpmin.index);CHKERRQ(ierr); 10643be36e83SMatthew G. Knepley } 10653be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 10663be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 10673be36e83SMatthew G. Knepley if (candidates) { 10683be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Adding shared face %D at idx %D\n[%d] ", rank, face, idx, rank);CHKERRQ(ierr);} 10693be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10703be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 10713be36e83SMatthew G. Knepley candidates[off+idx].rank = -1; 10723be36e83SMatthew G. Knepley candidates[off+idx++].index = coneSize-1; 10733be36e83SMatthew G. Knepley candidates[off+idx].rank = rank; 10743be36e83SMatthew G. Knepley candidates[off+idx++].index = face; 10753be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10763be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 10773be36e83SMatthew G. Knepley 10783be36e83SMatthew G. Knepley if (cp == p) continue; 10793be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx]);CHKERRQ(ierr); 10803be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index);CHKERRQ(ierr);} 10813be36e83SMatthew G. Knepley ++idx; 10823be36e83SMatthew G. Knepley } 10833be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "\n");CHKERRQ(ierr);} 10843be36e83SMatthew G. Knepley } else { 10853be36e83SMatthew G. Knepley /* Add cone size to section */ 10863be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %D\n", rank, face);CHKERRQ(ierr);} 10873be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10883be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 10893be36e83SMatthew G. Knepley ierr = PetscSectionAddDof(candidateSection, p, coneSize+1);CHKERRQ(ierr); 10903be36e83SMatthew G. Knepley } 10913be36e83SMatthew G. Knepley } 10923be36e83SMatthew G. Knepley } 10933be36e83SMatthew G. Knepley PetscFunctionReturn(0); 10943be36e83SMatthew G. Knepley } 10953be36e83SMatthew G. Knepley 10962e72742cSMatthew G. Knepley /*@ 10972e72742cSMatthew G. Knepley DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation 10982e72742cSMatthew G. Knepley 1099d083f849SBarry Smith Collective on dm 11002e72742cSMatthew G. Knepley 11012e72742cSMatthew G. Knepley Input Parameters: 11022e72742cSMatthew G. Knepley + dm - The interpolated DM 11032e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points 11042e72742cSMatthew G. Knepley 11052e72742cSMatthew G. Knepley Output Parameter: 11062e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points 11072e72742cSMatthew G. Knepley 1108f0cfc026SVaclav Hapla Level: developer 11092e72742cSMatthew G. Knepley 11102e72742cSMatthew 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 11112e72742cSMatthew G. Knepley 11122e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate() 11132e72742cSMatthew G. Knepley @*/ 1114e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 11152e72742cSMatthew G. Knepley { 11163be36e83SMatthew G. Knepley MPI_Comm comm; 11173be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 11183be36e83SMatthew G. Knepley PetscHMapI claimshash; 11193be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 11203be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 11212e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 11222e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 11233be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 11243be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 11253be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 1126f0cfc026SVaclav Hapla PetscMPIInt rank; 11272e72742cSMatthew G. Knepley PetscErrorCode ierr; 11282e72742cSMatthew G. Knepley 11292e72742cSMatthew G. Knepley PetscFunctionBegin; 1130f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11313be36e83SMatthew G. Knepley PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 3); 1132f0cfc026SVaclav Hapla ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr); 1133f0cfc026SVaclav Hapla if (!flg) PetscFunctionReturn(0); 11343be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 11353be36e83SMatthew G. Knepley ierr = DMSetPointSF(dm, pointSF);CHKERRQ(ierr); 11363be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 11373be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 11383be36e83SMatthew G. Knepley ierr = DMPlexGetOverlap(dm, &ov);CHKERRQ(ierr); 11393be36e83SMatthew G. Knepley if (ov) SETERRQ(comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 11403be36e83SMatthew G. Knepley ierr = PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug);CHKERRQ(ierr); 11412e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view");CHKERRQ(ierr); 11422e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view");CHKERRQ(ierr); 114325afeb17SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 11443be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 11453be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints);CHKERRQ(ierr); 11463be36e83SMatthew G. Knepley if (Nr < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 11473be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&remoteHash);CHKERRQ(ierr); 11483be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11493be36e83SMatthew G. Knepley PetscHashIJKey key; 11502e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 11512e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 11523be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(remoteHash, key, l);CHKERRQ(ierr); 11537bffde78SMichael Lange } 115466aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 11552e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 11562e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 11573be36e83SMatthew G. Knepley ierr = IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree);CHKERRQ(ierr); 11583be36e83SMatthew G. Knepley /* 11593be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 11603be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 11613be36e83SMatthew G. Knepley \begin{itemize} 11623be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 11633be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 11643be36e83SMatthew G. Knepley \end{itemize} 11653be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 11663be36e83SMatthew 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 11673be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 11683be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 11693be36e83SMatthew G. Knepley */ 11703be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 11713be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 11723be36e83SMatthew G. Knepley The array holds candidate shared faces, each face is refered to by the leaf point */ 11733be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateSection);CHKERRQ(ierr); 11743be36e83SMatthew G. Knepley ierr = PetscSectionSetChart(candidateSection, 0, Nr);CHKERRQ(ierr); 11757bffde78SMichael Lange { 11763be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 11772e72742cSMatthew G. Knepley 11783be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&faceHash);CHKERRQ(ierr); 11793be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11803be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 11812e72742cSMatthew G. Knepley 11823be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 11833be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug);CHKERRQ(ierr); 11842e72742cSMatthew G. Knepley } 11853be36e83SMatthew G. Knepley ierr = PetscHMapIJClear(faceHash);CHKERRQ(ierr); 11867bffde78SMichael Lange ierr = PetscSectionSetUp(candidateSection);CHKERRQ(ierr); 11877bffde78SMichael Lange ierr = PetscSectionGetStorageSize(candidateSection, &candidatesSize);CHKERRQ(ierr); 11887bffde78SMichael Lange ierr = PetscMalloc1(candidatesSize, &candidates);CHKERRQ(ierr); 11893be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11903be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 11912e72742cSMatthew G. Knepley 11923be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 11933be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug);CHKERRQ(ierr); 11942e72742cSMatthew G. Knepley } 11953be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&faceHash);CHKERRQ(ierr); 11963be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 11977bffde78SMichael Lange } 11983be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateSection, "Candidate Section");CHKERRQ(ierr); 11992e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view");CHKERRQ(ierr); 12003be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates);CHKERRQ(ierr); 12013be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 12022e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 12037bffde78SMichael Lange { 12047bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 12057bffde78SMichael Lange PetscInt *remoteOffsets; 12062e72742cSMatthew G. Knepley 12077bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 12087bffde78SMichael Lange ierr = PetscSFCreateInverseSF(sfMulti, &sfInverse);CHKERRQ(ierr); 12093be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateRemoteSection);CHKERRQ(ierr); 12103be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection);CHKERRQ(ierr); 12113be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates);CHKERRQ(ierr); 12123be36e83SMatthew G. Knepley ierr = PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize);CHKERRQ(ierr); 12137bffde78SMichael Lange ierr = PetscMalloc1(candidatesRemoteSize, &candidatesRemote);CHKERRQ(ierr); 12147bffde78SMichael Lange ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr); 12157bffde78SMichael Lange ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr); 12167bffde78SMichael Lange ierr = PetscSFDestroy(&sfInverse);CHKERRQ(ierr); 12177bffde78SMichael Lange ierr = PetscSFDestroy(&sfCandidates);CHKERRQ(ierr); 12187bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 12192e72742cSMatthew G. Knepley 12203be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section");CHKERRQ(ierr); 12213be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view");CHKERRQ(ierr); 12223be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote);CHKERRQ(ierr); 12237bffde78SMichael Lange } 12243be36e83SMatthew 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 */ 12257bffde78SMichael Lange { 12263be36e83SMatthew G. Knepley PetscHashIJKLRemote faceTable; 12273be36e83SMatthew G. Knepley PetscInt idx, idx2; 12283be36e83SMatthew G. Knepley 12293be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteCreate(&faceTable);CHKERRQ(ierr); 12302e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 12313be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 12322e72742cSMatthew G. Knepley PetscInt deg; 12333be36e83SMatthew G. Knepley 12342e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 12352e72742cSMatthew G. Knepley PetscInt offset, dof, d; 12362e72742cSMatthew G. Knepley 12373be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx, &dof);CHKERRQ(ierr); 12383be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx, &offset);CHKERRQ(ierr); 12393be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 12402e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12413be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 12423be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 12433be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx+1]; 12443be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 12453be36e83SMatthew G. Knepley PetscSFNode fcp0; 12463be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 12472e72742cSMatthew G. Knepley const PetscInt *join = NULL; 12483be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 12493be36e83SMatthew G. Knepley PetscHashIter iter; 12503be36e83SMatthew G. Knepley PetscBool missing; 12512e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 12522e72742cSMatthew G. Knepley 125366e92ce5SVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking face (%D, %D) at (%D, %D, %D) with cone size %D\n", rank, rface.rank, rface.index, r, idx, d, Np);CHKERRQ(ierr);} 125466e92ce5SVaclav Hapla if (Np > 4) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle face (%D, %D) at (%D, %D, %D) with %D cone points", rface.rank, rface.index, r, idx, d, Np); 12553be36e83SMatthew G. Knepley fcp0.rank = rank; 12563be36e83SMatthew G. Knepley fcp0.index = r; 12573be36e83SMatthew G. Knepley d += Np; 12583be36e83SMatthew G. Knepley /* Put remote face in hash table */ 12593be36e83SMatthew G. Knepley key.i = fcp0; 12603be36e83SMatthew G. Knepley key.j = fcone[0]; 12613be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 12623be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 12633be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 12643be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 12653be36e83SMatthew G. Knepley if (missing) { 12663be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Setting remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 12673be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 12683be36e83SMatthew G. Knepley } else { 12693be36e83SMatthew G. Knepley PetscSFNode oface; 12703be36e83SMatthew G. Knepley 12713be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 12723be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 12733be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 12743be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 12753be36e83SMatthew G. Knepley } 12763be36e83SMatthew G. Knepley } 12773be36e83SMatthew G. Knepley /* Check for local face */ 12782e72742cSMatthew G. Knepley points[0] = r; 12793be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 12803be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p]); 12813be36e83SMatthew G. Knepley if (ierr) break; /* We got a point not in our overlap */ 12823be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking local candidate %D\n", rank, points[p]);CHKERRQ(ierr);} 12837bffde78SMichael Lange } 12842e72742cSMatthew G. Knepley if (ierr) continue; 12853be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 12867bffde78SMichael Lange if (joinSize == 1) { 12873be36e83SMatthew G. Knepley PetscSFNode lface; 12883be36e83SMatthew G. Knepley PetscSFNode oface; 12893be36e83SMatthew G. Knepley 12903be36e83SMatthew G. Knepley /* Always replace with local face */ 12913be36e83SMatthew G. Knepley lface.rank = rank; 12923be36e83SMatthew G. Knepley lface.index = join[0]; 12933be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 12943be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing (%D, %D) with local face (%D, %D)\n", rank, oface.index, oface.rank, lface.index, lface.rank);CHKERRQ(ierr);} 12953be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, lface);CHKERRQ(ierr); 12967bffde78SMichael Lange } 12973be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 12983be36e83SMatthew G. Knepley } 12993be36e83SMatthew G. Knepley } 13003be36e83SMatthew G. Knepley /* Put back faces for this root */ 13013be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 13023be36e83SMatthew G. Knepley PetscInt offset, dof, d; 13033be36e83SMatthew G. Knepley 13043be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx2, &dof);CHKERRQ(ierr); 13053be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx2, &offset);CHKERRQ(ierr); 13063be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 13073be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 13083be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 13093be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 13103be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 13113be36e83SMatthew G. Knepley PetscSFNode fcp0; 13123be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 13133be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 13143be36e83SMatthew G. Knepley PetscHashIter iter; 13153be36e83SMatthew G. Knepley PetscBool missing; 13163be36e83SMatthew G. Knepley 13173be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Entering face at (%D, %D)\n", rank, r, idx);CHKERRQ(ierr);} 13183be36e83SMatthew G. Knepley if (Np > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np); 13193be36e83SMatthew G. Knepley fcp0.rank = rank; 13203be36e83SMatthew G. Knepley fcp0.index = r; 13213be36e83SMatthew G. Knepley d += Np; 13223be36e83SMatthew G. Knepley /* Find remote face in hash table */ 13233be36e83SMatthew G. Knepley key.i = fcp0; 13243be36e83SMatthew G. Knepley key.j = fcone[0]; 13253be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 13263be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 13273be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 13283be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] key (%D, %D) (%D, %D) (%D, %D) (%D, %D)\n", rank, key.i.rank, key.i.index, key.j.rank, key.j.index, key.k.rank, key.k.index, key.l.rank, key.l.index);CHKERRQ(ierr);} 13293be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 13303be36e83SMatthew G. Knepley if (missing) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an assoicated face", r, idx2); 13313be36e83SMatthew G. Knepley else {ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]);CHKERRQ(ierr);} 13327bffde78SMichael Lange } 13337bffde78SMichael Lange } 13347bffde78SMichael Lange } 13352e72742cSMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL);CHKERRQ(ierr);} 13363be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteDestroy(&faceTable);CHKERRQ(ierr); 13377bffde78SMichael Lange } 13383be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 13397bffde78SMichael Lange { 13407bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 13417bffde78SMichael Lange PetscSFNode *remotePointsNew; 13422e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 13433be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 13442e72742cSMatthew G. Knepley 13453be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 13467bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 13473be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &claimSection);CHKERRQ(ierr); 13483be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection);CHKERRQ(ierr); 13493be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims);CHKERRQ(ierr); 13502e72742cSMatthew G. Knepley ierr = PetscSectionGetStorageSize(claimSection, &claimsSize);CHKERRQ(ierr); 13512e72742cSMatthew G. Knepley ierr = PetscMalloc1(claimsSize, &claims);CHKERRQ(ierr); 13523be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 13537bffde78SMichael Lange ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr); 13547bffde78SMichael Lange ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr); 13557bffde78SMichael Lange ierr = PetscSFDestroy(&sfClaims);CHKERRQ(ierr); 13567bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 13573be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) claimSection, "Claim Section");CHKERRQ(ierr); 13582e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view");CHKERRQ(ierr); 13593be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims);CHKERRQ(ierr); 13603be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 13613be36e83SMatthew 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 */ 1362e8f14785SLisandro Dalcin ierr = PetscHMapICreate(&claimshash);CHKERRQ(ierr); 13633be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 13643be36e83SMatthew G. Knepley PetscInt dof, off, d; 13652e72742cSMatthew G. Knepley 13663be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %D\n", rank, r);CHKERRQ(ierr);} 13673be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateSection, r, &dof);CHKERRQ(ierr); 13683be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateSection, r, &off);CHKERRQ(ierr); 13692e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 13703be36e83SMatthew G. Knepley if (claims[off+d].rank >= 0) { 13713be36e83SMatthew G. Knepley const PetscInt faceInd = off+d; 13723be36e83SMatthew G. Knepley const PetscInt Np = candidates[off+d].index; 13732e72742cSMatthew G. Knepley const PetscInt *join = NULL; 13742e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 13752e72742cSMatthew G. Knepley 13763be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Found claim for remote point (%D, %D)\n", rank, claims[faceInd].rank, claims[faceInd].index);CHKERRQ(ierr);} 13773be36e83SMatthew G. Knepley points[0] = r; 13783be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[0]);CHKERRQ(ierr);} 13793be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 13803be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1]);CHKERRQ(ierr); 13813be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[c+1]);CHKERRQ(ierr);} 13822e72742cSMatthew G. Knepley } 13833be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 13842e72742cSMatthew G. Knepley if (joinSize == 1) { 13853be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 13863be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %D for non-remote partner\n", rank, join[0]);CHKERRQ(ierr);} 13873be36e83SMatthew G. Knepley } else { 13883be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Found local face %D\n", rank, join[0]);CHKERRQ(ierr);} 13892e72742cSMatthew G. Knepley ierr = PetscHMapISet(claimshash, join[0], faceInd);CHKERRQ(ierr); 13902e72742cSMatthew G. Knepley } 13913be36e83SMatthew G. Knepley } else { 13923be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank);CHKERRQ(ierr);} 13933be36e83SMatthew G. Knepley } 13943be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 13953be36e83SMatthew G. Knepley } else { 13963be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] No claim for point %D\n", rank, r);CHKERRQ(ierr);} 13973be36e83SMatthew G. Knepley d += claims[off+d].index+1; 13987bffde78SMichael Lange } 13997bffde78SMichael Lange } 14003be36e83SMatthew G. Knepley } 14013be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 14023be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 14033be36e83SMatthew G. Knepley ierr = PetscHMapIGetSize(claimshash, &NlNew);CHKERRQ(ierr); 14047bffde78SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 14053be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &localPointsNew);CHKERRQ(ierr); 14063be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &remotePointsNew);CHKERRQ(ierr); 14073be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 14083be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 14093be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 14103be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 14117bffde78SMichael Lange } 14123be36e83SMatthew G. Knepley p = Nl; 1413e8f14785SLisandro Dalcin ierr = PetscHMapIGetKeys(claimshash, &p, localPointsNew);CHKERRQ(ierr); 14143be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 14153be36e83SMatthew G. Knepley ierr = PetscSortInt(NlNew, &localPointsNew[Nl]);CHKERRQ(ierr); 14163be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 14173be36e83SMatthew G. Knepley PetscInt off; 14183be36e83SMatthew G. Knepley ierr = PetscHMapIGet(claimshash, localPointsNew[p], &off);CHKERRQ(ierr); 14193be36e83SMatthew G. Knepley if (claims[off].rank < 0 || claims[off].index < 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid claim for local point %D, (%D, %D)", localPointsNew[p], claims[off].rank, claims[off].index); 14203be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 14217bffde78SMichael Lange } 14223be36e83SMatthew G. Knepley ierr = PetscSFCreate(comm, &sfPointNew);CHKERRQ(ierr); 14233be36e83SMatthew G. Knepley ierr = PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 14243be36e83SMatthew G. Knepley ierr = PetscSFSetUp(sfPointNew);CHKERRQ(ierr); 14257bffde78SMichael Lange ierr = DMSetPointSF(dm, sfPointNew);CHKERRQ(ierr); 14263be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view");CHKERRQ(ierr); 14277bffde78SMichael Lange ierr = PetscSFDestroy(&sfPointNew);CHKERRQ(ierr); 1428e8f14785SLisandro Dalcin ierr = PetscHMapIDestroy(&claimshash);CHKERRQ(ierr); 14297bffde78SMichael Lange } 14303be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&remoteHash);CHKERRQ(ierr); 14317bffde78SMichael Lange ierr = PetscSectionDestroy(&candidateSection);CHKERRQ(ierr); 14323be36e83SMatthew G. Knepley ierr = PetscSectionDestroy(&candidateRemoteSection);CHKERRQ(ierr); 14337bffde78SMichael Lange ierr = PetscSectionDestroy(&claimSection);CHKERRQ(ierr); 14347bffde78SMichael Lange ierr = PetscFree(candidates);CHKERRQ(ierr); 14357bffde78SMichael Lange ierr = PetscFree(candidatesRemote);CHKERRQ(ierr); 14367bffde78SMichael Lange ierr = PetscFree(claims);CHKERRQ(ierr); 143725afeb17SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 14387bffde78SMichael Lange PetscFunctionReturn(0); 14397bffde78SMichael Lange } 14407bffde78SMichael Lange 1441248eb259SVaclav Hapla /*@ 144280330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 144380330477SMatthew G. Knepley 1444d083f849SBarry Smith Collective on dm 144580330477SMatthew G. Knepley 1446e56d480eSMatthew G. Knepley Input Parameters: 1447e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices 144810a67516SMatthew G. Knepley - dmInt - The interpolated DM 144980330477SMatthew G. Knepley 145080330477SMatthew G. Knepley Output Parameter: 14514e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object 145280330477SMatthew G. Knepley 145380330477SMatthew G. Knepley Level: intermediate 145480330477SMatthew G. Knepley 145595452b02SPatrick Sanan Notes: 145695452b02SPatrick Sanan It does not copy over the coordinates. 145743eeeb2dSStefano Zampini 14589ade3219SVaclav Hapla Developer Notes: 14599ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL. 14609ade3219SVaclav Hapla 146143eeeb2dSStefano Zampini .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellList(), DMPlexCopyCoordinates() 146280330477SMatthew G. Knepley @*/ 14639f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 14649f074e33SMatthew G Knepley { 1465a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 14669a5b13a2SMatthew G Knepley DM idm, odm = dm; 14677bffde78SMichael Lange PetscSF sfPoint; 14682e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 146910a67516SMatthew G. Knepley const char *name; 1470b325530aSVaclav Hapla PetscBool flg=PETSC_TRUE; 14719f074e33SMatthew G Knepley PetscErrorCode ierr; 14729f074e33SMatthew G Knepley 14739f074e33SMatthew G Knepley PetscFunctionBegin; 147410a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 147510a67516SMatthew G. Knepley PetscValidPointer(dmInt, 2); 1476a72f3261SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 14772e1b13c2SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1478c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1479827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1480827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1481827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 148276b791aaSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 148376b791aaSMatthew G. Knepley idm = dm; 1484b21b8912SMatthew G. Knepley } else { 14859a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 14869a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 148710a67516SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 14889a5b13a2SMatthew G Knepley ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 1489c73cfb54SMatthew G. Knepley ierr = DMSetDimension(idm, dim);CHKERRQ(ierr); 14907bffde78SMichael Lange if (depth > 0) { 14917bffde78SMichael Lange ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr); 14927bffde78SMichael Lange ierr = DMGetPointSF(odm, &sfPoint);CHKERRQ(ierr); 149394488200SVaclav Hapla { 14943be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 149594488200SVaclav Hapla PetscInt nroots; 149694488200SVaclav Hapla ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 149794488200SVaclav Hapla if (nroots >= 0) {ierr = DMPlexInterpolatePointSF(idm, sfPoint);CHKERRQ(ierr);} 149894488200SVaclav Hapla } 14997bffde78SMichael Lange } 15009a5b13a2SMatthew G Knepley if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);} 15019a5b13a2SMatthew G Knepley odm = idm; 15029f074e33SMatthew G Knepley } 150310a67516SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 150410a67516SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) idm, name);CHKERRQ(ierr); 150510a67516SMatthew G. Knepley ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr); 15065d80c0bfSVaclav Hapla ierr = DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE);CHKERRQ(ierr); 1507b325530aSVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL);CHKERRQ(ierr); 150827d0e99aSVaclav Hapla if (flg) {ierr = DMPlexOrientInterface_Internal(idm);CHKERRQ(ierr);} 150984699f70SSatish Balay } 151043eeeb2dSStefano Zampini { 151143eeeb2dSStefano Zampini PetscBool isper; 151243eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 151343eeeb2dSStefano Zampini const DMBoundaryType *bd; 151443eeeb2dSStefano Zampini 151543eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 151643eeeb2dSStefano Zampini ierr = DMSetPeriodicity(idm,isper,maxCell,L,bd);CHKERRQ(ierr); 151743eeeb2dSStefano Zampini } 1518827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1519827c4036SVaclav Hapla { 1520d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) idm->data; 1521827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1522827c4036SVaclav Hapla } 15239a5b13a2SMatthew G Knepley *dmInt = idm; 1524a72f3261SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 15259f074e33SMatthew G Knepley PetscFunctionReturn(0); 15269f074e33SMatthew G Knepley } 152707b0a1fcSMatthew G Knepley 152880330477SMatthew G. Knepley /*@ 152980330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 153080330477SMatthew G. Knepley 1531d083f849SBarry Smith Collective on dmA 153280330477SMatthew G. Knepley 153380330477SMatthew G. Knepley Input Parameter: 153480330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates 153580330477SMatthew G. Knepley 153680330477SMatthew G. Knepley Output Parameter: 153780330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates 153880330477SMatthew G. Knepley 153980330477SMatthew G. Knepley Level: intermediate 154080330477SMatthew G. Knepley 154180330477SMatthew G. Knepley Note: This is typically used when adding pieces other than vertices to a mesh 154280330477SMatthew G. Knepley 154365f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 154480330477SMatthew G. Knepley @*/ 154507b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 154607b0a1fcSMatthew G Knepley { 154707b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 154843eeeb2dSStefano Zampini VecType vtype; 154907b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 155007b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 15510bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 155290a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 155343eeeb2dSStefano Zampini PetscBool lc = PETSC_FALSE; 155407b0a1fcSMatthew G Knepley PetscErrorCode ierr; 155507b0a1fcSMatthew G Knepley 155607b0a1fcSMatthew G Knepley PetscFunctionBegin; 155743eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 155843eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 155976b791aaSMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 156090a8aa44SJed Brown ierr = DMGetCoordinateDim(dmA, &cdim);CHKERRQ(ierr); 156190a8aa44SJed Brown ierr = DMSetCoordinateDim(dmB, cdim);CHKERRQ(ierr); 156207b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr); 156307b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr); 156407b0a1fcSMatthew G Knepley if ((vEndA-vStartA) != (vEndB-vStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %d != %d in the second DM", vEndA-vStartA, vEndB-vStartB); 156543eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr); 156643eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr); 156769d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr); 156869d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr); 1569972bc18aSToby Isaac if (coordSectionA == coordSectionB) PetscFunctionReturn(0); 15700bedd6beSMatthew G. Knepley ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr); 15710bedd6beSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 15720bedd6beSMatthew G. Knepley if (Nf > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf); 1573df26b574SMatthew G. Knepley if (!coordSectionB) { 1574df26b574SMatthew G. Knepley PetscInt dim; 1575df26b574SMatthew G. Knepley 1576df26b574SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr); 1577df26b574SMatthew G. Knepley ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr); 1578df26b574SMatthew G. Knepley ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr); 1579df26b574SMatthew G. Knepley ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr); 1580df26b574SMatthew G. Knepley } 158107b0a1fcSMatthew G Knepley ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); 158207b0a1fcSMatthew G Knepley ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr); 158307b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr); 158443eeeb2dSStefano Zampini ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr); 158543eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 1586367003a6SStefano Zampini if ((cEndA-cStartA) != (cEndB-cStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cells in first DM %D != %D in the second DM", cEndA-cStartA, cEndB-cStartB); 158743eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 158843eeeb2dSStefano Zampini cE = vEndB; 158943eeeb2dSStefano Zampini lc = PETSC_TRUE; 159043eeeb2dSStefano Zampini } else { 159143eeeb2dSStefano Zampini cS = vStartB; 159243eeeb2dSStefano Zampini cE = vEndB; 159343eeeb2dSStefano Zampini } 159443eeeb2dSStefano Zampini ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr); 159507b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 159607b0a1fcSMatthew G Knepley ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr); 159707b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr); 159807b0a1fcSMatthew G Knepley } 159943eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 160043eeeb2dSStefano Zampini PetscInt c; 160143eeeb2dSStefano Zampini 160243eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 160343eeeb2dSStefano Zampini PetscInt dof; 160443eeeb2dSStefano Zampini 160543eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 160643eeeb2dSStefano Zampini ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr); 160743eeeb2dSStefano Zampini ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr); 160843eeeb2dSStefano Zampini } 160943eeeb2dSStefano Zampini } 161007b0a1fcSMatthew G Knepley ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); 161107b0a1fcSMatthew G Knepley ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr); 161207b0a1fcSMatthew G Knepley ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr); 16138b9ced59SLisandro Dalcin ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr); 161407b0a1fcSMatthew G Knepley ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); 161507b0a1fcSMatthew G Knepley ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr); 161643eeeb2dSStefano Zampini ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr); 161743eeeb2dSStefano Zampini ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr); 161843eeeb2dSStefano Zampini ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr); 161943eeeb2dSStefano Zampini ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr); 162007b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr); 162107b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); 162207b0a1fcSMatthew G Knepley for (v = 0; v < vEndB-vStartB; ++v) { 162343eeeb2dSStefano Zampini PetscInt offA, offB; 162443eeeb2dSStefano Zampini 162543eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr); 162643eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr); 162707b0a1fcSMatthew G Knepley for (d = 0; d < spaceDim; ++d) { 162843eeeb2dSStefano Zampini coordsB[offB+d] = coordsA[offA+d]; 162943eeeb2dSStefano Zampini } 163043eeeb2dSStefano Zampini } 163143eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 163243eeeb2dSStefano Zampini PetscInt c; 163343eeeb2dSStefano Zampini 163443eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 163543eeeb2dSStefano Zampini PetscInt dof, offA, offB; 163643eeeb2dSStefano Zampini 163743eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr); 163843eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr); 163943eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 1640580bdb30SBarry Smith ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr); 164107b0a1fcSMatthew G Knepley } 164207b0a1fcSMatthew G Knepley } 164307b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr); 164407b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); 164507b0a1fcSMatthew G Knepley ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr); 164607b0a1fcSMatthew G Knepley ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); 164707b0a1fcSMatthew G Knepley PetscFunctionReturn(0); 164807b0a1fcSMatthew G Knepley } 16495c386225SMatthew G. Knepley 16504e3744c5SMatthew G. Knepley /*@ 16514e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 16524e3744c5SMatthew G. Knepley 1653d083f849SBarry Smith Collective on dm 16544e3744c5SMatthew G. Knepley 16554e3744c5SMatthew G. Knepley Input Parameter: 16564e3744c5SMatthew G. Knepley . dm - The complete DMPlex object 16574e3744c5SMatthew G. Knepley 16584e3744c5SMatthew G. Knepley Output Parameter: 16594e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices 16604e3744c5SMatthew G. Knepley 16614e3744c5SMatthew G. Knepley Level: intermediate 16624e3744c5SMatthew G. Knepley 166395452b02SPatrick Sanan Notes: 166495452b02SPatrick Sanan It does not copy over the coordinates. 166543eeeb2dSStefano Zampini 16669ade3219SVaclav Hapla Developer Notes: 16679ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 16689ade3219SVaclav Hapla 166943eeeb2dSStefano Zampini .seealso: DMPlexInterpolate(), DMPlexCreateFromCellList(), DMPlexCopyCoordinates() 16704e3744c5SMatthew G. Knepley @*/ 16714e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 16724e3744c5SMatthew G. Knepley { 1673827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 16744e3744c5SMatthew G. Knepley DM udm; 1675c9f63434SStefano Zampini PetscInt dim, vStart, vEnd, cStart, cEnd, cMax, c, maxConeSize = 0, *cone; 16764e3744c5SMatthew G. Knepley PetscErrorCode ierr; 16774e3744c5SMatthew G. Knepley 16784e3744c5SMatthew G. Knepley PetscFunctionBegin; 167943eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 168043eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 1681c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1682827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1683827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1684827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1685827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 16864e3744c5SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 1687595d4abbSMatthew G. Knepley *dmUnint = dm; 1688595d4abbSMatthew G. Knepley PetscFunctionReturn(0); 16894e3744c5SMatthew G. Knepley } 1690595d4abbSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1691595d4abbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1692c9f63434SStefano Zampini ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 16934e3744c5SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr); 16944e3744c5SMatthew G. Knepley ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr); 1695c73cfb54SMatthew G. Knepley ierr = DMSetDimension(udm, dim);CHKERRQ(ierr); 16964e3744c5SMatthew G. Knepley ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr); 16974e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1698595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 16994e3744c5SMatthew G. Knepley 17004e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17014e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 17024e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 17034e3744c5SMatthew G. Knepley 17044e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 17054e3744c5SMatthew G. Knepley } 17064e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17074e3744c5SMatthew G. Knepley ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr); 1708595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 17094e3744c5SMatthew G. Knepley } 17104e3744c5SMatthew G. Knepley ierr = DMSetUp(udm);CHKERRQ(ierr); 1711785e854fSJed Brown ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr); 17124e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1713595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 17144e3744c5SMatthew G. Knepley 17154e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17164e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 17174e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 17184e3744c5SMatthew G. Knepley 17194e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 17204e3744c5SMatthew G. Knepley } 17214e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17224e3744c5SMatthew G. Knepley ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr); 17234e3744c5SMatthew G. Knepley } 17244e3744c5SMatthew G. Knepley ierr = PetscFree(cone);CHKERRQ(ierr); 1725c9f63434SStefano Zampini ierr = DMPlexSetHybridBounds(udm, cMax, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 17264e3744c5SMatthew G. Knepley ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr); 17274e3744c5SMatthew G. Knepley ierr = DMPlexStratify(udm);CHKERRQ(ierr); 17285c7de58aSMatthew G. Knepley /* Reduce SF */ 17295c7de58aSMatthew G. Knepley { 17305c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 17315c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 17325c7de58aSMatthew G. Knepley const PetscInt *localPoints; 17335c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 17345c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 17355c7de58aSMatthew G. Knepley PetscInt vEnd, numRoots, numLeaves, l; 17365c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 17375c7de58aSMatthew G. Knepley PetscErrorCode ierr; 17385c7de58aSMatthew G. Knepley 17395c7de58aSMatthew G. Knepley /* Get original SF information */ 17405c7de58aSMatthew G. Knepley ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 17415c7de58aSMatthew G. Knepley ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr); 17425c7de58aSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr); 17435c7de58aSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 17445c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 17455c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++; 17465c7de58aSMatthew G. Knepley /* Fill in leaves */ 17475c7de58aSMatthew G. Knepley if (vEnd >= 0) { 17485c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr); 17495c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr); 17505c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 17515c7de58aSMatthew G. Knepley if (localPoints[l] < vEnd) { 17525c7de58aSMatthew G. Knepley localPointsUn[n] = localPoints[l]; 17535c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 17545c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 17555c7de58aSMatthew G. Knepley ++n; 17565c7de58aSMatthew G. Knepley } 17575c7de58aSMatthew G. Knepley } 17585c7de58aSMatthew G. Knepley if (n != numLeavesUn) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn); 17595c7de58aSMatthew G. Knepley ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr); 17605c7de58aSMatthew G. Knepley } 17615c7de58aSMatthew G. Knepley } 176243eeeb2dSStefano Zampini { 176343eeeb2dSStefano Zampini PetscBool isper; 176443eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 176543eeeb2dSStefano Zampini const DMBoundaryType *bd; 176643eeeb2dSStefano Zampini 176743eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 176843eeeb2dSStefano Zampini ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr); 176943eeeb2dSStefano Zampini } 1770827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1771827c4036SVaclav Hapla { 1772d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) udm->data; 1773827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1774827c4036SVaclav Hapla } 17754e3744c5SMatthew G. Knepley *dmUnint = udm; 17764e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 17774e3744c5SMatthew G. Knepley } 1778a7748839SVaclav Hapla 1779a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1780a7748839SVaclav Hapla { 1781a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1782a7748839SVaclav Hapla MPI_Comm comm; 1783a7748839SVaclav Hapla PetscErrorCode ierr; 1784a7748839SVaclav Hapla 1785a7748839SVaclav Hapla PetscFunctionBegin; 1786a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1787a7748839SVaclav Hapla ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1788a7748839SVaclav Hapla ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1789a7748839SVaclav Hapla 1790a7748839SVaclav Hapla if (depth == dim) { 1791a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1792a7748839SVaclav Hapla if (!dim) goto finish; 1793a7748839SVaclav Hapla 1794a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 1795a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr); 1796a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1797a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1798a7748839SVaclav Hapla if (coneSize) { 1799a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1800a7748839SVaclav Hapla goto finish; 1801a7748839SVaclav Hapla } 1802a7748839SVaclav Hapla } 1803a7748839SVaclav Hapla 1804a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1805a7748839SVaclav Hapla for (h=0; h<dim; h++) { 1806a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 1807a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1808a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1809a7748839SVaclav Hapla if (!coneSize) { 1810a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1811a7748839SVaclav Hapla goto finish; 1812a7748839SVaclav Hapla } 1813a7748839SVaclav Hapla } 1814a7748839SVaclav Hapla } 1815a7748839SVaclav Hapla } else if (depth == 1) { 1816a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1817a7748839SVaclav Hapla } else { 1818a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1819a7748839SVaclav Hapla } 1820a7748839SVaclav Hapla finish: 1821a7748839SVaclav Hapla PetscFunctionReturn(0); 1822a7748839SVaclav Hapla } 1823a7748839SVaclav Hapla 1824a7748839SVaclav Hapla /*@ 18259ade3219SVaclav Hapla DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated. 1826a7748839SVaclav Hapla 1827a7748839SVaclav Hapla Not Collective 1828a7748839SVaclav Hapla 1829a7748839SVaclav Hapla Input Parameter: 1830a7748839SVaclav Hapla . dm - The DM object 1831a7748839SVaclav Hapla 1832a7748839SVaclav Hapla Output Parameter: 1833a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1834a7748839SVaclav Hapla 1835a7748839SVaclav Hapla Level: intermediate 1836a7748839SVaclav Hapla 1837a7748839SVaclav Hapla Notes: 18389ade3219SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this is NOT collective 18399ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1840a7748839SVaclav Hapla However, DMPlexInterpolate() guarantees the result is the same on all. 18419ade3219SVaclav Hapla 1842a7748839SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED. 1843a7748839SVaclav Hapla 18449ade3219SVaclav Hapla Developer Notes: 18459ade3219SVaclav Hapla Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID. 18469ade3219SVaclav Hapla 18479ade3219SVaclav Hapla If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called. 18489ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 18499ade3219SVaclav Hapla DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL. 18509ade3219SVaclav Hapla 18519ade3219SVaclav Hapla If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated. 18529ade3219SVaclav Hapla 18539ade3219SVaclav Hapla DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL, 18549ade3219SVaclav Hapla and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 18559ade3219SVaclav Hapla 1856a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective() 1857a7748839SVaclav Hapla @*/ 1858a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1859a7748839SVaclav Hapla { 1860a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1861a7748839SVaclav Hapla PetscErrorCode ierr; 1862a7748839SVaclav Hapla 1863a7748839SVaclav Hapla PetscFunctionBegin; 1864a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1865a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1866a7748839SVaclav Hapla if (plex->interpolated < 0) { 1867a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr); 1868a7748839SVaclav Hapla } else { 1869a7748839SVaclav Hapla #if defined (PETSC_USE_DEBUG) 1870a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1871a7748839SVaclav Hapla 1872a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr); 18737fc06600SVaclav Hapla if (flg != plex->interpolated) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Stashed DMPlexInterpolatedFlag %s is inconsistent with current %s", DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[flg]); 1874a7748839SVaclav Hapla #endif 1875a7748839SVaclav Hapla } 1876a7748839SVaclav Hapla *interpolated = plex->interpolated; 1877a7748839SVaclav Hapla PetscFunctionReturn(0); 1878a7748839SVaclav Hapla } 1879a7748839SVaclav Hapla 1880a7748839SVaclav Hapla /*@ 18819ade3219SVaclav Hapla DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner). 1882a7748839SVaclav Hapla 18832666ff3cSVaclav Hapla Collective 1884a7748839SVaclav Hapla 1885a7748839SVaclav Hapla Input Parameter: 1886a7748839SVaclav Hapla . dm - The DM object 1887a7748839SVaclav Hapla 1888a7748839SVaclav Hapla Output Parameter: 1889a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1890a7748839SVaclav Hapla 1891a7748839SVaclav Hapla Level: intermediate 1892a7748839SVaclav Hapla 1893a7748839SVaclav Hapla Notes: 18949ade3219SVaclav Hapla Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks. 18959ade3219SVaclav Hapla 18969ade3219SVaclav Hapla This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks. 18979ade3219SVaclav Hapla 18989ade3219SVaclav Hapla Developer Notes: 18999ade3219SVaclav Hapla Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID. 19009ade3219SVaclav Hapla 19019ade3219SVaclav Hapla If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated. 19029ade3219SVaclav Hapla MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 19039ade3219SVaclav Hapla if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED, 19049ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 19059ade3219SVaclav Hapla 19069ade3219SVaclav Hapla If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective. 1907a7748839SVaclav Hapla 1908a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated() 1909a7748839SVaclav Hapla @*/ 1910a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 1911a7748839SVaclav Hapla { 1912a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1913a7748839SVaclav Hapla PetscBool debug=PETSC_FALSE; 1914a7748839SVaclav Hapla PetscErrorCode ierr; 1915a7748839SVaclav Hapla 1916a7748839SVaclav Hapla PetscFunctionBegin; 1917a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1918a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1919a7748839SVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr); 1920a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1921a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1922a7748839SVaclav Hapla MPI_Comm comm; 1923a7748839SVaclav Hapla 1924a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1925a7748839SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr); 1926a7748839SVaclav Hapla ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRQ(ierr); 1927a7748839SVaclav Hapla ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRQ(ierr); 1928a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1929a7748839SVaclav Hapla if (debug) { 1930a7748839SVaclav Hapla PetscMPIInt rank; 1931a7748839SVaclav Hapla 1932a7748839SVaclav Hapla ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1933a7748839SVaclav Hapla ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr); 1934a7748839SVaclav Hapla ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr); 1935a7748839SVaclav Hapla } 1936a7748839SVaclav Hapla } 1937a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 1938a7748839SVaclav Hapla PetscFunctionReturn(0); 1939a7748839SVaclav Hapla } 1940