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; 10263be36e83SMatthew G. Knepley PetscInt supportSize, s, off = 0, idx = 0; 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); 10333be36e83SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 10343be36e83SMatthew G. Knepley ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 10353be36e83SMatthew G. Knepley if (candidates) {ierr = PetscSectionGetOffset(candidateSection, p, &off);CHKERRQ(ierr);} 10363be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 10373be36e83SMatthew G. Knepley const PetscInt face = support[s]; 10383be36e83SMatthew G. Knepley const PetscInt *cone; 10393be36e83SMatthew G. Knepley PetscSFNode cpmin={-1,-1}, rp={-1,-1}; 10403be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 10413be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 10423be36e83SMatthew G. Knepley PetscHashIJKey key; 10433be36e83SMatthew G. Knepley 10443be36e83SMatthew G. Knepley /* Only add point once */ 10453be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Support face %D\n", rank, face);CHKERRQ(ierr);} 10463be36e83SMatthew G. Knepley key.i = p; 10473be36e83SMatthew G. Knepley key.j = face; 10483be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(faceHash, key, &f);CHKERRQ(ierr); 10493be36e83SMatthew G. Knepley if (f >= 0) continue; 10503be36e83SMatthew G. Knepley ierr = DMPlexConeIsShared(dm, face, &isShared);CHKERRQ(ierr); 10513be36e83SMatthew G. Knepley ierr = DMPlexGetConeMinimum(dm, face, &cpmin);CHKERRQ(ierr); 10523be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, p, &rp);CHKERRQ(ierr); 10533be36e83SMatthew G. Knepley if (debug) { 10543be36e83SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] Face point %D is shared: %d\n", rank, face, (int) isShared);CHKERRQ(ierr); 10553be36e83SMatthew 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); 10563be36e83SMatthew G. Knepley } 10573be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 10583be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 10593be36e83SMatthew G. Knepley if (candidates) { 10603be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Adding shared face %D at idx %D\n[%d] ", rank, face, idx, rank);CHKERRQ(ierr);} 10613be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10623be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 10633be36e83SMatthew G. Knepley candidates[off+idx].rank = -1; 10643be36e83SMatthew G. Knepley candidates[off+idx++].index = coneSize-1; 10653be36e83SMatthew G. Knepley candidates[off+idx].rank = rank; 10663be36e83SMatthew G. Knepley candidates[off+idx++].index = face; 10673be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 10683be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 10693be36e83SMatthew G. Knepley 10703be36e83SMatthew G. Knepley if (cp == p) continue; 10713be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx]);CHKERRQ(ierr); 10723be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index);CHKERRQ(ierr);} 10733be36e83SMatthew G. Knepley ++idx; 10743be36e83SMatthew G. Knepley } 10753be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "\n");CHKERRQ(ierr);} 10763be36e83SMatthew G. Knepley } else { 10773be36e83SMatthew G. Knepley /* Add cone size to section */ 10783be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %D\n", rank, face);CHKERRQ(ierr);} 10793be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10803be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 10813be36e83SMatthew G. Knepley ierr = PetscSectionAddDof(candidateSection, p, coneSize+1);CHKERRQ(ierr); 10823be36e83SMatthew G. Knepley } 10833be36e83SMatthew G. Knepley } 10843be36e83SMatthew G. Knepley } 10853be36e83SMatthew G. Knepley PetscFunctionReturn(0); 10863be36e83SMatthew G. Knepley } 10873be36e83SMatthew G. Knepley 10882e72742cSMatthew G. Knepley /*@ 10892e72742cSMatthew G. Knepley DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation 10902e72742cSMatthew G. Knepley 1091d083f849SBarry Smith Collective on dm 10922e72742cSMatthew G. Knepley 10932e72742cSMatthew G. Knepley Input Parameters: 10942e72742cSMatthew G. Knepley + dm - The interpolated DM 10952e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points 10962e72742cSMatthew G. Knepley 10972e72742cSMatthew G. Knepley Output Parameter: 10982e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points 10992e72742cSMatthew G. Knepley 1100f0cfc026SVaclav Hapla Level: developer 11012e72742cSMatthew G. Knepley 11022e72742cSMatthew 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 11032e72742cSMatthew G. Knepley 11042e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate() 11052e72742cSMatthew G. Knepley @*/ 1106e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 11072e72742cSMatthew G. Knepley { 11083be36e83SMatthew G. Knepley MPI_Comm comm; 11093be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 11103be36e83SMatthew G. Knepley PetscHMapI claimshash; 11113be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 11123be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 11132e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 11142e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 11153be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 11163be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 11173be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 1118f0cfc026SVaclav Hapla PetscMPIInt rank; 11192e72742cSMatthew G. Knepley PetscErrorCode ierr; 11202e72742cSMatthew G. Knepley 11212e72742cSMatthew G. Knepley PetscFunctionBegin; 1122f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11233be36e83SMatthew G. Knepley PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 3); 1124f0cfc026SVaclav Hapla ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr); 1125f0cfc026SVaclav Hapla if (!flg) PetscFunctionReturn(0); 11263be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 11273be36e83SMatthew G. Knepley ierr = DMSetPointSF(dm, pointSF);CHKERRQ(ierr); 11283be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 11293be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 11303be36e83SMatthew G. Knepley ierr = DMPlexGetOverlap(dm, &ov);CHKERRQ(ierr); 11313be36e83SMatthew G. Knepley if (ov) SETERRQ(comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 11323be36e83SMatthew G. Knepley ierr = PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug);CHKERRQ(ierr); 11332e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view");CHKERRQ(ierr); 11342e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view");CHKERRQ(ierr); 113525afeb17SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 11363be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 11373be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints);CHKERRQ(ierr); 11383be36e83SMatthew G. Knepley if (Nr < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 11393be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&remoteHash);CHKERRQ(ierr); 11403be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11413be36e83SMatthew G. Knepley PetscHashIJKey key; 11422e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 11432e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 11443be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(remoteHash, key, l);CHKERRQ(ierr); 11457bffde78SMichael Lange } 114666aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 11472e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 11482e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 11493be36e83SMatthew G. Knepley ierr = IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree);CHKERRQ(ierr); 11503be36e83SMatthew G. Knepley /* 11513be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 11523be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 11533be36e83SMatthew G. Knepley \begin{itemize} 11543be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 11553be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 11563be36e83SMatthew G. Knepley \end{itemize} 11573be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 11583be36e83SMatthew 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 11593be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 11603be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 11613be36e83SMatthew G. Knepley */ 11623be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 11633be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 11643be36e83SMatthew G. Knepley The array holds candidate shared faces, each face is refered to by the leaf point */ 11653be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateSection);CHKERRQ(ierr); 11663be36e83SMatthew G. Knepley ierr = PetscSectionSetChart(candidateSection, 0, Nr);CHKERRQ(ierr); 11677bffde78SMichael Lange { 11683be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 11692e72742cSMatthew G. Knepley 11703be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&faceHash);CHKERRQ(ierr); 11713be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11723be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 11732e72742cSMatthew G. Knepley 11743be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 11753be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug);CHKERRQ(ierr); 11762e72742cSMatthew G. Knepley } 11773be36e83SMatthew G. Knepley ierr = PetscHMapIJClear(faceHash);CHKERRQ(ierr); 11787bffde78SMichael Lange ierr = PetscSectionSetUp(candidateSection);CHKERRQ(ierr); 11797bffde78SMichael Lange ierr = PetscSectionGetStorageSize(candidateSection, &candidatesSize);CHKERRQ(ierr); 11807bffde78SMichael Lange ierr = PetscMalloc1(candidatesSize, &candidates);CHKERRQ(ierr); 11813be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 11823be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 11832e72742cSMatthew G. Knepley 11843be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 11853be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug);CHKERRQ(ierr); 11862e72742cSMatthew G. Knepley } 11873be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&faceHash);CHKERRQ(ierr); 11883be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 11897bffde78SMichael Lange } 11903be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateSection, "Candidate Section");CHKERRQ(ierr); 11912e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view");CHKERRQ(ierr); 11923be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates);CHKERRQ(ierr); 11933be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 11942e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 11957bffde78SMichael Lange { 11967bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 11977bffde78SMichael Lange PetscInt *remoteOffsets; 11982e72742cSMatthew G. Knepley 11997bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 12007bffde78SMichael Lange ierr = PetscSFCreateInverseSF(sfMulti, &sfInverse);CHKERRQ(ierr); 12013be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateRemoteSection);CHKERRQ(ierr); 12023be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection);CHKERRQ(ierr); 12033be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates);CHKERRQ(ierr); 12043be36e83SMatthew G. Knepley ierr = PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize);CHKERRQ(ierr); 12057bffde78SMichael Lange ierr = PetscMalloc1(candidatesRemoteSize, &candidatesRemote);CHKERRQ(ierr); 12067bffde78SMichael Lange ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr); 12077bffde78SMichael Lange ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr); 12087bffde78SMichael Lange ierr = PetscSFDestroy(&sfInverse);CHKERRQ(ierr); 12097bffde78SMichael Lange ierr = PetscSFDestroy(&sfCandidates);CHKERRQ(ierr); 12107bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 12112e72742cSMatthew G. Knepley 12123be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section");CHKERRQ(ierr); 12133be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view");CHKERRQ(ierr); 12143be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote);CHKERRQ(ierr); 12157bffde78SMichael Lange } 12163be36e83SMatthew 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 */ 12177bffde78SMichael Lange { 12183be36e83SMatthew G. Knepley PetscHashIJKLRemote faceTable; 12193be36e83SMatthew G. Knepley PetscInt idx, idx2; 12203be36e83SMatthew G. Knepley 12213be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteCreate(&faceTable);CHKERRQ(ierr); 12222e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 12233be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 12242e72742cSMatthew G. Knepley PetscInt deg; 12253be36e83SMatthew G. Knepley 12262e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 12272e72742cSMatthew G. Knepley PetscInt offset, dof, d; 12282e72742cSMatthew G. Knepley 12293be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx, &dof);CHKERRQ(ierr); 12303be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx, &offset);CHKERRQ(ierr); 12313be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 12322e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12333be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 12343be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 12353be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx+1]; 12363be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 12373be36e83SMatthew G. Knepley PetscSFNode fcp0; 12383be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 12392e72742cSMatthew G. Knepley const PetscInt *join = NULL; 12403be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 12413be36e83SMatthew G. Knepley PetscHashIter iter; 12423be36e83SMatthew G. Knepley PetscBool missing; 12432e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 12442e72742cSMatthew G. Knepley 1245*66e92ce5SVaclav 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);} 1246*66e92ce5SVaclav 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); 12473be36e83SMatthew G. Knepley fcp0.rank = rank; 12483be36e83SMatthew G. Knepley fcp0.index = r; 12493be36e83SMatthew G. Knepley d += Np; 12503be36e83SMatthew G. Knepley /* Put remote face in hash table */ 12513be36e83SMatthew G. Knepley key.i = fcp0; 12523be36e83SMatthew G. Knepley key.j = fcone[0]; 12533be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 12543be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 12553be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 12563be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 12573be36e83SMatthew G. Knepley if (missing) { 12583be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Setting remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 12593be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 12603be36e83SMatthew G. Knepley } else { 12613be36e83SMatthew G. Knepley PetscSFNode oface; 12623be36e83SMatthew G. Knepley 12633be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 12643be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 12653be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 12663be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 12673be36e83SMatthew G. Knepley } 12683be36e83SMatthew G. Knepley } 12693be36e83SMatthew G. Knepley /* Check for local face */ 12702e72742cSMatthew G. Knepley points[0] = r; 12713be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 12723be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p]); 12733be36e83SMatthew G. Knepley if (ierr) break; /* We got a point not in our overlap */ 12743be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking local candidate %D\n", rank, points[p]);CHKERRQ(ierr);} 12757bffde78SMichael Lange } 12762e72742cSMatthew G. Knepley if (ierr) continue; 12773be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 12787bffde78SMichael Lange if (joinSize == 1) { 12793be36e83SMatthew G. Knepley PetscSFNode lface; 12803be36e83SMatthew G. Knepley PetscSFNode oface; 12813be36e83SMatthew G. Knepley 12823be36e83SMatthew G. Knepley /* Always replace with local face */ 12833be36e83SMatthew G. Knepley lface.rank = rank; 12843be36e83SMatthew G. Knepley lface.index = join[0]; 12853be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 12863be36e83SMatthew 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);} 12873be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, lface);CHKERRQ(ierr); 12887bffde78SMichael Lange } 12893be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 12903be36e83SMatthew G. Knepley } 12913be36e83SMatthew G. Knepley } 12923be36e83SMatthew G. Knepley /* Put back faces for this root */ 12933be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 12943be36e83SMatthew G. Knepley PetscInt offset, dof, d; 12953be36e83SMatthew G. Knepley 12963be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx2, &dof);CHKERRQ(ierr); 12973be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx2, &offset);CHKERRQ(ierr); 12983be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 12993be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 13003be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 13013be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 13023be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 13033be36e83SMatthew G. Knepley PetscSFNode fcp0; 13043be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 13053be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 13063be36e83SMatthew G. Knepley PetscHashIter iter; 13073be36e83SMatthew G. Knepley PetscBool missing; 13083be36e83SMatthew G. Knepley 13093be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Entering face at (%D, %D)\n", rank, r, idx);CHKERRQ(ierr);} 13103be36e83SMatthew G. Knepley if (Np > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np); 13113be36e83SMatthew G. Knepley fcp0.rank = rank; 13123be36e83SMatthew G. Knepley fcp0.index = r; 13133be36e83SMatthew G. Knepley d += Np; 13143be36e83SMatthew G. Knepley /* Find remote face in hash table */ 13153be36e83SMatthew G. Knepley key.i = fcp0; 13163be36e83SMatthew G. Knepley key.j = fcone[0]; 13173be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 13183be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 13193be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 13203be36e83SMatthew 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);} 13213be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 13223be36e83SMatthew G. Knepley if (missing) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an assoicated face", r, idx2); 13233be36e83SMatthew G. Knepley else {ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]);CHKERRQ(ierr);} 13247bffde78SMichael Lange } 13257bffde78SMichael Lange } 13267bffde78SMichael Lange } 13272e72742cSMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL);CHKERRQ(ierr);} 13283be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteDestroy(&faceTable);CHKERRQ(ierr); 13297bffde78SMichael Lange } 13303be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 13317bffde78SMichael Lange { 13327bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 13337bffde78SMichael Lange PetscSFNode *remotePointsNew; 13342e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 13353be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 13362e72742cSMatthew G. Knepley 13373be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 13387bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 13393be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &claimSection);CHKERRQ(ierr); 13403be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection);CHKERRQ(ierr); 13413be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims);CHKERRQ(ierr); 13422e72742cSMatthew G. Knepley ierr = PetscSectionGetStorageSize(claimSection, &claimsSize);CHKERRQ(ierr); 13432e72742cSMatthew G. Knepley ierr = PetscMalloc1(claimsSize, &claims);CHKERRQ(ierr); 13443be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 13457bffde78SMichael Lange ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr); 13467bffde78SMichael Lange ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr); 13477bffde78SMichael Lange ierr = PetscSFDestroy(&sfClaims);CHKERRQ(ierr); 13487bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 13493be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) claimSection, "Claim Section");CHKERRQ(ierr); 13502e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view");CHKERRQ(ierr); 13513be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims);CHKERRQ(ierr); 13523be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 13533be36e83SMatthew 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 */ 1354e8f14785SLisandro Dalcin ierr = PetscHMapICreate(&claimshash);CHKERRQ(ierr); 13553be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 13563be36e83SMatthew G. Knepley PetscInt dof, off, d; 13572e72742cSMatthew G. Knepley 13583be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %D\n", rank, r);CHKERRQ(ierr);} 13593be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateSection, r, &dof);CHKERRQ(ierr); 13603be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateSection, r, &off);CHKERRQ(ierr); 13612e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 13623be36e83SMatthew G. Knepley if (claims[off+d].rank >= 0) { 13633be36e83SMatthew G. Knepley const PetscInt faceInd = off+d; 13643be36e83SMatthew G. Knepley const PetscInt Np = candidates[off+d].index; 13652e72742cSMatthew G. Knepley const PetscInt *join = NULL; 13662e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 13672e72742cSMatthew G. Knepley 13683be36e83SMatthew 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);} 13693be36e83SMatthew G. Knepley points[0] = r; 13703be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[0]);CHKERRQ(ierr);} 13713be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 13723be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1]);CHKERRQ(ierr); 13733be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[c+1]);CHKERRQ(ierr);} 13742e72742cSMatthew G. Knepley } 13753be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 13762e72742cSMatthew G. Knepley if (joinSize == 1) { 13773be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 13783be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %D for non-remote partner\n", rank, join[0]);CHKERRQ(ierr);} 13793be36e83SMatthew G. Knepley } else { 13803be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Found local face %D\n", rank, join[0]);CHKERRQ(ierr);} 13812e72742cSMatthew G. Knepley ierr = PetscHMapISet(claimshash, join[0], faceInd);CHKERRQ(ierr); 13822e72742cSMatthew G. Knepley } 13833be36e83SMatthew G. Knepley } else { 13843be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank);CHKERRQ(ierr);} 13853be36e83SMatthew G. Knepley } 13863be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 13873be36e83SMatthew G. Knepley } else { 13883be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] No claim for point %D\n", rank, r);CHKERRQ(ierr);} 13893be36e83SMatthew G. Knepley d += claims[off+d].index+1; 13907bffde78SMichael Lange } 13917bffde78SMichael Lange } 13923be36e83SMatthew G. Knepley } 13933be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 13943be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 13953be36e83SMatthew G. Knepley ierr = PetscHMapIGetSize(claimshash, &NlNew);CHKERRQ(ierr); 13967bffde78SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 13973be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &localPointsNew);CHKERRQ(ierr); 13983be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &remotePointsNew);CHKERRQ(ierr); 13993be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 14003be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 14013be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 14023be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 14037bffde78SMichael Lange } 14043be36e83SMatthew G. Knepley p = Nl; 1405e8f14785SLisandro Dalcin ierr = PetscHMapIGetKeys(claimshash, &p, localPointsNew);CHKERRQ(ierr); 14063be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 14073be36e83SMatthew G. Knepley ierr = PetscSortInt(NlNew, &localPointsNew[Nl]);CHKERRQ(ierr); 14083be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 14093be36e83SMatthew G. Knepley PetscInt off; 14103be36e83SMatthew G. Knepley ierr = PetscHMapIGet(claimshash, localPointsNew[p], &off);CHKERRQ(ierr); 14113be36e83SMatthew 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); 14123be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 14137bffde78SMichael Lange } 14143be36e83SMatthew G. Knepley ierr = PetscSFCreate(comm, &sfPointNew);CHKERRQ(ierr); 14153be36e83SMatthew G. Knepley ierr = PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 14163be36e83SMatthew G. Knepley ierr = PetscSFSetUp(sfPointNew);CHKERRQ(ierr); 14177bffde78SMichael Lange ierr = DMSetPointSF(dm, sfPointNew);CHKERRQ(ierr); 14183be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view");CHKERRQ(ierr); 14197bffde78SMichael Lange ierr = PetscSFDestroy(&sfPointNew);CHKERRQ(ierr); 1420e8f14785SLisandro Dalcin ierr = PetscHMapIDestroy(&claimshash);CHKERRQ(ierr); 14217bffde78SMichael Lange } 14223be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&remoteHash);CHKERRQ(ierr); 14237bffde78SMichael Lange ierr = PetscSectionDestroy(&candidateSection);CHKERRQ(ierr); 14243be36e83SMatthew G. Knepley ierr = PetscSectionDestroy(&candidateRemoteSection);CHKERRQ(ierr); 14257bffde78SMichael Lange ierr = PetscSectionDestroy(&claimSection);CHKERRQ(ierr); 14267bffde78SMichael Lange ierr = PetscFree(candidates);CHKERRQ(ierr); 14277bffde78SMichael Lange ierr = PetscFree(candidatesRemote);CHKERRQ(ierr); 14287bffde78SMichael Lange ierr = PetscFree(claims);CHKERRQ(ierr); 142925afeb17SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 14307bffde78SMichael Lange PetscFunctionReturn(0); 14317bffde78SMichael Lange } 14327bffde78SMichael Lange 1433248eb259SVaclav Hapla /*@ 143480330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 143580330477SMatthew G. Knepley 1436d083f849SBarry Smith Collective on dm 143780330477SMatthew G. Knepley 1438e56d480eSMatthew G. Knepley Input Parameters: 1439e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices 144010a67516SMatthew G. Knepley - dmInt - The interpolated DM 144180330477SMatthew G. Knepley 144280330477SMatthew G. Knepley Output Parameter: 14434e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object 144480330477SMatthew G. Knepley 144580330477SMatthew G. Knepley Level: intermediate 144680330477SMatthew G. Knepley 144795452b02SPatrick Sanan Notes: 144895452b02SPatrick Sanan It does not copy over the coordinates. 144943eeeb2dSStefano Zampini 14509ade3219SVaclav Hapla Developer Notes: 14519ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL. 14529ade3219SVaclav Hapla 145343eeeb2dSStefano Zampini .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellList(), DMPlexCopyCoordinates() 145480330477SMatthew G. Knepley @*/ 14559f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 14569f074e33SMatthew G Knepley { 1457a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 14589a5b13a2SMatthew G Knepley DM idm, odm = dm; 14597bffde78SMichael Lange PetscSF sfPoint; 14602e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 146110a67516SMatthew G. Knepley const char *name; 1462b325530aSVaclav Hapla PetscBool flg=PETSC_TRUE; 14639f074e33SMatthew G Knepley PetscErrorCode ierr; 14649f074e33SMatthew G Knepley 14659f074e33SMatthew G Knepley PetscFunctionBegin; 146610a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 146710a67516SMatthew G. Knepley PetscValidPointer(dmInt, 2); 1468a72f3261SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 14692e1b13c2SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1470c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1471827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1472827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1473827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 147476b791aaSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 147576b791aaSMatthew G. Knepley idm = dm; 1476b21b8912SMatthew G. Knepley } else { 14779a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 14789a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 147910a67516SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 14809a5b13a2SMatthew G Knepley ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 1481c73cfb54SMatthew G. Knepley ierr = DMSetDimension(idm, dim);CHKERRQ(ierr); 14827bffde78SMichael Lange if (depth > 0) { 14837bffde78SMichael Lange ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr); 14847bffde78SMichael Lange ierr = DMGetPointSF(odm, &sfPoint);CHKERRQ(ierr); 148594488200SVaclav Hapla { 14863be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 148794488200SVaclav Hapla PetscInt nroots; 148894488200SVaclav Hapla ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 148994488200SVaclav Hapla if (nroots >= 0) {ierr = DMPlexInterpolatePointSF(idm, sfPoint);CHKERRQ(ierr);} 149094488200SVaclav Hapla } 14917bffde78SMichael Lange } 14929a5b13a2SMatthew G Knepley if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);} 14939a5b13a2SMatthew G Knepley odm = idm; 14949f074e33SMatthew G Knepley } 149510a67516SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 149610a67516SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) idm, name);CHKERRQ(ierr); 149710a67516SMatthew G. Knepley ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr); 14985d80c0bfSVaclav Hapla ierr = DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE);CHKERRQ(ierr); 1499b325530aSVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL);CHKERRQ(ierr); 150027d0e99aSVaclav Hapla if (flg) {ierr = DMPlexOrientInterface_Internal(idm);CHKERRQ(ierr);} 150184699f70SSatish Balay } 150243eeeb2dSStefano Zampini { 150343eeeb2dSStefano Zampini PetscBool isper; 150443eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 150543eeeb2dSStefano Zampini const DMBoundaryType *bd; 150643eeeb2dSStefano Zampini 150743eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 150843eeeb2dSStefano Zampini ierr = DMSetPeriodicity(idm,isper,maxCell,L,bd);CHKERRQ(ierr); 150943eeeb2dSStefano Zampini } 1510827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1511827c4036SVaclav Hapla { 1512d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) idm->data; 1513827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1514827c4036SVaclav Hapla } 15159a5b13a2SMatthew G Knepley *dmInt = idm; 1516a72f3261SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 15179f074e33SMatthew G Knepley PetscFunctionReturn(0); 15189f074e33SMatthew G Knepley } 151907b0a1fcSMatthew G Knepley 152080330477SMatthew G. Knepley /*@ 152180330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 152280330477SMatthew G. Knepley 1523d083f849SBarry Smith Collective on dmA 152480330477SMatthew G. Knepley 152580330477SMatthew G. Knepley Input Parameter: 152680330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates 152780330477SMatthew G. Knepley 152880330477SMatthew G. Knepley Output Parameter: 152980330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates 153080330477SMatthew G. Knepley 153180330477SMatthew G. Knepley Level: intermediate 153280330477SMatthew G. Knepley 153380330477SMatthew G. Knepley Note: This is typically used when adding pieces other than vertices to a mesh 153480330477SMatthew G. Knepley 153565f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 153680330477SMatthew G. Knepley @*/ 153707b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 153807b0a1fcSMatthew G Knepley { 153907b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 154043eeeb2dSStefano Zampini VecType vtype; 154107b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 154207b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 15430bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 154490a8aa44SJed Brown PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE, cdim; 154543eeeb2dSStefano Zampini PetscBool lc = PETSC_FALSE; 154607b0a1fcSMatthew G Knepley PetscErrorCode ierr; 154707b0a1fcSMatthew G Knepley 154807b0a1fcSMatthew G Knepley PetscFunctionBegin; 154943eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 155043eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 155176b791aaSMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 155290a8aa44SJed Brown ierr = DMGetCoordinateDim(dmA, &cdim);CHKERRQ(ierr); 155390a8aa44SJed Brown ierr = DMSetCoordinateDim(dmB, cdim);CHKERRQ(ierr); 155407b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr); 155507b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr); 155607b0a1fcSMatthew 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); 155743eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr); 155843eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr); 155969d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr); 156069d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr); 1561972bc18aSToby Isaac if (coordSectionA == coordSectionB) PetscFunctionReturn(0); 15620bedd6beSMatthew G. Knepley ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr); 15630bedd6beSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 15640bedd6beSMatthew G. Knepley if (Nf > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf); 1565df26b574SMatthew G. Knepley if (!coordSectionB) { 1566df26b574SMatthew G. Knepley PetscInt dim; 1567df26b574SMatthew G. Knepley 1568df26b574SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr); 1569df26b574SMatthew G. Knepley ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr); 1570df26b574SMatthew G. Knepley ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr); 1571df26b574SMatthew G. Knepley ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr); 1572df26b574SMatthew G. Knepley } 157307b0a1fcSMatthew G Knepley ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); 157407b0a1fcSMatthew G Knepley ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr); 157507b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr); 157643eeeb2dSStefano Zampini ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr); 157743eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 1578367003a6SStefano 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); 157943eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 158043eeeb2dSStefano Zampini cE = vEndB; 158143eeeb2dSStefano Zampini lc = PETSC_TRUE; 158243eeeb2dSStefano Zampini } else { 158343eeeb2dSStefano Zampini cS = vStartB; 158443eeeb2dSStefano Zampini cE = vEndB; 158543eeeb2dSStefano Zampini } 158643eeeb2dSStefano Zampini ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr); 158707b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 158807b0a1fcSMatthew G Knepley ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr); 158907b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr); 159007b0a1fcSMatthew G Knepley } 159143eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 159243eeeb2dSStefano Zampini PetscInt c; 159343eeeb2dSStefano Zampini 159443eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 159543eeeb2dSStefano Zampini PetscInt dof; 159643eeeb2dSStefano Zampini 159743eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 159843eeeb2dSStefano Zampini ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr); 159943eeeb2dSStefano Zampini ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr); 160043eeeb2dSStefano Zampini } 160143eeeb2dSStefano Zampini } 160207b0a1fcSMatthew G Knepley ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); 160307b0a1fcSMatthew G Knepley ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr); 160407b0a1fcSMatthew G Knepley ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr); 16058b9ced59SLisandro Dalcin ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr); 160607b0a1fcSMatthew G Knepley ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); 160707b0a1fcSMatthew G Knepley ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr); 160843eeeb2dSStefano Zampini ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr); 160943eeeb2dSStefano Zampini ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr); 161043eeeb2dSStefano Zampini ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr); 161143eeeb2dSStefano Zampini ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr); 161207b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr); 161307b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); 161407b0a1fcSMatthew G Knepley for (v = 0; v < vEndB-vStartB; ++v) { 161543eeeb2dSStefano Zampini PetscInt offA, offB; 161643eeeb2dSStefano Zampini 161743eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr); 161843eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr); 161907b0a1fcSMatthew G Knepley for (d = 0; d < spaceDim; ++d) { 162043eeeb2dSStefano Zampini coordsB[offB+d] = coordsA[offA+d]; 162143eeeb2dSStefano Zampini } 162243eeeb2dSStefano Zampini } 162343eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 162443eeeb2dSStefano Zampini PetscInt c; 162543eeeb2dSStefano Zampini 162643eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 162743eeeb2dSStefano Zampini PetscInt dof, offA, offB; 162843eeeb2dSStefano Zampini 162943eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr); 163043eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr); 163143eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 1632580bdb30SBarry Smith ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr); 163307b0a1fcSMatthew G Knepley } 163407b0a1fcSMatthew G Knepley } 163507b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr); 163607b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); 163707b0a1fcSMatthew G Knepley ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr); 163807b0a1fcSMatthew G Knepley ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); 163907b0a1fcSMatthew G Knepley PetscFunctionReturn(0); 164007b0a1fcSMatthew G Knepley } 16415c386225SMatthew G. Knepley 16424e3744c5SMatthew G. Knepley /*@ 16434e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 16444e3744c5SMatthew G. Knepley 1645d083f849SBarry Smith Collective on dm 16464e3744c5SMatthew G. Knepley 16474e3744c5SMatthew G. Knepley Input Parameter: 16484e3744c5SMatthew G. Knepley . dm - The complete DMPlex object 16494e3744c5SMatthew G. Knepley 16504e3744c5SMatthew G. Knepley Output Parameter: 16514e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices 16524e3744c5SMatthew G. Knepley 16534e3744c5SMatthew G. Knepley Level: intermediate 16544e3744c5SMatthew G. Knepley 165595452b02SPatrick Sanan Notes: 165695452b02SPatrick Sanan It does not copy over the coordinates. 165743eeeb2dSStefano Zampini 16589ade3219SVaclav Hapla Developer Notes: 16599ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 16609ade3219SVaclav Hapla 166143eeeb2dSStefano Zampini .seealso: DMPlexInterpolate(), DMPlexCreateFromCellList(), DMPlexCopyCoordinates() 16624e3744c5SMatthew G. Knepley @*/ 16634e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 16644e3744c5SMatthew G. Knepley { 1665827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 16664e3744c5SMatthew G. Knepley DM udm; 1667c9f63434SStefano Zampini PetscInt dim, vStart, vEnd, cStart, cEnd, cMax, c, maxConeSize = 0, *cone; 16684e3744c5SMatthew G. Knepley PetscErrorCode ierr; 16694e3744c5SMatthew G. Knepley 16704e3744c5SMatthew G. Knepley PetscFunctionBegin; 167143eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 167243eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 1673c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1674827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1675827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1676827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1677827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 16784e3744c5SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 1679595d4abbSMatthew G. Knepley *dmUnint = dm; 1680595d4abbSMatthew G. Knepley PetscFunctionReturn(0); 16814e3744c5SMatthew G. Knepley } 1682595d4abbSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1683595d4abbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1684c9f63434SStefano Zampini ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 16854e3744c5SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr); 16864e3744c5SMatthew G. Knepley ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr); 1687c73cfb54SMatthew G. Knepley ierr = DMSetDimension(udm, dim);CHKERRQ(ierr); 16884e3744c5SMatthew G. Knepley ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr); 16894e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1690595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 16914e3744c5SMatthew G. Knepley 16924e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 16934e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 16944e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 16954e3744c5SMatthew G. Knepley 16964e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 16974e3744c5SMatthew G. Knepley } 16984e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 16994e3744c5SMatthew G. Knepley ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr); 1700595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 17014e3744c5SMatthew G. Knepley } 17024e3744c5SMatthew G. Knepley ierr = DMSetUp(udm);CHKERRQ(ierr); 1703785e854fSJed Brown ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr); 17044e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1705595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 17064e3744c5SMatthew G. Knepley 17074e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17084e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 17094e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 17104e3744c5SMatthew G. Knepley 17114e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 17124e3744c5SMatthew G. Knepley } 17134e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17144e3744c5SMatthew G. Knepley ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr); 17154e3744c5SMatthew G. Knepley } 17164e3744c5SMatthew G. Knepley ierr = PetscFree(cone);CHKERRQ(ierr); 1717c9f63434SStefano Zampini ierr = DMPlexSetHybridBounds(udm, cMax, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 17184e3744c5SMatthew G. Knepley ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr); 17194e3744c5SMatthew G. Knepley ierr = DMPlexStratify(udm);CHKERRQ(ierr); 17205c7de58aSMatthew G. Knepley /* Reduce SF */ 17215c7de58aSMatthew G. Knepley { 17225c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 17235c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 17245c7de58aSMatthew G. Knepley const PetscInt *localPoints; 17255c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 17265c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 17275c7de58aSMatthew G. Knepley PetscInt vEnd, numRoots, numLeaves, l; 17285c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 17295c7de58aSMatthew G. Knepley PetscErrorCode ierr; 17305c7de58aSMatthew G. Knepley 17315c7de58aSMatthew G. Knepley /* Get original SF information */ 17325c7de58aSMatthew G. Knepley ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 17335c7de58aSMatthew G. Knepley ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr); 17345c7de58aSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr); 17355c7de58aSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 17365c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 17375c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++; 17385c7de58aSMatthew G. Knepley /* Fill in leaves */ 17395c7de58aSMatthew G. Knepley if (vEnd >= 0) { 17405c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr); 17415c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr); 17425c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 17435c7de58aSMatthew G. Knepley if (localPoints[l] < vEnd) { 17445c7de58aSMatthew G. Knepley localPointsUn[n] = localPoints[l]; 17455c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 17465c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 17475c7de58aSMatthew G. Knepley ++n; 17485c7de58aSMatthew G. Knepley } 17495c7de58aSMatthew G. Knepley } 17505c7de58aSMatthew G. Knepley if (n != numLeavesUn) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn); 17515c7de58aSMatthew G. Knepley ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr); 17525c7de58aSMatthew G. Knepley } 17535c7de58aSMatthew G. Knepley } 175443eeeb2dSStefano Zampini { 175543eeeb2dSStefano Zampini PetscBool isper; 175643eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 175743eeeb2dSStefano Zampini const DMBoundaryType *bd; 175843eeeb2dSStefano Zampini 175943eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 176043eeeb2dSStefano Zampini ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr); 176143eeeb2dSStefano Zampini } 1762827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1763827c4036SVaclav Hapla { 1764d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) udm->data; 1765827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1766827c4036SVaclav Hapla } 17674e3744c5SMatthew G. Knepley *dmUnint = udm; 17684e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 17694e3744c5SMatthew G. Knepley } 1770a7748839SVaclav Hapla 1771a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1772a7748839SVaclav Hapla { 1773a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1774a7748839SVaclav Hapla MPI_Comm comm; 1775a7748839SVaclav Hapla PetscErrorCode ierr; 1776a7748839SVaclav Hapla 1777a7748839SVaclav Hapla PetscFunctionBegin; 1778a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1779a7748839SVaclav Hapla ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1780a7748839SVaclav Hapla ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1781a7748839SVaclav Hapla 1782a7748839SVaclav Hapla if (depth == dim) { 1783a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1784a7748839SVaclav Hapla if (!dim) goto finish; 1785a7748839SVaclav Hapla 1786a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 1787a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr); 1788a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1789a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1790a7748839SVaclav Hapla if (coneSize) { 1791a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1792a7748839SVaclav Hapla goto finish; 1793a7748839SVaclav Hapla } 1794a7748839SVaclav Hapla } 1795a7748839SVaclav Hapla 1796a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1797a7748839SVaclav Hapla for (h=0; h<dim; h++) { 1798a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 1799a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1800a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1801a7748839SVaclav Hapla if (!coneSize) { 1802a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1803a7748839SVaclav Hapla goto finish; 1804a7748839SVaclav Hapla } 1805a7748839SVaclav Hapla } 1806a7748839SVaclav Hapla } 1807a7748839SVaclav Hapla } else if (depth == 1) { 1808a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1809a7748839SVaclav Hapla } else { 1810a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1811a7748839SVaclav Hapla } 1812a7748839SVaclav Hapla finish: 1813a7748839SVaclav Hapla PetscFunctionReturn(0); 1814a7748839SVaclav Hapla } 1815a7748839SVaclav Hapla 1816a7748839SVaclav Hapla /*@ 18179ade3219SVaclav Hapla DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated. 1818a7748839SVaclav Hapla 1819a7748839SVaclav Hapla Not Collective 1820a7748839SVaclav Hapla 1821a7748839SVaclav Hapla Input Parameter: 1822a7748839SVaclav Hapla . dm - The DM object 1823a7748839SVaclav Hapla 1824a7748839SVaclav Hapla Output Parameter: 1825a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1826a7748839SVaclav Hapla 1827a7748839SVaclav Hapla Level: intermediate 1828a7748839SVaclav Hapla 1829a7748839SVaclav Hapla Notes: 18309ade3219SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this is NOT collective 18319ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1832a7748839SVaclav Hapla However, DMPlexInterpolate() guarantees the result is the same on all. 18339ade3219SVaclav Hapla 1834a7748839SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED. 1835a7748839SVaclav Hapla 18369ade3219SVaclav Hapla Developer Notes: 18379ade3219SVaclav Hapla Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID. 18389ade3219SVaclav Hapla 18399ade3219SVaclav Hapla If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called. 18409ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 18419ade3219SVaclav Hapla DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL. 18429ade3219SVaclav Hapla 18439ade3219SVaclav Hapla If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated. 18449ade3219SVaclav Hapla 18459ade3219SVaclav Hapla DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL, 18469ade3219SVaclav Hapla and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 18479ade3219SVaclav Hapla 1848a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective() 1849a7748839SVaclav Hapla @*/ 1850a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1851a7748839SVaclav Hapla { 1852a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1853a7748839SVaclav Hapla PetscErrorCode ierr; 1854a7748839SVaclav Hapla 1855a7748839SVaclav Hapla PetscFunctionBegin; 1856a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1857a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1858a7748839SVaclav Hapla if (plex->interpolated < 0) { 1859a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr); 1860a7748839SVaclav Hapla } else { 1861a7748839SVaclav Hapla #if defined (PETSC_USE_DEBUG) 1862a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1863a7748839SVaclav Hapla 1864a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr); 18657fc06600SVaclav 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]); 1866a7748839SVaclav Hapla #endif 1867a7748839SVaclav Hapla } 1868a7748839SVaclav Hapla *interpolated = plex->interpolated; 1869a7748839SVaclav Hapla PetscFunctionReturn(0); 1870a7748839SVaclav Hapla } 1871a7748839SVaclav Hapla 1872a7748839SVaclav Hapla /*@ 18739ade3219SVaclav Hapla DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner). 1874a7748839SVaclav Hapla 18752666ff3cSVaclav Hapla Collective 1876a7748839SVaclav Hapla 1877a7748839SVaclav Hapla Input Parameter: 1878a7748839SVaclav Hapla . dm - The DM object 1879a7748839SVaclav Hapla 1880a7748839SVaclav Hapla Output Parameter: 1881a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1882a7748839SVaclav Hapla 1883a7748839SVaclav Hapla Level: intermediate 1884a7748839SVaclav Hapla 1885a7748839SVaclav Hapla Notes: 18869ade3219SVaclav Hapla Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks. 18879ade3219SVaclav Hapla 18889ade3219SVaclav Hapla This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks. 18899ade3219SVaclav Hapla 18909ade3219SVaclav Hapla Developer Notes: 18919ade3219SVaclav Hapla Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID. 18929ade3219SVaclav Hapla 18939ade3219SVaclav Hapla If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated. 18949ade3219SVaclav Hapla MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 18959ade3219SVaclav Hapla if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED, 18969ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 18979ade3219SVaclav Hapla 18989ade3219SVaclav Hapla If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective. 1899a7748839SVaclav Hapla 1900a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated() 1901a7748839SVaclav Hapla @*/ 1902a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 1903a7748839SVaclav Hapla { 1904a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1905a7748839SVaclav Hapla PetscBool debug=PETSC_FALSE; 1906a7748839SVaclav Hapla PetscErrorCode ierr; 1907a7748839SVaclav Hapla 1908a7748839SVaclav Hapla PetscFunctionBegin; 1909a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1910a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1911a7748839SVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr); 1912a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1913a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1914a7748839SVaclav Hapla MPI_Comm comm; 1915a7748839SVaclav Hapla 1916a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1917a7748839SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr); 1918a7748839SVaclav Hapla ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRQ(ierr); 1919a7748839SVaclav Hapla ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRQ(ierr); 1920a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1921a7748839SVaclav Hapla if (debug) { 1922a7748839SVaclav Hapla PetscMPIInt rank; 1923a7748839SVaclav Hapla 1924a7748839SVaclav Hapla ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1925a7748839SVaclav Hapla ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr); 1926a7748839SVaclav Hapla ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr); 1927a7748839SVaclav Hapla } 1928a7748839SVaclav Hapla } 1929a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 1930a7748839SVaclav Hapla PetscFunctionReturn(0); 1931a7748839SVaclav Hapla } 1932