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 22*3be36e83SMatthew G. Knepley static PetscSFNode _PetscInvalidSFNode = {-1, -1}; 23*3be36e83SMatthew G. Knepley 24*3be36e83SMatthew G. Knepley typedef struct _PetscHashIJKLRemoteKey { PetscSFNode i, j, k, l; } PetscHashIJKLRemoteKey; 25*3be36e83SMatthew G. Knepley 26*3be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyHash(key) \ 27*3be36e83SMatthew G. Knepley PetscHashCombine(PetscHashCombine(PetscHashInt((key).i.rank + (key).i.index),PetscHashInt((key).j.rank + (key).j.index)), \ 28*3be36e83SMatthew G. Knepley PetscHashCombine(PetscHashInt((key).k.rank + (key).k.index),PetscHashInt((key).l.rank + (key).l.index))) 29*3be36e83SMatthew G. Knepley 30*3be36e83SMatthew G. Knepley #define PetscHashIJKLRemoteKeyEqual(k1,k2) \ 31*3be36e83SMatthew 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) 32*3be36e83SMatthew G. Knepley 33*3be36e83SMatthew G. Knepley PETSC_HASH_MAP(HashIJKLRemote, PetscHashIJKLRemoteKey, PetscSFNode, PetscHashIJKLRemoteKeyHash, PetscHashIJKLRemoteKeyEqual, _PetscInvalidSFNode) 34*3be36e83SMatthew G. Knepley 35*3be36e83SMatthew G. Knepley static PetscErrorCode PetscSortSFNode(PetscInt n, PetscSFNode A[]) 36*3be36e83SMatthew G. Knepley { 37*3be36e83SMatthew G. Knepley PetscInt i; 38*3be36e83SMatthew G. Knepley 39*3be36e83SMatthew G. Knepley PetscFunctionBegin; 40*3be36e83SMatthew G. Knepley for (i = 1; i < n; ++i) { 41*3be36e83SMatthew G. Knepley PetscSFNode x = A[i]; 42*3be36e83SMatthew G. Knepley PetscInt j; 43*3be36e83SMatthew G. Knepley 44*3be36e83SMatthew G. Knepley for (j = i-1; j >= 0; --j) { 45*3be36e83SMatthew G. Knepley if ((A[j].rank > x.rank) || (A[j].rank == x.rank && A[j].index > x.index)) break; 46*3be36e83SMatthew G. Knepley A[j+1] = A[j]; 47*3be36e83SMatthew G. Knepley } 48*3be36e83SMatthew G. Knepley A[j+1] = x; 49*3be36e83SMatthew G. Knepley } 50*3be36e83SMatthew G. Knepley PetscFunctionReturn(0); 51*3be36e83SMatthew 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 */ 57439ece16SMatthew G. Knepley PetscErrorCode DMPlexGetFaces_Internal(DM dm, PetscInt dim, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 589f074e33SMatthew G Knepley { 599f074e33SMatthew G Knepley const PetscInt *cone = NULL; 60cd921712SStefano Zampini PetscInt coneSize; 619f074e33SMatthew G Knepley PetscErrorCode ierr; 629f074e33SMatthew G Knepley 639f074e33SMatthew G Knepley PetscFunctionBegin; 649f074e33SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 659f074e33SMatthew G Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 669f074e33SMatthew G Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 67439ece16SMatthew G. Knepley ierr = DMPlexGetRawFaces_Internal(dm, dim, coneSize, 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 */ 74439ece16SMatthew G. Knepley PetscErrorCode DMPlexRestoreFaces_Internal(DM dm, PetscInt dim, 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 */ 86439ece16SMatthew G. Knepley PetscErrorCode DMPlexGetRawFaces_Internal(DM dm, PetscInt dim, PetscInt coneSize, 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); 94cd921712SStefano Zampini if (faces && coneSize) PetscValidIntPointer(cone,4); 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);} 979f074e33SMatthew G Knepley switch (dim) { 98c49d9212SMatthew G. Knepley case 1: 99c49d9212SMatthew G. Knepley switch (coneSize) { 100c49d9212SMatthew G. Knepley case 2: 101c49d9212SMatthew G. Knepley if (faces) { 102c49d9212SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 103c49d9212SMatthew G. Knepley *faces = facesTmp; 104c49d9212SMatthew G. Knepley } 105c49d9212SMatthew G. Knepley if (numFaces) *numFaces = 2; 106c49d9212SMatthew G. Knepley if (faceSize) *faceSize = 1; 107c49d9212SMatthew G. Knepley break; 108c49d9212SMatthew G. Knepley default: 10999836e0eSStefano Zampini SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 110c49d9212SMatthew G. Knepley } 111c49d9212SMatthew G. Knepley break; 1129f074e33SMatthew G Knepley case 2: 1139f074e33SMatthew G Knepley switch (coneSize) { 1149f074e33SMatthew G Knepley case 3: 1159a5b13a2SMatthew G Knepley if (faces) { 1169a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1179a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1189a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[0]; 1199a5b13a2SMatthew G Knepley *faces = facesTmp; 1209a5b13a2SMatthew G Knepley } 1219a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 3; 1229a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 2; 1239f074e33SMatthew G Knepley break; 1249f074e33SMatthew G Knepley case 4: 1259a5b13a2SMatthew G Knepley /* Vertices follow right hand rule */ 1269a5b13a2SMatthew G Knepley if (faces) { 1279a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1289a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1299a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[3]; 1309a5b13a2SMatthew G Knepley facesTmp[6] = cone[3]; facesTmp[7] = cone[0]; 1319a5b13a2SMatthew G Knepley *faces = facesTmp; 1329a5b13a2SMatthew G Knepley } 1339a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 1349a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 2; 1359f074e33SMatthew G Knepley break; 1369f074e33SMatthew G Knepley default: 13799836e0eSStefano Zampini SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1389f074e33SMatthew G Knepley } 1399f074e33SMatthew G Knepley break; 1409f074e33SMatthew G Knepley case 3: 1419f074e33SMatthew G Knepley switch (coneSize) { 1429f074e33SMatthew G Knepley case 3: 1439a5b13a2SMatthew G Knepley if (faces) { 1449a5b13a2SMatthew G Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 1459a5b13a2SMatthew G Knepley facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; 1469a5b13a2SMatthew G Knepley facesTmp[4] = cone[2]; facesTmp[5] = cone[0]; 1479a5b13a2SMatthew G Knepley *faces = facesTmp; 1489a5b13a2SMatthew G Knepley } 1499a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 3; 1509a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 2; 1519f074e33SMatthew G Knepley break; 1529f074e33SMatthew G Knepley case 4: 1532e1b13c2SMatthew G. Knepley /* Vertices of first face follow right hand rule and normal points away from last vertex */ 1549a5b13a2SMatthew G Knepley if (faces) { 1552e1b13c2SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; 1562e1b13c2SMatthew G. Knepley facesTmp[3] = cone[0]; facesTmp[4] = cone[3]; facesTmp[5] = cone[1]; 1572e1b13c2SMatthew G. Knepley facesTmp[6] = cone[0]; facesTmp[7] = cone[2]; facesTmp[8] = cone[3]; 1582e1b13c2SMatthew G. Knepley facesTmp[9] = cone[2]; facesTmp[10] = cone[1]; facesTmp[11] = cone[3]; 1599a5b13a2SMatthew G Knepley *faces = facesTmp; 1609a5b13a2SMatthew G Knepley } 1619a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 4; 1629a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 3; 1639a5b13a2SMatthew G Knepley break; 1649a5b13a2SMatthew G Knepley case 8: 165e368ef20SMatthew G. Knepley /* 7--------6 166e368ef20SMatthew G. Knepley /| /| 167e368ef20SMatthew G. Knepley / | / | 168e368ef20SMatthew G. Knepley 4--------5 | 169e368ef20SMatthew G. Knepley | | | | 170e368ef20SMatthew G. Knepley | | | | 171e368ef20SMatthew G. Knepley | 1--------2 172e368ef20SMatthew G. Knepley | / | / 173e368ef20SMatthew G. Knepley |/ |/ 174e368ef20SMatthew G. Knepley 0--------3 175e368ef20SMatthew G. Knepley */ 1769a5b13a2SMatthew G Knepley if (faces) { 17751cfd6a4SMatthew G. Knepley facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; /* Bottom */ 17851cfd6a4SMatthew G. Knepley facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; facesTmp[6] = cone[6]; facesTmp[7] = cone[7]; /* Top */ 17951cfd6a4SMatthew G. Knepley facesTmp[8] = cone[0]; facesTmp[9] = cone[3]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; /* Front */ 18051cfd6a4SMatthew G. Knepley facesTmp[12] = cone[2]; facesTmp[13] = cone[1]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; /* Back */ 18151cfd6a4SMatthew G. Knepley facesTmp[16] = cone[3]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; /* Right */ 18251cfd6a4SMatthew G. Knepley facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[1]; /* Left */ 1839a5b13a2SMatthew G Knepley *faces = facesTmp; 1849a5b13a2SMatthew G Knepley } 1859a5b13a2SMatthew G Knepley if (numFaces) *numFaces = 6; 1869a5b13a2SMatthew G Knepley if (faceSize) *faceSize = 4; 1879f074e33SMatthew G Knepley break; 1889f074e33SMatthew G Knepley default: 18999836e0eSStefano Zampini SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1909f074e33SMatthew G Knepley } 1919f074e33SMatthew G Knepley break; 1929f074e33SMatthew G Knepley default: 19399836e0eSStefano Zampini SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1949f074e33SMatthew G Knepley } 1959f074e33SMatthew G Knepley PetscFunctionReturn(0); 1969f074e33SMatthew G Knepley } 1979f074e33SMatthew G Knepley 19899836e0eSStefano Zampini /* 19999836e0eSStefano Zampini DMPlexGetRawFacesHybrid_Internal - Gets groups of vertices that correspond to faces for the given cone using hybrid ordering (prisms) 20099836e0eSStefano Zampini */ 20199836e0eSStefano Zampini static PetscErrorCode DMPlexGetRawFacesHybrid_Internal(DM dm, PetscInt dim, PetscInt coneSize, const PetscInt cone[], PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[]) 20299836e0eSStefano Zampini { 20399836e0eSStefano Zampini PetscInt *facesTmp; 20499836e0eSStefano Zampini PetscInt maxConeSize, maxSupportSize; 20599836e0eSStefano Zampini PetscErrorCode ierr; 20699836e0eSStefano Zampini 20799836e0eSStefano Zampini PetscFunctionBegin; 20899836e0eSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20999836e0eSStefano Zampini if (faces && coneSize) PetscValidIntPointer(cone,4); 21099836e0eSStefano Zampini ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 21199836e0eSStefano Zampini if (faces) {ierr = DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), MPIU_INT, &facesTmp);CHKERRQ(ierr);} 21299836e0eSStefano Zampini switch (dim) { 21399836e0eSStefano Zampini case 1: 21499836e0eSStefano Zampini switch (coneSize) { 21599836e0eSStefano Zampini case 2: 21699836e0eSStefano Zampini if (faces) { 21799836e0eSStefano Zampini facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 21899836e0eSStefano Zampini *faces = facesTmp; 21999836e0eSStefano Zampini } 22099836e0eSStefano Zampini if (numFaces) *numFaces = 2; 22199836e0eSStefano Zampini if (numFacesNotH) *numFacesNotH = 2; 22299836e0eSStefano Zampini if (faceSize) *faceSize = 1; 22399836e0eSStefano Zampini break; 22499836e0eSStefano Zampini default: 22599836e0eSStefano Zampini SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 22699836e0eSStefano Zampini } 22799836e0eSStefano Zampini break; 22899836e0eSStefano Zampini case 2: 22999836e0eSStefano Zampini switch (coneSize) { 23099836e0eSStefano Zampini case 4: 23199836e0eSStefano Zampini if (faces) { 23299836e0eSStefano Zampini facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; 23399836e0eSStefano Zampini facesTmp[2] = cone[2]; facesTmp[3] = cone[3]; 23499836e0eSStefano Zampini facesTmp[4] = cone[0]; facesTmp[5] = cone[2]; 23599836e0eSStefano Zampini facesTmp[6] = cone[1]; facesTmp[7] = cone[3]; 23699836e0eSStefano Zampini *faces = facesTmp; 23799836e0eSStefano Zampini } 23899836e0eSStefano Zampini if (numFaces) *numFaces = 4; 23999836e0eSStefano Zampini if (numFacesNotH) *numFacesNotH = 2; 24099836e0eSStefano Zampini if (faceSize) *faceSize = 2; 24199836e0eSStefano Zampini break; 24299836e0eSStefano Zampini default: 24399836e0eSStefano Zampini SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 24499836e0eSStefano Zampini } 24599836e0eSStefano Zampini break; 24699836e0eSStefano Zampini case 3: 24799836e0eSStefano Zampini switch (coneSize) { 24899836e0eSStefano Zampini case 6: /* triangular prism */ 24999836e0eSStefano Zampini if (faces) { 25099836e0eSStefano Zampini facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[2]; facesTmp[3] = -1; /* Bottom */ 25199836e0eSStefano Zampini facesTmp[4] = cone[3]; facesTmp[5] = cone[4]; facesTmp[6] = cone[5]; facesTmp[7] = -1; /* Top */ 25299836e0eSStefano Zampini facesTmp[8] = cone[0]; facesTmp[9] = cone[1]; facesTmp[10] = cone[3]; facesTmp[11] = cone[4]; /* Back left */ 25399836e0eSStefano Zampini facesTmp[12] = cone[1]; facesTmp[13] = cone[2]; facesTmp[14] = cone[4]; facesTmp[15] = cone[5]; /* Back right */ 25499836e0eSStefano Zampini facesTmp[16] = cone[2]; facesTmp[17] = cone[0]; facesTmp[18] = cone[5]; facesTmp[19] = cone[3]; /* Front */ 25599836e0eSStefano Zampini *faces = facesTmp; 25699836e0eSStefano Zampini } 25799836e0eSStefano Zampini if (numFaces) *numFaces = 5; 25899836e0eSStefano Zampini if (numFacesNotH) *numFacesNotH = 2; 25999836e0eSStefano Zampini if (faceSize) *faceSize = -4; 26099836e0eSStefano Zampini break; 26199836e0eSStefano Zampini default: 26299836e0eSStefano Zampini SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 26399836e0eSStefano Zampini } 26499836e0eSStefano Zampini break; 26599836e0eSStefano Zampini default: 26699836e0eSStefano Zampini SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 26799836e0eSStefano Zampini } 26899836e0eSStefano Zampini PetscFunctionReturn(0); 26999836e0eSStefano Zampini } 27099836e0eSStefano Zampini 27199836e0eSStefano Zampini static PetscErrorCode DMPlexRestoreRawFacesHybrid_Internal(DM dm, PetscInt dim, PetscInt coneSize, const PetscInt cone[], PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[]) 27299836e0eSStefano Zampini { 27399836e0eSStefano Zampini PetscErrorCode ierr; 27499836e0eSStefano Zampini 27599836e0eSStefano Zampini PetscFunctionBegin; 27699836e0eSStefano Zampini if (faces) { ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void *) faces);CHKERRQ(ierr); } 27799836e0eSStefano Zampini PetscFunctionReturn(0); 27899836e0eSStefano Zampini } 27999836e0eSStefano Zampini 28099836e0eSStefano Zampini static PetscErrorCode DMPlexGetFacesHybrid_Internal(DM dm, PetscInt dim, PetscInt p, PetscInt *numFaces, PetscInt *numFacesNotH, PetscInt *faceSize, const PetscInt *faces[]) 28199836e0eSStefano Zampini { 28299836e0eSStefano Zampini const PetscInt *cone = NULL; 28399836e0eSStefano Zampini PetscInt coneSize; 28499836e0eSStefano Zampini PetscErrorCode ierr; 28599836e0eSStefano Zampini 28699836e0eSStefano Zampini PetscFunctionBegin; 28799836e0eSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28899836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 28999836e0eSStefano Zampini ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 29099836e0eSStefano Zampini ierr = DMPlexGetRawFacesHybrid_Internal(dm, dim, coneSize, cone, numFaces, numFacesNotH, faceSize, faces);CHKERRQ(ierr); 29199836e0eSStefano Zampini PetscFunctionReturn(0); 29299836e0eSStefano Zampini } 29399836e0eSStefano Zampini 2949a5b13a2SMatthew G Knepley /* This interpolates faces for cells at some stratum */ 2959a5b13a2SMatthew G Knepley static PetscErrorCode DMPlexInterpolateFaces_Internal(DM dm, PetscInt cellDepth, DM idm) 2969f074e33SMatthew G Knepley { 297d4efc6f1SMatthew G. Knepley DMLabel subpointMap; 2989a5b13a2SMatthew G Knepley PetscHashIJKL faceTable; 2999a5b13a2SMatthew G Knepley PetscInt *pStart, *pEnd; 3009a5b13a2SMatthew G Knepley PetscInt cellDim, depth, faceDepth = cellDepth, numPoints = 0, faceSizeAll = 0, face, c, d; 301e9fa77a1SMatthew G. Knepley PetscInt coneSizeH = 0, faceSizeAllH = 0, faceSizeAllT = 0, numCellFacesH = 0, faceT = 0, faceH, pMax = -1, dim, outerloop; 30299836e0eSStefano Zampini PetscInt cMax, fMax, eMax, vMax; 3039f074e33SMatthew G Knepley PetscErrorCode ierr; 3049f074e33SMatthew G Knepley 3059f074e33SMatthew G Knepley PetscFunctionBegin; 306c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &cellDim);CHKERRQ(ierr); 307d4efc6f1SMatthew G. Knepley /* HACK: I need a better way to determine face dimension, or an alternative to GetFaces() */ 308d4efc6f1SMatthew G. Knepley ierr = DMPlexGetSubpointMap(dm, &subpointMap);CHKERRQ(ierr); 309d4efc6f1SMatthew G. Knepley if (subpointMap) ++cellDim; 3109a5b13a2SMatthew G Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3119a5b13a2SMatthew G Knepley ++depth; 3129a5b13a2SMatthew G Knepley ++cellDepth; 3139a5b13a2SMatthew G Knepley cellDim -= depth - cellDepth; 314dcca6d9dSJed Brown ierr = PetscMalloc2(depth+1,&pStart,depth+1,&pEnd);CHKERRQ(ierr); 3159a5b13a2SMatthew G Knepley for (d = depth-1; d >= faceDepth; --d) { 3169a5b13a2SMatthew G Knepley ierr = DMPlexGetDepthStratum(dm, d, &pStart[d+1], &pEnd[d+1]);CHKERRQ(ierr); 3179f074e33SMatthew G Knepley } 3189a5b13a2SMatthew G Knepley ierr = DMPlexGetDepthStratum(dm, -1, NULL, &pStart[faceDepth]);CHKERRQ(ierr); 3199a5b13a2SMatthew G Knepley pEnd[faceDepth] = pStart[faceDepth]; 3209a5b13a2SMatthew G Knepley for (d = faceDepth-1; d >= 0; --d) { 3219a5b13a2SMatthew G Knepley ierr = DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d]);CHKERRQ(ierr); 3229f074e33SMatthew G Knepley } 32399836e0eSStefano Zampini cMax = fMax = eMax = vMax = PETSC_DETERMINE; 32499836e0eSStefano Zampini ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 32599836e0eSStefano Zampini if (cellDim == dim) { 32699836e0eSStefano Zampini ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 32799836e0eSStefano Zampini pMax = cMax; 32899836e0eSStefano Zampini } else if (cellDim == dim -1) { 32999836e0eSStefano Zampini ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);CHKERRQ(ierr); 33099836e0eSStefano Zampini pMax = fMax; 33199836e0eSStefano Zampini } 33299836e0eSStefano Zampini pMax = pMax < 0 ? pEnd[cellDepth] : pMax; 33399836e0eSStefano Zampini if (pMax < pEnd[cellDepth]) { 33499836e0eSStefano Zampini const PetscInt *cellFaces, *cone; 33599836e0eSStefano Zampini PetscInt numCellFacesT, faceSize, cf; 3369f074e33SMatthew G Knepley 337e9fa77a1SMatthew G. Knepley /* First get normal cell face size (we now allow hybrid cells to meet normal cells on either hybrid or normal faces */ 3385ebdaad1SMatthew G. Knepley if (pStart[cellDepth] < pMax) {ierr = DMPlexGetFaces_Internal(dm, cellDim, pStart[cellDepth], NULL, &faceSizeAll, NULL);CHKERRQ(ierr);} 339e9fa77a1SMatthew G. Knepley 34099836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, pMax, &coneSizeH);CHKERRQ(ierr); 34199836e0eSStefano Zampini ierr = DMPlexGetCone(dm, pMax, &cone);CHKERRQ(ierr); 34299836e0eSStefano Zampini ierr = DMPlexGetRawFacesHybrid_Internal(dm, cellDim, coneSizeH, cone, &numCellFacesH, &numCellFacesT, &faceSize, &cellFaces);CHKERRQ(ierr); 34399836e0eSStefano Zampini if (faceSize < 0) { 34499836e0eSStefano Zampini PetscInt *sizes, minv, maxv; 34599836e0eSStefano Zampini 34699836e0eSStefano Zampini /* count vertices of hybrid and non-hybrid faces */ 34799836e0eSStefano Zampini ierr = PetscCalloc1(numCellFacesH, &sizes);CHKERRQ(ierr); 34899836e0eSStefano Zampini for (cf = 0; cf < numCellFacesT; ++cf) { /* These are the non-hybrid faces */ 34999836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[-cf*faceSize]; 35099836e0eSStefano Zampini PetscInt f; 35199836e0eSStefano Zampini 35299836e0eSStefano Zampini for (f = 0; f < -faceSize; ++f) sizes[cf] += (cellFace[f] >= 0 ? 1 : 0); 35399836e0eSStefano Zampini } 35499836e0eSStefano Zampini ierr = PetscSortInt(numCellFacesT, sizes);CHKERRQ(ierr); 35599836e0eSStefano Zampini minv = sizes[0]; 35699836e0eSStefano Zampini maxv = sizes[PetscMax(numCellFacesT-1, 0)]; 35799836e0eSStefano Zampini if (minv != maxv) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Different number of vertices for non-hybrid face %D != %D", minv, maxv); 358e9fa77a1SMatthew G. Knepley faceSizeAllT = minv; 359580bdb30SBarry Smith ierr = PetscArrayzero(sizes, numCellFacesH);CHKERRQ(ierr); 36099836e0eSStefano Zampini for (cf = numCellFacesT; cf < numCellFacesH; ++cf) { /* These are the hybrid faces */ 36199836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[-cf*faceSize]; 36299836e0eSStefano Zampini PetscInt f; 36399836e0eSStefano Zampini 36499836e0eSStefano Zampini for (f = 0; f < -faceSize; ++f) sizes[cf-numCellFacesT] += (cellFace[f] >= 0 ? 1 : 0); 36599836e0eSStefano Zampini } 36699836e0eSStefano Zampini ierr = PetscSortInt(numCellFacesH - numCellFacesT, sizes);CHKERRQ(ierr); 36799836e0eSStefano Zampini minv = sizes[0]; 36899836e0eSStefano Zampini maxv = sizes[PetscMax(numCellFacesH - numCellFacesT-1, 0)]; 36999836e0eSStefano Zampini ierr = PetscFree(sizes);CHKERRQ(ierr); 37099836e0eSStefano Zampini if (minv != maxv) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Different number of vertices for hybrid face %D != %D", minv, maxv); 37199836e0eSStefano Zampini faceSizeAllH = minv; 3725ebdaad1SMatthew G. Knepley if (!faceSizeAll) faceSizeAll = faceSizeAllT; 37399836e0eSStefano Zampini } else { /* the size of the faces in hybrid cells is the same */ 374e9fa77a1SMatthew G. Knepley faceSizeAll = faceSizeAllH = faceSizeAllT = faceSize; 37599836e0eSStefano Zampini } 37699836e0eSStefano Zampini ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, cellDim, coneSizeH, cone, &numCellFacesH, &numCellFacesT, &faceSize, &cellFaces);CHKERRQ(ierr); 37799836e0eSStefano Zampini } else if (pEnd[cellDepth] > pStart[cellDepth]) { 37899836e0eSStefano Zampini ierr = DMPlexGetFaces_Internal(dm, cellDim, pStart[cellDepth], NULL, &faceSizeAll, NULL);CHKERRQ(ierr); 379a1bcd873SMatthew G. Knepley faceSizeAllH = faceSizeAllT = faceSizeAll; 38099836e0eSStefano Zampini } 38199836e0eSStefano Zampini if (faceSizeAll > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSizeAll); 38299836e0eSStefano Zampini 383b135d7daSStefano Zampini /* With hybrid grids, we first iterate on hybrid cells and start numbering the non-hybrid faces 38499836e0eSStefano Zampini Then, faces for non-hybrid cells are numbered. 38599836e0eSStefano Zampini This is to guarantee consistent orientations (all 0) of all the points in the cone of the hybrid cells */ 38699836e0eSStefano Zampini ierr = PetscHashIJKLCreate(&faceTable);CHKERRQ(ierr); 38799836e0eSStefano Zampini for (outerloop = 0, face = pStart[faceDepth]; outerloop < 2; outerloop++) { 38899836e0eSStefano Zampini PetscInt start, end; 38999836e0eSStefano Zampini 39099836e0eSStefano Zampini start = outerloop == 0 ? pMax : pStart[cellDepth]; 39199836e0eSStefano Zampini end = outerloop == 0 ? pEnd[cellDepth] : pMax; 39299836e0eSStefano Zampini for (c = start; c < end; ++c) { 39399836e0eSStefano Zampini const PetscInt *cellFaces; 394e9fa77a1SMatthew G. Knepley PetscInt numCellFaces, faceSize, faceSizeInc, faceSizeCheck, cf; 39599836e0eSStefano Zampini 39699836e0eSStefano Zampini if (c < pMax) { 3979a5b13a2SMatthew G Knepley ierr = DMPlexGetFaces_Internal(dm, cellDim, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 3989a5b13a2SMatthew G Knepley if (faceSize != faceSizeAll) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent face for cell %D of size %D != %D", c, faceSize, faceSizeAll); 399e9fa77a1SMatthew G. Knepley faceSizeCheck = faceSizeAll; 40099836e0eSStefano Zampini } else { /* Hybrid cell */ 40199836e0eSStefano Zampini const PetscInt *cone; 40299836e0eSStefano Zampini PetscInt numCellFacesN, coneSize; 40399836e0eSStefano Zampini 40499836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 40599836e0eSStefano Zampini if (coneSize != coneSizeH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid coneSize %D != %D", coneSize, coneSizeH); 40699836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 40799836e0eSStefano Zampini ierr = DMPlexGetRawFacesHybrid_Internal(dm, cellDim, coneSize, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 40899836e0eSStefano Zampini if (numCellFaces != numCellFacesH) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected numCellFaces %D != %D for hybrid cell %D", numCellFaces, numCellFacesH, c); 40999836e0eSStefano Zampini faceSize = PetscMax(faceSize, -faceSize); 41099836e0eSStefano Zampini if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSize); 41199836e0eSStefano Zampini numCellFaces = numCellFacesN; /* process only non-hybrid faces */ 412e9fa77a1SMatthew G. Knepley faceSizeCheck = faceSizeAllT; 41399836e0eSStefano Zampini } 41499836e0eSStefano Zampini faceSizeInc = faceSize; 4159f074e33SMatthew G Knepley for (cf = 0; cf < numCellFaces; ++cf) { 41699836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[cf*faceSizeInc]; 41799836e0eSStefano Zampini PetscInt faceSizeH = faceSize; 4189a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 419e8f14785SLisandro Dalcin PetscHashIter iter; 420e8f14785SLisandro Dalcin PetscBool missing; 4219f074e33SMatthew G Knepley 42299836e0eSStefano Zampini if (faceSizeInc == 2) { 4239a5b13a2SMatthew G Knepley key.i = PetscMin(cellFace[0], cellFace[1]); 4249a5b13a2SMatthew G Knepley key.j = PetscMax(cellFace[0], cellFace[1]); 42599836e0eSStefano Zampini key.k = PETSC_MAX_INT; 42699836e0eSStefano Zampini key.l = PETSC_MAX_INT; 4279a5b13a2SMatthew G Knepley } else { 42899836e0eSStefano Zampini key.i = cellFace[0]; 42999836e0eSStefano Zampini key.j = cellFace[1]; 43099836e0eSStefano Zampini key.k = cellFace[2]; 43199836e0eSStefano Zampini key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT; 432302440fdSBarry Smith ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 4339f074e33SMatthew G Knepley } 43499836e0eSStefano Zampini /* this check is redundant for non-hybrid meshes */ 435e9fa77a1SMatthew 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); 436e8f14785SLisandro Dalcin ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 437e9fa77a1SMatthew G. Knepley if (missing) { 438e9fa77a1SMatthew G. Knepley ierr = PetscHashIJKLIterSet(faceTable, iter, face++);CHKERRQ(ierr); 439e9fa77a1SMatthew G. Knepley if (c >= pMax) ++faceT; 440e9fa77a1SMatthew G. Knepley } 4419a5b13a2SMatthew G Knepley } 44299836e0eSStefano Zampini if (c < pMax) { 443439ece16SMatthew G. Knepley ierr = DMPlexRestoreFaces_Internal(dm, cellDim, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 44499836e0eSStefano Zampini } else { 44599836e0eSStefano Zampini ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, cellDim, coneSizeH, NULL, NULL, NULL, NULL, &cellFaces);CHKERRQ(ierr); 44699836e0eSStefano Zampini } 44799836e0eSStefano Zampini } 44899836e0eSStefano Zampini } 44999836e0eSStefano Zampini pEnd[faceDepth] = face; 45099836e0eSStefano Zampini 45199836e0eSStefano Zampini /* Second pass for hybrid meshes: number hybrid faces */ 45299836e0eSStefano Zampini for (c = pMax; c < pEnd[cellDepth]; ++c) { 45399836e0eSStefano Zampini const PetscInt *cellFaces, *cone; 45499836e0eSStefano Zampini PetscInt numCellFaces, numCellFacesN, faceSize, cf, coneSize; 45599836e0eSStefano Zampini 45699836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 45799836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 45899836e0eSStefano Zampini ierr = DMPlexGetRawFacesHybrid_Internal(dm, cellDim, coneSize, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 45999836e0eSStefano Zampini if (numCellFaces != numCellFacesH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid numCellFaces %D != %D", numCellFaces, numCellFacesH); 46099836e0eSStefano Zampini faceSize = PetscMax(faceSize, -faceSize); 46199836e0eSStefano Zampini for (cf = numCellFacesN; cf < numCellFaces; ++cf) { /* These are the hybrid faces */ 46299836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[cf*faceSize]; 46399836e0eSStefano Zampini PetscHashIJKLKey key; 46499836e0eSStefano Zampini PetscHashIter iter; 46599836e0eSStefano Zampini PetscBool missing; 46699836e0eSStefano Zampini PetscInt faceSizeH = faceSize; 46799836e0eSStefano Zampini 46899836e0eSStefano Zampini if (faceSize == 2) { 46999836e0eSStefano Zampini key.i = PetscMin(cellFace[0], cellFace[1]); 47099836e0eSStefano Zampini key.j = PetscMax(cellFace[0], cellFace[1]); 47199836e0eSStefano Zampini key.k = PETSC_MAX_INT; 47299836e0eSStefano Zampini key.l = PETSC_MAX_INT; 47399836e0eSStefano Zampini } else { 47499836e0eSStefano Zampini key.i = cellFace[0]; 47599836e0eSStefano Zampini key.j = cellFace[1]; 47699836e0eSStefano Zampini key.k = cellFace[2]; 47799836e0eSStefano Zampini key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT; 47899836e0eSStefano Zampini ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 47999836e0eSStefano Zampini } 48099836e0eSStefano 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); 48199836e0eSStefano Zampini ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 48299836e0eSStefano Zampini if (missing) {ierr = PetscHashIJKLIterSet(faceTable, iter, face++);CHKERRQ(ierr);} 48399836e0eSStefano Zampini } 48499836e0eSStefano Zampini ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, cellDim, coneSize, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 48599836e0eSStefano Zampini } 48699836e0eSStefano Zampini faceH = face - pEnd[faceDepth]; 48799836e0eSStefano Zampini if (faceH) { 48899836e0eSStefano Zampini if (fMax == PETSC_DETERMINE) fMax = pEnd[faceDepth]; 48999836e0eSStefano Zampini else if (eMax == PETSC_DETERMINE) eMax = pEnd[faceDepth]; 49099836e0eSStefano Zampini else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of unassigned hybrid facets %D for cellDim %D and dimension %D", faceH, cellDim, dim); 4919a5b13a2SMatthew G Knepley } 4929a5b13a2SMatthew G Knepley pEnd[faceDepth] = face; 4939a5b13a2SMatthew G Knepley ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr); 4949a5b13a2SMatthew G Knepley /* Count new points */ 4959a5b13a2SMatthew G Knepley for (d = 0; d <= depth; ++d) { 4969a5b13a2SMatthew G Knepley numPoints += pEnd[d]-pStart[d]; 4979a5b13a2SMatthew G Knepley } 4989a5b13a2SMatthew G Knepley ierr = DMPlexSetChart(idm, 0, numPoints);CHKERRQ(ierr); 4999a5b13a2SMatthew G Knepley /* Set cone sizes */ 5009a5b13a2SMatthew G Knepley for (d = 0; d <= depth; ++d) { 5019a5b13a2SMatthew G Knepley PetscInt coneSize, p; 5029f074e33SMatthew G Knepley 5039a5b13a2SMatthew G Knepley if (d == faceDepth) { 504e9fa77a1SMatthew G. Knepley /* Now we have two cases: */ 505e9fa77a1SMatthew G. Knepley if (faceSizeAll == faceSizeAllT) { 5069a5b13a2SMatthew G Knepley /* I see no way to do this if we admit faces of different shapes */ 50799836e0eSStefano Zampini for (p = pStart[d]; p < pEnd[d]-faceH; ++p) { 5089a5b13a2SMatthew G Knepley ierr = DMPlexSetConeSize(idm, p, faceSizeAll);CHKERRQ(ierr); 5099a5b13a2SMatthew G Knepley } 51099836e0eSStefano Zampini for (p = pEnd[d]-faceH; p < pEnd[d]; ++p) { 51199836e0eSStefano Zampini ierr = DMPlexSetConeSize(idm, p, faceSizeAllH);CHKERRQ(ierr); 51299836e0eSStefano Zampini } 513e9fa77a1SMatthew G. Knepley } else if (faceSizeAll == faceSizeAllH) { 514e9fa77a1SMatthew G. Knepley for (p = pStart[d]; p < pStart[d]+faceT; ++p) { 515e9fa77a1SMatthew G. Knepley ierr = DMPlexSetConeSize(idm, p, faceSizeAllT);CHKERRQ(ierr); 516e9fa77a1SMatthew G. Knepley } 517e9fa77a1SMatthew G. Knepley for (p = pStart[d]+faceT; p < pEnd[d]-faceH; ++p) { 518e9fa77a1SMatthew G. Knepley ierr = DMPlexSetConeSize(idm, p, faceSizeAll);CHKERRQ(ierr); 519e9fa77a1SMatthew G. Knepley } 520e9fa77a1SMatthew G. Knepley for (p = pEnd[d]-faceH; p < pEnd[d]; ++p) { 521e9fa77a1SMatthew G. Knepley ierr = DMPlexSetConeSize(idm, p, faceSizeAllH);CHKERRQ(ierr); 522e9fa77a1SMatthew G. Knepley } 523e9fa77a1SMatthew G. Knepley } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent faces sizes N: %D T: %D H: %D", faceSizeAll, faceSizeAllT, faceSizeAllH); 524a014044eSMatthew G Knepley } else if (d == cellDepth) { 525a014044eSMatthew G Knepley for (p = pStart[d]; p < pEnd[d]; ++p) { 526a014044eSMatthew G Knepley /* Number of cell faces may be different from number of cell vertices*/ 52799836e0eSStefano Zampini if (p < pMax) { 528a014044eSMatthew G Knepley ierr = DMPlexGetFaces_Internal(dm, cellDim, p, &coneSize, NULL, NULL);CHKERRQ(ierr); 52999836e0eSStefano Zampini } else { 53099836e0eSStefano Zampini ierr = DMPlexGetFacesHybrid_Internal(dm, cellDim, p, &coneSize, NULL, NULL, NULL);CHKERRQ(ierr); 53199836e0eSStefano Zampini } 532a014044eSMatthew G Knepley ierr = DMPlexSetConeSize(idm, p, coneSize);CHKERRQ(ierr); 533a014044eSMatthew G Knepley } 5349a5b13a2SMatthew G Knepley } else { 5359a5b13a2SMatthew G Knepley for (p = pStart[d]; p < pEnd[d]; ++p) { 5369a5b13a2SMatthew G Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5379a5b13a2SMatthew G Knepley ierr = DMPlexSetConeSize(idm, p, coneSize);CHKERRQ(ierr); 5389f074e33SMatthew G Knepley } 5399f074e33SMatthew G Knepley } 5409f074e33SMatthew G Knepley } 5419f074e33SMatthew G Knepley ierr = DMSetUp(idm);CHKERRQ(ierr); 5429f074e33SMatthew G Knepley /* Get face cones from subsets of cell vertices */ 54399836e0eSStefano Zampini if (faceSizeAll > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSizeAll); 5449a5b13a2SMatthew G Knepley ierr = PetscHashIJKLCreate(&faceTable);CHKERRQ(ierr); 5459a5b13a2SMatthew G Knepley for (d = depth; d > cellDepth; --d) { 5469a5b13a2SMatthew G Knepley const PetscInt *cone; 5479a5b13a2SMatthew G Knepley PetscInt p; 5489a5b13a2SMatthew G Knepley 5499a5b13a2SMatthew G Knepley for (p = pStart[d]; p < pEnd[d]; ++p) { 5509a5b13a2SMatthew G Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5519a5b13a2SMatthew G Knepley ierr = DMPlexSetCone(idm, p, cone);CHKERRQ(ierr); 5529a5b13a2SMatthew G Knepley ierr = DMPlexGetConeOrientation(dm, p, &cone);CHKERRQ(ierr); 5539a5b13a2SMatthew G Knepley ierr = DMPlexSetConeOrientation(idm, p, cone);CHKERRQ(ierr); 5549f074e33SMatthew G Knepley } 5559a5b13a2SMatthew G Knepley } 55699836e0eSStefano Zampini for (outerloop = 0, face = pStart[faceDepth]; outerloop < 2; outerloop++) { 55799836e0eSStefano Zampini PetscInt start, end; 5589f074e33SMatthew G Knepley 55999836e0eSStefano Zampini start = outerloop == 0 ? pMax : pStart[cellDepth]; 56099836e0eSStefano Zampini end = outerloop == 0 ? pEnd[cellDepth] : pMax; 56199836e0eSStefano Zampini for (c = start; c < end; ++c) { 56299836e0eSStefano Zampini const PetscInt *cellFaces; 56399836e0eSStefano Zampini PetscInt numCellFaces, faceSize, faceSizeInc, cf; 56499836e0eSStefano Zampini 56599836e0eSStefano Zampini if (c < pMax) { 5669a5b13a2SMatthew G Knepley ierr = DMPlexGetFaces_Internal(dm, cellDim, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 5679a5b13a2SMatthew G Knepley if (faceSize != faceSizeAll) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent face for cell %D of size %D != %D", c, faceSize, faceSizeAll); 56899836e0eSStefano Zampini } else { 56999836e0eSStefano Zampini const PetscInt *cone; 57099836e0eSStefano Zampini PetscInt numCellFacesN, coneSize; 57199836e0eSStefano Zampini 57299836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 57399836e0eSStefano Zampini if (coneSize != coneSizeH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid coneSize %D != %D", coneSize, coneSizeH); 57499836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 57599836e0eSStefano Zampini ierr = DMPlexGetRawFacesHybrid_Internal(dm, cellDim, coneSize, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 57699836e0eSStefano Zampini if (numCellFaces != numCellFacesH) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected numCellFaces %D != %D for hybrid cell %D", numCellFaces, numCellFacesH, c); 57799836e0eSStefano Zampini faceSize = PetscMax(faceSize, -faceSize); 57899836e0eSStefano Zampini if (faceSize > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not support interpolation of meshes with faces of %D vertices", faceSize); 57999836e0eSStefano Zampini numCellFaces = numCellFacesN; /* process only non-hybrid faces */ 58099836e0eSStefano Zampini } 58199836e0eSStefano Zampini faceSizeInc = faceSize; 5829f074e33SMatthew G Knepley for (cf = 0; cf < numCellFaces; ++cf) { 58399836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[cf*faceSizeInc]; 5849a5b13a2SMatthew G Knepley PetscHashIJKLKey key; 585e8f14785SLisandro Dalcin PetscHashIter iter; 586e8f14785SLisandro Dalcin PetscBool missing; 5879f074e33SMatthew G Knepley 58899836e0eSStefano Zampini if (faceSizeInc == 2) { 5899a5b13a2SMatthew G Knepley key.i = PetscMin(cellFace[0], cellFace[1]); 5909a5b13a2SMatthew G Knepley key.j = PetscMax(cellFace[0], cellFace[1]); 59199836e0eSStefano Zampini key.k = PETSC_MAX_INT; 59299836e0eSStefano Zampini key.l = PETSC_MAX_INT; 5939a5b13a2SMatthew G Knepley } else { 594e8f14785SLisandro Dalcin key.i = cellFace[0]; 595e8f14785SLisandro Dalcin key.j = cellFace[1]; 596e8f14785SLisandro Dalcin key.k = cellFace[2]; 59799836e0eSStefano Zampini key.l = faceSizeInc > 3 ? (cellFace[3] < 0 ? faceSize = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT; 59899836e0eSStefano Zampini ierr = PetscSortInt(faceSizeInc, (PetscInt *) &key);CHKERRQ(ierr); 5999f074e33SMatthew G Knepley } 600e8f14785SLisandro Dalcin ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 601735a0255SMatthew G. Knepley if (missing) { 6029a5b13a2SMatthew G Knepley ierr = DMPlexSetCone(idm, face, cellFace);CHKERRQ(ierr); 603e8f14785SLisandro Dalcin ierr = PetscHashIJKLIterSet(faceTable, iter, face);CHKERRQ(ierr); 604735a0255SMatthew G. Knepley ierr = DMPlexInsertCone(idm, c, cf, face++);CHKERRQ(ierr); 6059a5b13a2SMatthew G Knepley } else { 6069a5b13a2SMatthew G Knepley const PetscInt *cone; 607735a0255SMatthew G. Knepley PetscInt coneSize, ornt, i, j, f; 6089f074e33SMatthew G Knepley 609e8f14785SLisandro Dalcin ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr); 6109a5b13a2SMatthew G Knepley ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 6112e1b13c2SMatthew G. Knepley /* Orient face: Do not allow reverse orientation at the first vertex */ 6129f074e33SMatthew G Knepley ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 6139f074e33SMatthew G Knepley ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 6149a5b13a2SMatthew 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); 6159a5b13a2SMatthew G Knepley /* - First find the initial vertex */ 6169a5b13a2SMatthew G Knepley for (i = 0; i < faceSize; ++i) if (cellFace[0] == cone[i]) break; 6179a5b13a2SMatthew G Knepley /* - Try forward comparison */ 6189a5b13a2SMatthew G Knepley for (j = 0; j < faceSize; ++j) if (cellFace[j] != cone[(i+j)%faceSize]) break; 6199a5b13a2SMatthew G Knepley if (j == faceSize) { 6209a5b13a2SMatthew G Knepley if ((faceSize == 2) && (i == 1)) ornt = -2; 6219a5b13a2SMatthew G Knepley else ornt = i; 6229a5b13a2SMatthew G Knepley } else { 6239a5b13a2SMatthew G Knepley /* - Try backward comparison */ 6249a5b13a2SMatthew G Knepley for (j = 0; j < faceSize; ++j) if (cellFace[j] != cone[(i+faceSize-j)%faceSize]) break; 6252e1b13c2SMatthew G. Knepley if (j == faceSize) { 6262e1b13c2SMatthew G. Knepley if (i == 0) ornt = -faceSize; 627dc1a705cSMatthew G. Knepley else ornt = -i; 628e9fa77a1SMatthew G. Knepley } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not determine orientation of face %D in cell %D", f, c); 6299a5b13a2SMatthew G Knepley } 6309a5b13a2SMatthew G Knepley ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr); 6319f074e33SMatthew G Knepley } 6329f074e33SMatthew G Knepley } 63399836e0eSStefano Zampini if (c < pMax) { 634439ece16SMatthew G. Knepley ierr = DMPlexRestoreFaces_Internal(dm, cellDim, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 63599836e0eSStefano Zampini } else { 63699836e0eSStefano Zampini ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, cellDim, coneSizeH, NULL, NULL, NULL, NULL, &cellFaces);CHKERRQ(ierr); 6379f074e33SMatthew G Knepley } 63899836e0eSStefano Zampini } 63999836e0eSStefano Zampini } 64099836e0eSStefano Zampini /* Second pass for hybrid meshes: orient hybrid faces */ 64199836e0eSStefano Zampini for (c = pMax; c < pEnd[cellDepth]; ++c) { 64299836e0eSStefano Zampini const PetscInt *cellFaces, *cone; 64399836e0eSStefano Zampini PetscInt numCellFaces, numCellFacesN, faceSize, cf, coneSize; 64499836e0eSStefano Zampini 64599836e0eSStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 64699836e0eSStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 64799836e0eSStefano Zampini ierr = DMPlexGetRawFacesHybrid_Internal(dm, cellDim, coneSize, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 64899836e0eSStefano Zampini if (numCellFaces != numCellFacesH) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unexpected hybrid numCellFaces %D != %D", numCellFaces, numCellFacesH); 64999836e0eSStefano Zampini faceSize = PetscMax(faceSize, -faceSize); 65099836e0eSStefano Zampini for (cf = numCellFacesN; cf < numCellFaces; ++cf) { /* These are the hybrid faces */ 65199836e0eSStefano Zampini const PetscInt *cellFace = &cellFaces[cf*faceSize]; 65299836e0eSStefano Zampini PetscHashIJKLKey key; 65399836e0eSStefano Zampini PetscHashIter iter; 65499836e0eSStefano Zampini PetscBool missing; 65599836e0eSStefano Zampini PetscInt faceSizeH = faceSize; 65699836e0eSStefano Zampini 65799836e0eSStefano Zampini if (faceSize == 2) { 65899836e0eSStefano Zampini key.i = PetscMin(cellFace[0], cellFace[1]); 65999836e0eSStefano Zampini key.j = PetscMax(cellFace[0], cellFace[1]); 66099836e0eSStefano Zampini key.k = PETSC_MAX_INT; 66199836e0eSStefano Zampini key.l = PETSC_MAX_INT; 66299836e0eSStefano Zampini } else { 66399836e0eSStefano Zampini key.i = cellFace[0]; 66499836e0eSStefano Zampini key.j = cellFace[1]; 66599836e0eSStefano Zampini key.k = cellFace[2]; 66699836e0eSStefano Zampini key.l = faceSize > 3 ? (cellFace[3] < 0 ? faceSizeH = 3, PETSC_MAX_INT : cellFace[3]) : PETSC_MAX_INT; 66799836e0eSStefano Zampini ierr = PetscSortInt(faceSize, (PetscInt *) &key);CHKERRQ(ierr); 66899836e0eSStefano Zampini } 66999836e0eSStefano 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); 67099836e0eSStefano Zampini ierr = PetscHashIJKLPut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 67199836e0eSStefano Zampini if (missing) { 67299836e0eSStefano Zampini ierr = DMPlexSetCone(idm, face, cellFace);CHKERRQ(ierr); 67399836e0eSStefano Zampini ierr = PetscHashIJKLIterSet(faceTable, iter, face);CHKERRQ(ierr); 67499836e0eSStefano Zampini ierr = DMPlexInsertCone(idm, c, cf, face++);CHKERRQ(ierr); 67599836e0eSStefano Zampini } else { 676e9fa77a1SMatthew G. Knepley PetscInt fv[4] = {0, 1, 2, 3}; 67799836e0eSStefano Zampini const PetscInt *cone; 67899836e0eSStefano Zampini PetscInt coneSize, ornt, i, j, f; 679a74221b0SStefano Zampini PetscBool q2h = PETSC_FALSE; 68099836e0eSStefano Zampini 68199836e0eSStefano Zampini ierr = PetscHashIJKLIterGet(faceTable, iter, &f);CHKERRQ(ierr); 68299836e0eSStefano Zampini ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 68399836e0eSStefano Zampini /* Orient face: Do not allow reverse orientation at the first vertex */ 68499836e0eSStefano Zampini ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 68599836e0eSStefano Zampini ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 68699836e0eSStefano 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); 687e9fa77a1SMatthew G. Knepley /* Hybrid faces are stored as tensor products of edges, so to compare them to normal faces, we have to flip */ 688a74221b0SStefano Zampini if (faceSize == 4 && c >= pMax && faceSizeAll != faceSizeAllT && f < pEnd[faceDepth] - faceH) {q2h = PETSC_TRUE; fv[2] = 3; fv[3] = 2;} 68999836e0eSStefano Zampini /* - First find the initial vertex */ 690e9fa77a1SMatthew G. Knepley for (i = 0; i < faceSizeH; ++i) if (cellFace[fv[0]] == cone[i]) break; 691a74221b0SStefano 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 */ 69299836e0eSStefano Zampini /* - Try forward comparison */ 693e9fa77a1SMatthew G. Knepley for (j = 0; j < faceSizeH; ++j) if (cellFace[fv[j]] != cone[(i+j)%faceSizeH]) break; 69499836e0eSStefano Zampini if (j == faceSizeH) { 69599836e0eSStefano Zampini if ((faceSizeH == 2) && (i == 1)) ornt = -2; 69699836e0eSStefano Zampini else ornt = i; 69799836e0eSStefano Zampini } else { 69899836e0eSStefano Zampini /* - Try backward comparison */ 699e9fa77a1SMatthew G. Knepley for (j = 0; j < faceSizeH; ++j) if (cellFace[fv[j]] != cone[(i+faceSizeH-j)%faceSizeH]) break; 70099836e0eSStefano Zampini if (j == faceSizeH) { 70199836e0eSStefano Zampini if (i == 0) ornt = -faceSizeH; 70299836e0eSStefano Zampini else ornt = -i; 703e9fa77a1SMatthew G. Knepley } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not determine orientation of face %D in cell %D", f, c); 70499836e0eSStefano Zampini } 705a74221b0SStefano Zampini } else { 706a74221b0SStefano Zampini /* when matching hybrid faces in 3D, only few cases are possible. 707a74221b0SStefano Zampini Face traversal however can no longer follow the usual convention, this seems a serious issue to me */ 708a74221b0SStefano Zampini PetscInt tquad_map[4][4] = { {PETSC_MIN_INT, 0,PETSC_MIN_INT,PETSC_MIN_INT}, 709a74221b0SStefano Zampini { -1,PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT}, 710a74221b0SStefano Zampini {PETSC_MIN_INT,PETSC_MIN_INT,PETSC_MIN_INT, 1}, 711a74221b0SStefano Zampini {PETSC_MIN_INT,PETSC_MIN_INT, -2,PETSC_MIN_INT} }; 712a74221b0SStefano Zampini PetscInt i2; 713a74221b0SStefano Zampini 714a74221b0SStefano Zampini /* find the second vertex */ 715a74221b0SStefano Zampini for (i2 = 0; i2 < faceSizeH; ++i2) if (cellFace[fv[1]] == cone[i2]) break; 716a74221b0SStefano Zampini switch (faceSizeH) { 717a74221b0SStefano Zampini case 2: 718a74221b0SStefano Zampini ornt = i ? -2 : 0; 719a74221b0SStefano Zampini break; 720a74221b0SStefano Zampini case 4: 721a74221b0SStefano Zampini ornt = tquad_map[i][i2]; 722a74221b0SStefano Zampini break; 723a74221b0SStefano Zampini default: 724a74221b0SStefano Zampini SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unhandled face size %D for face %D in cell %D", faceSizeH, f, c); 725a74221b0SStefano Zampini 726a74221b0SStefano Zampini } 727a74221b0SStefano Zampini } 72899836e0eSStefano Zampini ierr = DMPlexInsertConeOrientation(idm, c, cf, ornt);CHKERRQ(ierr); 72999836e0eSStefano Zampini } 73099836e0eSStefano Zampini } 73199836e0eSStefano Zampini ierr = DMPlexRestoreRawFacesHybrid_Internal(dm, cellDim, coneSize, cone, &numCellFaces, &numCellFacesN, &faceSize, &cellFaces);CHKERRQ(ierr); 73299836e0eSStefano Zampini } 73399836e0eSStefano 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]); 734c907b753SJed Brown ierr = PetscFree2(pStart,pEnd);CHKERRQ(ierr); 7359a5b13a2SMatthew G Knepley ierr = PetscHashIJKLDestroy(&faceTable);CHKERRQ(ierr); 7366551a8c7SMatthew G. Knepley ierr = PetscFree2(pStart,pEnd);CHKERRQ(ierr); 73799836e0eSStefano Zampini ierr = DMPlexSetHybridBounds(idm, cMax, fMax, eMax, vMax);CHKERRQ(ierr); 7389a5b13a2SMatthew G Knepley ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 7399a5b13a2SMatthew G Knepley ierr = DMPlexStratify(idm);CHKERRQ(ierr); 7409f074e33SMatthew G Knepley PetscFunctionReturn(0); 7419f074e33SMatthew G Knepley } 7429f074e33SMatthew G Knepley 743f80536cbSVaclav Hapla static PetscErrorCode SortRmineRremoteByRemote_Private(PetscSF sf, PetscInt *rmine1[], PetscInt *rremote1[]) 744f80536cbSVaclav Hapla { 745f80536cbSVaclav Hapla PetscInt nleaves; 746f80536cbSVaclav Hapla PetscInt nranks; 747a0d42dbcSVaclav Hapla const PetscMPIInt *ranks=NULL; 748a0d42dbcSVaclav Hapla const PetscInt *roffset=NULL, *rmine=NULL, *rremote=NULL; 749f80536cbSVaclav Hapla PetscInt n, o, r; 750f80536cbSVaclav Hapla PetscErrorCode ierr; 751f80536cbSVaclav Hapla 752f80536cbSVaclav Hapla PetscFunctionBegin; 753dec1416fSJunchao Zhang ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote);CHKERRQ(ierr); 754f80536cbSVaclav Hapla nleaves = roffset[nranks]; 755f80536cbSVaclav Hapla ierr = PetscMalloc2(nleaves, rmine1, nleaves, rremote1);CHKERRQ(ierr); 756f80536cbSVaclav Hapla for (r=0; r<nranks; r++) { 757f80536cbSVaclav Hapla /* simultaneously sort rank-wise portions of rmine & rremote by values in rremote 758f80536cbSVaclav Hapla - to unify order with the other side */ 759f80536cbSVaclav Hapla o = roffset[r]; 760f80536cbSVaclav Hapla n = roffset[r+1] - o; 761580bdb30SBarry Smith ierr = PetscArraycpy(&(*rmine1)[o], &rmine[o], n);CHKERRQ(ierr); 762580bdb30SBarry Smith ierr = PetscArraycpy(&(*rremote1)[o], &rremote[o], n);CHKERRQ(ierr); 763f80536cbSVaclav Hapla ierr = PetscSortIntWithArray(n, &(*rremote1)[o], &(*rmine1)[o]);CHKERRQ(ierr); 764f80536cbSVaclav Hapla } 765f80536cbSVaclav Hapla PetscFunctionReturn(0); 766f80536cbSVaclav Hapla } 767f80536cbSVaclav Hapla 76827d0e99aSVaclav Hapla PetscErrorCode DMPlexOrientInterface_Internal(DM dm) 7692e745bdaSMatthew G. Knepley { 77027d0e99aSVaclav Hapla /* Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */ 77127d0e99aSVaclav Hapla PetscInt masterCone[2]; 772cae7fe92SVaclav Hapla PetscInt (*roots)[2], (*leaves)[2]; 7738a650c75SVaclav Hapla PetscMPIInt (*rootsRanks)[2], (*leavesRanks)[2]; 77427d0e99aSVaclav Hapla 77527d0e99aSVaclav Hapla PetscSF sf=NULL; 776a0d42dbcSVaclav Hapla const PetscInt *locals=NULL; 777a0d42dbcSVaclav Hapla const PetscSFNode *remotes=NULL; 7788a650c75SVaclav Hapla PetscInt nroots, nleaves, p, c; 779f80536cbSVaclav Hapla PetscInt nranks, n, o, r; 780a0d42dbcSVaclav Hapla const PetscMPIInt *ranks=NULL; 781a0d42dbcSVaclav Hapla const PetscInt *roffset=NULL; 782a0d42dbcSVaclav Hapla PetscInt *rmine1=NULL, *rremote1=NULL; /* rmine and rremote copies simultaneously sorted by rank and rremote */ 783a0d42dbcSVaclav Hapla const PetscInt *cone=NULL; 784adeface4SVaclav Hapla PetscInt coneSize, ind0; 7852e745bdaSMatthew G. Knepley MPI_Comm comm; 78627d0e99aSVaclav Hapla PetscMPIInt rank,size; 7872e745bdaSMatthew G. Knepley PetscInt debug = 0; 7882e745bdaSMatthew G. Knepley PetscErrorCode ierr; 7892e745bdaSMatthew G. Knepley 7902e745bdaSMatthew G. Knepley PetscFunctionBegin; 791df6a9fadSVaclav Hapla ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7922e745bdaSMatthew G. Knepley ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &locals, &remotes);CHKERRQ(ierr); 7933ede9f65SMatthew G. Knepley if (nroots < 0) PetscFunctionReturn(0); 794f80536cbSVaclav Hapla ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 795dec1416fSJunchao Zhang ierr = PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, NULL, NULL);CHKERRQ(ierr); 796dc21a0bfSVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-before_fix_dm_view");CHKERRQ(ierr); 79727d0e99aSVaclav Hapla #if defined(PETSC_USE_DEBUG) 798dc21a0bfSVaclav Hapla ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 799dc21a0bfSVaclav Hapla #endif 800f80536cbSVaclav Hapla ierr = SortRmineRremoteByRemote_Private(sf, &rmine1, &rremote1);CHKERRQ(ierr); 8018a650c75SVaclav Hapla ierr = PetscMalloc4(nroots, &roots, nroots, &leaves, nroots, &rootsRanks, nroots, &leavesRanks);CHKERRQ(ierr); 8022e745bdaSMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8032e745bdaSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 80427d0e99aSVaclav Hapla ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 8059e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 8069e24d8a0SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8079e24d8a0SVaclav Hapla ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 80827d0e99aSVaclav Hapla if (coneSize < 2) { 80927d0e99aSVaclav Hapla for (c = 0; c < 2; c++) { 81027d0e99aSVaclav Hapla roots[p][c] = -1; 81127d0e99aSVaclav Hapla rootsRanks[p][c] = -1; 81227d0e99aSVaclav Hapla } 81327d0e99aSVaclav Hapla continue; 81427d0e99aSVaclav Hapla } 8152e745bdaSMatthew G. Knepley /* Translate all points to root numbering */ 8168a650c75SVaclav Hapla for (c = 0; c < 2; c++) { 8178a650c75SVaclav Hapla ierr = PetscFindInt(cone[c], nleaves, locals, &ind0);CHKERRQ(ierr); 8188a650c75SVaclav Hapla if (ind0 < 0) { 8198a650c75SVaclav Hapla roots[p][c] = cone[c]; 8208a650c75SVaclav Hapla rootsRanks[p][c] = rank; 821c8148b97SVaclav Hapla } else { 8228a650c75SVaclav Hapla roots[p][c] = remotes[ind0].index; 8238a650c75SVaclav Hapla rootsRanks[p][c] = remotes[ind0].rank; 8248a650c75SVaclav Hapla } 8252e745bdaSMatthew G. Knepley } 8262e745bdaSMatthew G. Knepley } 8279e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 8288ccb905dSVaclav Hapla for (c = 0; c < 2; c++) { 8298ccb905dSVaclav Hapla leaves[p][c] = -2; 8308ccb905dSVaclav Hapla leavesRanks[p][c] = -2; 8318ccb905dSVaclav Hapla } 832c8148b97SVaclav Hapla } 8332e745bdaSMatthew G. Knepley ierr = PetscSFBcastBegin(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr); 8348a650c75SVaclav Hapla ierr = PetscSFBcastBegin(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr); 8352e745bdaSMatthew G. Knepley ierr = PetscSFBcastEnd(sf, MPIU_2INT, roots, leaves);CHKERRQ(ierr); 8368a650c75SVaclav Hapla ierr = PetscSFBcastEnd(sf, MPI_2INT, rootsRanks, leavesRanks);CHKERRQ(ierr); 837c8148b97SVaclav Hapla if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 83827d0e99aSVaclav Hapla if (debug && rank == 0) {ierr = PetscSynchronizedPrintf(comm, "Referenced roots\n");CHKERRQ(ierr);} 8399e24d8a0SVaclav Hapla for (p = 0; p < nroots; ++p) { 8409e24d8a0SVaclav Hapla if (leaves[p][0] < 0) continue; 8419e24d8a0SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8429e24d8a0SVaclav Hapla ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 84327d0e99aSVaclav 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);} 84482f5c0aeSVaclav 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])) { 84527d0e99aSVaclav Hapla /* Translate these two leaves to my cone points; masterCone means desired order p's cone points */ 846f80536cbSVaclav Hapla for (c = 0; c < 2; c++) { 84727d0e99aSVaclav Hapla if (leavesRanks[p][c] == rank) { 84827d0e99aSVaclav Hapla /* A local leave is just taken as it is */ 84927d0e99aSVaclav Hapla masterCone[c] = leaves[p][c]; 85027d0e99aSVaclav Hapla continue; 85127d0e99aSVaclav Hapla } 852f80536cbSVaclav Hapla /* Find index of rank leavesRanks[p][c] among remote ranks */ 853f80536cbSVaclav Hapla /* No need for PetscMPIIntCast because these integers were originally cast from PetscMPIInt. */ 854f80536cbSVaclav Hapla ierr = PetscFindMPIInt((PetscMPIInt)leavesRanks[p][c], nranks, ranks, &r);CHKERRQ(ierr); 85527d0e99aSVaclav 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]); 85627d0e99aSVaclav 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]); 857f80536cbSVaclav Hapla /* Find point leaves[p][c] among remote points aimed at rank leavesRanks[p][c] */ 858f80536cbSVaclav Hapla o = roffset[r]; 859f80536cbSVaclav Hapla n = roffset[r+1] - o; 860f80536cbSVaclav Hapla ierr = PetscFindInt(leaves[p][c], n, &rremote1[o], &ind0);CHKERRQ(ierr); 86127d0e99aSVaclav 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]); 862f80536cbSVaclav Hapla /* Get the corresponding local point */ 863f80536cbSVaclav Hapla masterCone[c] = rmine1[o+ind0];CHKERRQ(ierr); 864f80536cbSVaclav Hapla } 86527d0e99aSVaclav Hapla if (debug) {ierr = PetscSynchronizedPrintf(comm, " masterCone=[%4D %4D]\n", masterCone[0], masterCone[1]);CHKERRQ(ierr);} 86627d0e99aSVaclav Hapla /* Set the desired order of p's cone points and fix orientations accordingly */ 867f80536cbSVaclav Hapla /* Vaclav's note: Here we only compare first 2 points of the cone. Full cone size would lead to stronger self-checking. */ 868f80536cbSVaclav Hapla ierr = DMPlexOrientCell(dm, p, 2, masterCone);CHKERRQ(ierr); 86927d0e99aSVaclav Hapla } else if (debug) {ierr = PetscSynchronizedPrintf(comm, " ==\n");CHKERRQ(ierr);} 87023aaf07bSVaclav Hapla } 87127d0e99aSVaclav Hapla if (debug) { 87227d0e99aSVaclav Hapla ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 87327d0e99aSVaclav Hapla ierr = MPI_Barrier(comm);CHKERRQ(ierr); 8742e745bdaSMatthew G. Knepley } 875adeface4SVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-after_fix_dm_view");CHKERRQ(ierr); 8768a650c75SVaclav Hapla ierr = PetscFree4(roots, leaves, rootsRanks, leavesRanks);CHKERRQ(ierr); 8777c7bb832SVaclav Hapla ierr = PetscFree2(rmine1, rremote1);CHKERRQ(ierr); 8782e745bdaSMatthew G. Knepley PetscFunctionReturn(0); 8792e745bdaSMatthew G. Knepley } 8802e745bdaSMatthew G. Knepley 8812e72742cSMatthew 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[]) 8827bffde78SMichael Lange { 8832e72742cSMatthew G. Knepley PetscInt idx; 8842e72742cSMatthew G. Knepley PetscMPIInt rank; 8852e72742cSMatthew G. Knepley PetscBool flg; 8867bffde78SMichael Lange PetscErrorCode ierr; 8877bffde78SMichael Lange 8887bffde78SMichael Lange PetscFunctionBegin; 8892e72742cSMatthew G. Knepley ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr); 8902e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 8912e72742cSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 8922e72742cSMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr); 8932e72742cSMatthew 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);} 8942e72742cSMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 8952e72742cSMatthew G. Knepley PetscFunctionReturn(0); 8962e72742cSMatthew G. Knepley } 8972e72742cSMatthew G. Knepley 8982e72742cSMatthew G. Knepley static PetscErrorCode SFNodeArrayViewFromOptions(MPI_Comm comm, const char opt[], const char name[], const char idxname[], PetscInt n, const PetscSFNode a[]) 8992e72742cSMatthew G. Knepley { 9002e72742cSMatthew G. Knepley PetscInt idx; 9012e72742cSMatthew G. Knepley PetscMPIInt rank; 9022e72742cSMatthew G. Knepley PetscBool flg; 9032e72742cSMatthew G. Knepley PetscErrorCode ierr; 9042e72742cSMatthew G. Knepley 9052e72742cSMatthew G. Knepley PetscFunctionBegin; 9062e72742cSMatthew G. Knepley ierr = PetscOptionsHasName(NULL, NULL, opt, &flg);CHKERRQ(ierr); 9072e72742cSMatthew G. Knepley if (!flg) PetscFunctionReturn(0); 9082e72742cSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 9092e72742cSMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d]%s:\n", rank, name);CHKERRQ(ierr); 9102e72742cSMatthew G. Knepley if (idxname) { 9112e72742cSMatthew 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);} 9122e72742cSMatthew G. Knepley } else { 9132e72742cSMatthew 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);} 9142e72742cSMatthew G. Knepley } 9152e72742cSMatthew G. Knepley ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 9162e72742cSMatthew G. Knepley PetscFunctionReturn(0); 9172e72742cSMatthew G. Knepley } 9182e72742cSMatthew G. Knepley 919*3be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToLocalPoint(DM dm, PetscHMapIJ remotehash, PetscSFNode remotePoint, PetscInt *localPoint) 9202e72742cSMatthew G. Knepley { 921*3be36e83SMatthew G. Knepley PetscSF sf; 922*3be36e83SMatthew G. Knepley const PetscInt *locals; 923*3be36e83SMatthew G. Knepley PetscMPIInt rank; 9242e72742cSMatthew G. Knepley PetscErrorCode ierr; 9252e72742cSMatthew G. Knepley 9262e72742cSMatthew G. Knepley PetscFunctionBegin; 927*3be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 928*3be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 929*3be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, NULL, &locals, NULL);CHKERRQ(ierr); 9302e72742cSMatthew G. Knepley if (remotePoint.rank == rank) { 9312e72742cSMatthew G. Knepley *localPoint = remotePoint.index; 9322e72742cSMatthew G. Knepley } else { 9332e72742cSMatthew G. Knepley PetscHashIJKey key; 934*3be36e83SMatthew G. Knepley PetscInt l; 9352e72742cSMatthew G. Knepley 9362e72742cSMatthew G. Knepley key.i = remotePoint.index; 9372e72742cSMatthew G. Knepley key.j = remotePoint.rank; 938*3be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(remotehash, key, &l);CHKERRQ(ierr); 939*3be36e83SMatthew G. Knepley if (l >= 0) { 940*3be36e83SMatthew G. Knepley *localPoint = locals[l]; 9412e72742cSMatthew G. Knepley } else PetscFunctionReturn(1); 9422e72742cSMatthew G. Knepley } 9432e72742cSMatthew G. Knepley PetscFunctionReturn(0); 9442e72742cSMatthew G. Knepley } 9452e72742cSMatthew G. Knepley 946*3be36e83SMatthew G. Knepley static PetscErrorCode DMPlexMapToGlobalPoint(DM dm, PetscInt localPoint, PetscSFNode *remotePoint) 947*3be36e83SMatthew G. Knepley { 948*3be36e83SMatthew G. Knepley PetscSF sf; 949*3be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 950*3be36e83SMatthew G. Knepley const PetscSFNode *remotes; 951*3be36e83SMatthew G. Knepley PetscInt Nl, l; 952*3be36e83SMatthew G. Knepley PetscMPIInt rank; 953*3be36e83SMatthew G. Knepley PetscErrorCode ierr; 954*3be36e83SMatthew G. Knepley 955*3be36e83SMatthew G. Knepley PetscFunctionBegin; 956*3be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 957*3be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 958*3be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, &remotes);CHKERRQ(ierr); 959*3be36e83SMatthew G. Knepley if (Nl < 0) goto owned; 960*3be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 961*3be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 962*3be36e83SMatthew G. Knepley if (rootdegree[localPoint]) goto owned; 963*3be36e83SMatthew G. Knepley ierr = PetscFindInt(localPoint, Nl, locals, &l);CHKERRQ(ierr); 964*3be36e83SMatthew G. Knepley if (l < 0) PetscFunctionReturn(1); 965*3be36e83SMatthew G. Knepley *remotePoint = remotes[l]; 966*3be36e83SMatthew G. Knepley PetscFunctionReturn(0); 967*3be36e83SMatthew G. Knepley owned: 968*3be36e83SMatthew G. Knepley remotePoint->rank = rank; 969*3be36e83SMatthew G. Knepley remotePoint->index = localPoint; 970*3be36e83SMatthew G. Knepley PetscFunctionReturn(0); 971*3be36e83SMatthew G. Knepley } 972*3be36e83SMatthew G. Knepley 973*3be36e83SMatthew G. Knepley 974*3be36e83SMatthew G. Knepley static PetscErrorCode DMPlexPointIsShared(DM dm, PetscInt p, PetscBool *isShared) 975*3be36e83SMatthew G. Knepley { 976*3be36e83SMatthew G. Knepley PetscSF sf; 977*3be36e83SMatthew G. Knepley const PetscInt *locals, *rootdegree; 978*3be36e83SMatthew G. Knepley PetscInt Nl, idx; 979*3be36e83SMatthew G. Knepley PetscErrorCode ierr; 980*3be36e83SMatthew G. Knepley 981*3be36e83SMatthew G. Knepley PetscFunctionBegin; 982*3be36e83SMatthew G. Knepley *isShared = PETSC_FALSE; 983*3be36e83SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 984*3be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &Nl, &locals, NULL);CHKERRQ(ierr); 985*3be36e83SMatthew G. Knepley if (Nl < 0) PetscFunctionReturn(0); 986*3be36e83SMatthew G. Knepley ierr = PetscFindInt(p, Nl, locals, &idx);CHKERRQ(ierr); 987*3be36e83SMatthew G. Knepley if (idx >= 0) {*isShared = PETSC_TRUE; PetscFunctionReturn(0);} 988*3be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 989*3be36e83SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 990*3be36e83SMatthew G. Knepley if (rootdegree[p] > 0) *isShared = PETSC_TRUE; 991*3be36e83SMatthew G. Knepley PetscFunctionReturn(0); 992*3be36e83SMatthew G. Knepley } 993*3be36e83SMatthew G. Knepley 994*3be36e83SMatthew G. Knepley static PetscErrorCode DMPlexConeIsShared(DM dm, PetscInt p, PetscBool *isShared) 995*3be36e83SMatthew G. Knepley { 996*3be36e83SMatthew G. Knepley const PetscInt *cone; 997*3be36e83SMatthew G. Knepley PetscInt coneSize, c; 998*3be36e83SMatthew G. Knepley PetscBool cShared = PETSC_TRUE; 999*3be36e83SMatthew G. Knepley PetscErrorCode ierr; 1000*3be36e83SMatthew G. Knepley 1001*3be36e83SMatthew G. Knepley PetscFunctionBegin; 1002*3be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1003*3be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1004*3be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1005*3be36e83SMatthew G. Knepley PetscBool pointShared; 1006*3be36e83SMatthew G. Knepley 1007*3be36e83SMatthew G. Knepley ierr = DMPlexPointIsShared(dm, cone[c], &pointShared);CHKERRQ(ierr); 1008*3be36e83SMatthew G. Knepley cShared = (PetscBool) (cShared && pointShared); 1009*3be36e83SMatthew G. Knepley } 1010*3be36e83SMatthew G. Knepley *isShared = coneSize ? cShared : PETSC_FALSE; 1011*3be36e83SMatthew G. Knepley PetscFunctionReturn(0); 1012*3be36e83SMatthew G. Knepley } 1013*3be36e83SMatthew G. Knepley 1014*3be36e83SMatthew G. Knepley static PetscErrorCode DMPlexGetConeMinimum(DM dm, PetscInt p, PetscSFNode *cpmin) 1015*3be36e83SMatthew G. Knepley { 1016*3be36e83SMatthew G. Knepley const PetscInt *cone; 1017*3be36e83SMatthew G. Knepley PetscInt coneSize, c; 1018*3be36e83SMatthew G. Knepley PetscSFNode cmin = {PETSC_MAX_INT, PETSC_MAX_INT}, missing = {-1, -1}; 1019*3be36e83SMatthew G. Knepley PetscErrorCode ierr; 1020*3be36e83SMatthew G. Knepley 1021*3be36e83SMatthew G. Knepley PetscFunctionBegin; 1022*3be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1023*3be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1024*3be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1025*3be36e83SMatthew G. Knepley PetscSFNode rcp; 1026*3be36e83SMatthew G. Knepley 1027*3be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cone[c], &rcp); 1028*3be36e83SMatthew G. Knepley if (ierr) { 1029*3be36e83SMatthew G. Knepley cmin = missing; 1030*3be36e83SMatthew G. Knepley } else { 1031*3be36e83SMatthew G. Knepley cmin = (rcp.rank < cmin.rank) || (rcp.rank == cmin.rank && rcp.index < cmin.index) ? rcp : cmin; 1032*3be36e83SMatthew G. Knepley } 1033*3be36e83SMatthew G. Knepley } 1034*3be36e83SMatthew G. Knepley *cpmin = coneSize ? cmin : missing; 1035*3be36e83SMatthew G. Knepley PetscFunctionReturn(0); 1036*3be36e83SMatthew G. Knepley } 1037*3be36e83SMatthew G. Knepley 1038*3be36e83SMatthew G. Knepley static PetscErrorCode DMPlexCheckSharedFaces(DM dm) 1039*3be36e83SMatthew G. Knepley { 1040*3be36e83SMatthew G. Knepley PetscInt fStart, fEnd, f; 1041*3be36e83SMatthew G. Knepley PetscErrorCode ierr; 1042*3be36e83SMatthew G. Knepley 1043*3be36e83SMatthew G. Knepley PetscFunctionBegin; 1044*3be36e83SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 1045*3be36e83SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 1046*3be36e83SMatthew G. Knepley const PetscInt *cone; 1047*3be36e83SMatthew G. Knepley PetscInt coneSize, c; 1048*3be36e83SMatthew G. Knepley PetscBool faceShared, shouldShare = PETSC_TRUE; 1049*3be36e83SMatthew G. Knepley 1050*3be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 1051*3be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 1052*3be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1053*3be36e83SMatthew G. Knepley PetscBool pointShared; 1054*3be36e83SMatthew G. Knepley 1055*3be36e83SMatthew G. Knepley ierr = DMPlexPointIsShared(dm, cone[c], &pointShared);CHKERRQ(ierr); 1056*3be36e83SMatthew G. Knepley shouldShare = (PetscBool) (shouldShare && pointShared); 1057*3be36e83SMatthew G. Knepley } 1058*3be36e83SMatthew G. Knepley ierr = DMPlexPointIsShared(dm, f, &faceShared);CHKERRQ(ierr); 1059*3be36e83SMatthew G. Knepley if (faceShared && !shouldShare) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Face %D is shared, but its cone is not completely shared", f); 1060*3be36e83SMatthew G. Knepley if (!faceShared && shouldShare) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Face %D is not shared, but its cone is completely shared", f); 1061*3be36e83SMatthew G. Knepley } 1062*3be36e83SMatthew G. Knepley PetscFunctionReturn(0); 1063*3be36e83SMatthew G. Knepley } 1064*3be36e83SMatthew G. Knepley 1065*3be36e83SMatthew G. Knepley /* 1066*3be36e83SMatthew G. Knepley Each shared face has an entry in the candidates array: 1067*3be36e83SMatthew G. Knepley (-1, coneSize-1), {(global cone point)} 1068*3be36e83SMatthew G. Knepley where the set is missing the point p which we use as the key for the face 1069*3be36e83SMatthew G. Knepley */ 1070*3be36e83SMatthew G. Knepley static PetscErrorCode DMPlexAddSharedFace_Private(DM dm, PetscSection candidateSection, PetscSFNode candidates[], PetscHMapIJ faceHash, PetscInt p, PetscBool debug) 1071*3be36e83SMatthew G. Knepley { 1072*3be36e83SMatthew G. Knepley MPI_Comm comm; 1073*3be36e83SMatthew G. Knepley const PetscInt *support; 1074*3be36e83SMatthew G. Knepley PetscInt supportSize, s, off = 0, idx = 0; 1075*3be36e83SMatthew G. Knepley PetscMPIInt rank; 1076*3be36e83SMatthew G. Knepley PetscErrorCode ierr; 1077*3be36e83SMatthew G. Knepley 1078*3be36e83SMatthew G. Knepley PetscFunctionBegin; 1079*3be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1080*3be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1081*3be36e83SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1082*3be36e83SMatthew G. Knepley ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 1083*3be36e83SMatthew G. Knepley if (candidates) {ierr = PetscSectionGetOffset(candidateSection, p, &off);CHKERRQ(ierr);} 1084*3be36e83SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 1085*3be36e83SMatthew G. Knepley const PetscInt face = support[s]; 1086*3be36e83SMatthew G. Knepley const PetscInt *cone; 1087*3be36e83SMatthew G. Knepley PetscSFNode cpmin={-1,-1}, rp={-1,-1}; 1088*3be36e83SMatthew G. Knepley PetscInt coneSize, c, f; 1089*3be36e83SMatthew G. Knepley PetscBool isShared = PETSC_FALSE; 1090*3be36e83SMatthew G. Knepley PetscHashIJKey key; 1091*3be36e83SMatthew G. Knepley 1092*3be36e83SMatthew G. Knepley /* Only add point once */ 1093*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Support face %D\n", rank, face);CHKERRQ(ierr);} 1094*3be36e83SMatthew G. Knepley key.i = p; 1095*3be36e83SMatthew G. Knepley key.j = face; 1096*3be36e83SMatthew G. Knepley ierr = PetscHMapIJGet(faceHash, key, &f);CHKERRQ(ierr); 1097*3be36e83SMatthew G. Knepley if (f >= 0) continue; 1098*3be36e83SMatthew G. Knepley ierr = DMPlexConeIsShared(dm, face, &isShared);CHKERRQ(ierr); 1099*3be36e83SMatthew G. Knepley ierr = DMPlexGetConeMinimum(dm, face, &cpmin);CHKERRQ(ierr); 1100*3be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, p, &rp);CHKERRQ(ierr); 1101*3be36e83SMatthew G. Knepley if (debug) { 1102*3be36e83SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] Face point %D is shared: %d\n", rank, face, (int) isShared);CHKERRQ(ierr); 1103*3be36e83SMatthew 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); 1104*3be36e83SMatthew G. Knepley } 1105*3be36e83SMatthew G. Knepley if (isShared && (rp.rank == cpmin.rank && rp.index == cpmin.index)) { 1106*3be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 1107*3be36e83SMatthew G. Knepley if (candidates) { 1108*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Adding shared face %D at idx %D\n[%d] ", rank, face, idx, rank);CHKERRQ(ierr);} 1109*3be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 1110*3be36e83SMatthew G. Knepley ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 1111*3be36e83SMatthew G. Knepley candidates[off+idx].rank = -1; 1112*3be36e83SMatthew G. Knepley candidates[off+idx++].index = coneSize-1; 1113*3be36e83SMatthew G. Knepley candidates[off+idx].rank = rank; 1114*3be36e83SMatthew G. Knepley candidates[off+idx++].index = face; 1115*3be36e83SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1116*3be36e83SMatthew G. Knepley const PetscInt cp = cone[c]; 1117*3be36e83SMatthew G. Knepley 1118*3be36e83SMatthew G. Knepley if (cp == p) continue; 1119*3be36e83SMatthew G. Knepley ierr = DMPlexMapToGlobalPoint(dm, cp, &candidates[off+idx]);CHKERRQ(ierr); 1120*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, " (%D,%D)", candidates[off+idx].rank, candidates[off+idx].index);CHKERRQ(ierr);} 1121*3be36e83SMatthew G. Knepley ++idx; 1122*3be36e83SMatthew G. Knepley } 1123*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "\n");CHKERRQ(ierr);} 1124*3be36e83SMatthew G. Knepley } else { 1125*3be36e83SMatthew G. Knepley /* Add cone size to section */ 1126*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Scheduling shared face %D\n", rank, face);CHKERRQ(ierr);} 1127*3be36e83SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 1128*3be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(faceHash, key, p);CHKERRQ(ierr); 1129*3be36e83SMatthew G. Knepley ierr = PetscSectionAddDof(candidateSection, p, coneSize+1);CHKERRQ(ierr); 1130*3be36e83SMatthew G. Knepley } 1131*3be36e83SMatthew G. Knepley } 1132*3be36e83SMatthew G. Knepley } 1133*3be36e83SMatthew G. Knepley PetscFunctionReturn(0); 1134*3be36e83SMatthew G. Knepley } 1135*3be36e83SMatthew G. Knepley 11362e72742cSMatthew G. Knepley /*@ 11372e72742cSMatthew G. Knepley DMPlexInterpolatePointSF - Insert interpolated points in the overlap into the PointSF in parallel, following local interpolation 11382e72742cSMatthew G. Knepley 1139d083f849SBarry Smith Collective on dm 11402e72742cSMatthew G. Knepley 11412e72742cSMatthew G. Knepley Input Parameters: 11422e72742cSMatthew G. Knepley + dm - The interpolated DM 11432e72742cSMatthew G. Knepley - pointSF - The initial SF without interpolated points 11442e72742cSMatthew G. Knepley 11452e72742cSMatthew G. Knepley Output Parameter: 11462e72742cSMatthew G. Knepley . pointSF - The SF including interpolated points 11472e72742cSMatthew G. Knepley 1148f0cfc026SVaclav Hapla Level: developer 11492e72742cSMatthew G. Knepley 11502e72742cSMatthew 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 11512e72742cSMatthew G. Knepley 11522e72742cSMatthew G. Knepley .seealso: DMPlexInterpolate(), DMPlexUninterpolate() 11532e72742cSMatthew G. Knepley @*/ 1154e53487d3SMatthew G. Knepley PetscErrorCode DMPlexInterpolatePointSF(DM dm, PetscSF pointSF) 11552e72742cSMatthew G. Knepley { 1156*3be36e83SMatthew G. Knepley MPI_Comm comm; 1157*3be36e83SMatthew G. Knepley PetscHMapIJ remoteHash; 1158*3be36e83SMatthew G. Knepley PetscHMapI claimshash; 1159*3be36e83SMatthew G. Knepley PetscSection candidateSection, candidateRemoteSection, claimSection; 1160*3be36e83SMatthew G. Knepley PetscSFNode *candidates, *candidatesRemote, *claims; 11612e72742cSMatthew G. Knepley const PetscInt *localPoints, *rootdegree; 11622e72742cSMatthew G. Knepley const PetscSFNode *remotePoints; 1163*3be36e83SMatthew G. Knepley PetscInt ov, Nr, r, Nl, l; 1164*3be36e83SMatthew G. Knepley PetscInt candidatesSize, candidatesRemoteSize, claimsSize; 1165*3be36e83SMatthew G. Knepley PetscBool flg, debug = PETSC_FALSE; 1166f0cfc026SVaclav Hapla PetscMPIInt rank; 11672e72742cSMatthew G. Knepley PetscErrorCode ierr; 11682e72742cSMatthew G. Knepley 11692e72742cSMatthew G. Knepley PetscFunctionBegin; 1170f0cfc026SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1171*3be36e83SMatthew G. Knepley PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 3); 1172f0cfc026SVaclav Hapla ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr); 1173f0cfc026SVaclav Hapla if (!flg) PetscFunctionReturn(0); 1174*3be36e83SMatthew G. Knepley /* Set initial SF so that lower level queries work */ 1175*3be36e83SMatthew G. Knepley ierr = DMSetPointSF(dm, pointSF);CHKERRQ(ierr); 1176*3be36e83SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1177*3be36e83SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1178*3be36e83SMatthew G. Knepley ierr = DMPlexGetOverlap(dm, &ov);CHKERRQ(ierr); 1179*3be36e83SMatthew G. Knepley if (ov) SETERRQ(comm, PETSC_ERR_SUP, "Interpolation of overlapped DMPlex not implemented yet"); 1180*3be36e83SMatthew G. Knepley ierr = PetscOptionsHasName(NULL, ((PetscObject) dm)->prefix, "-dmplex_interp_debug", &debug);CHKERRQ(ierr); 11812e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_interp_pre_view");CHKERRQ(ierr); 11822e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) pointSF, NULL, "-petscsf_interp_pre_view");CHKERRQ(ierr); 118325afeb17SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 1184*3be36e83SMatthew G. Knepley /* Step 0: Precalculations */ 1185*3be36e83SMatthew G. Knepley ierr = PetscSFGetGraph(pointSF, &Nr, &Nl, &localPoints, &remotePoints);CHKERRQ(ierr); 1186*3be36e83SMatthew G. Knepley if (Nr < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but input PointSF has no graph set"); 1187*3be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&remoteHash);CHKERRQ(ierr); 1188*3be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1189*3be36e83SMatthew G. Knepley PetscHashIJKey key; 11902e72742cSMatthew G. Knepley key.i = remotePoints[l].index; 11912e72742cSMatthew G. Knepley key.j = remotePoints[l].rank; 1192*3be36e83SMatthew G. Knepley ierr = PetscHMapIJSet(remoteHash, key, l);CHKERRQ(ierr); 11937bffde78SMichael Lange } 119466aa2a39SMatthew G. Knepley /* Compute root degree to identify shared points */ 11952e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 11962e72742cSMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 1197*3be36e83SMatthew G. Knepley ierr = IntArrayViewFromOptions(comm, "-interp_root_degree_view", "Root degree", "point", "degree", Nr, rootdegree);CHKERRQ(ierr); 1198*3be36e83SMatthew G. Knepley /* 1199*3be36e83SMatthew G. Knepley 1) Loop over each leaf point $p$ at depth $d$ in the SF 1200*3be36e83SMatthew G. Knepley \item Get set $F(p)$ of faces $f$ in the support of $p$ for which 1201*3be36e83SMatthew G. Knepley \begin{itemize} 1202*3be36e83SMatthew G. Knepley \item all cone points of $f$ are shared 1203*3be36e83SMatthew G. Knepley \item $p$ is the cone point with smallest canonical number 1204*3be36e83SMatthew G. Knepley \end{itemize} 1205*3be36e83SMatthew G. Knepley \item Send $F(p)$ and the cone of each face to the active root point $r(p)$ 1206*3be36e83SMatthew 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 1207*3be36e83SMatthew G. Knepley \item Send the root face from the root back to all leaf process 1208*3be36e83SMatthew G. Knepley \item Leaf processes add the shared face to the SF 1209*3be36e83SMatthew G. Knepley */ 1210*3be36e83SMatthew G. Knepley /* Step 1: Construct section+SFNode array 1211*3be36e83SMatthew G. Knepley The section has entries for all shared faces for which we have a leaf point in the cone 1212*3be36e83SMatthew G. Knepley The array holds candidate shared faces, each face is refered to by the leaf point */ 1213*3be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateSection);CHKERRQ(ierr); 1214*3be36e83SMatthew G. Knepley ierr = PetscSectionSetChart(candidateSection, 0, Nr);CHKERRQ(ierr); 12157bffde78SMichael Lange { 1216*3be36e83SMatthew G. Knepley PetscHMapIJ faceHash; 12172e72742cSMatthew G. Knepley 1218*3be36e83SMatthew G. Knepley ierr = PetscHMapIJCreate(&faceHash);CHKERRQ(ierr); 1219*3be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1220*3be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 12212e72742cSMatthew G. Knepley 1222*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] First pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 1223*3be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, NULL, faceHash, p, debug);CHKERRQ(ierr); 12242e72742cSMatthew G. Knepley } 1225*3be36e83SMatthew G. Knepley ierr = PetscHMapIJClear(faceHash);CHKERRQ(ierr); 12267bffde78SMichael Lange ierr = PetscSectionSetUp(candidateSection);CHKERRQ(ierr); 12277bffde78SMichael Lange ierr = PetscSectionGetStorageSize(candidateSection, &candidatesSize);CHKERRQ(ierr); 12287bffde78SMichael Lange ierr = PetscMalloc1(candidatesSize, &candidates);CHKERRQ(ierr); 1229*3be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1230*3be36e83SMatthew G. Knepley const PetscInt p = localPoints[l]; 12312e72742cSMatthew G. Knepley 1232*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Second pass leaf point %D\n", rank, p);CHKERRQ(ierr);} 1233*3be36e83SMatthew G. Knepley ierr = DMPlexAddSharedFace_Private(dm, candidateSection, candidates, faceHash, p, debug);CHKERRQ(ierr); 12342e72742cSMatthew G. Knepley } 1235*3be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&faceHash);CHKERRQ(ierr); 1236*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 12377bffde78SMichael Lange } 1238*3be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateSection, "Candidate Section");CHKERRQ(ierr); 12392e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateSection, NULL, "-petscsection_interp_candidate_view");CHKERRQ(ierr); 1240*3be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_view", "Candidates", NULL, candidatesSize, candidates);CHKERRQ(ierr); 1241*3be36e83SMatthew G. Knepley /* Step 2: Gather candidate section / array pair into the root partition via inverse(multi(pointSF)). */ 12422e72742cSMatthew G. Knepley /* Note that this section is indexed by offsets into leaves, not by point number */ 12437bffde78SMichael Lange { 12447bffde78SMichael Lange PetscSF sfMulti, sfInverse, sfCandidates; 12457bffde78SMichael Lange PetscInt *remoteOffsets; 12462e72742cSMatthew G. Knepley 12477bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 12487bffde78SMichael Lange ierr = PetscSFCreateInverseSF(sfMulti, &sfInverse);CHKERRQ(ierr); 1249*3be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &candidateRemoteSection);CHKERRQ(ierr); 1250*3be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfInverse, candidateSection, &remoteOffsets, candidateRemoteSection);CHKERRQ(ierr); 1251*3be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfInverse, candidateSection, remoteOffsets, candidateRemoteSection, &sfCandidates);CHKERRQ(ierr); 1252*3be36e83SMatthew G. Knepley ierr = PetscSectionGetStorageSize(candidateRemoteSection, &candidatesRemoteSize);CHKERRQ(ierr); 12537bffde78SMichael Lange ierr = PetscMalloc1(candidatesRemoteSize, &candidatesRemote);CHKERRQ(ierr); 12547bffde78SMichael Lange ierr = PetscSFBcastBegin(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr); 12557bffde78SMichael Lange ierr = PetscSFBcastEnd(sfCandidates, MPIU_2INT, candidates, candidatesRemote);CHKERRQ(ierr); 12567bffde78SMichael Lange ierr = PetscSFDestroy(&sfInverse);CHKERRQ(ierr); 12577bffde78SMichael Lange ierr = PetscSFDestroy(&sfCandidates);CHKERRQ(ierr); 12587bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 12592e72742cSMatthew G. Knepley 1260*3be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) candidateRemoteSection, "Remote Candidate Section");CHKERRQ(ierr); 1261*3be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) candidateRemoteSection, NULL, "-petscsection_interp_candidate_remote_view");CHKERRQ(ierr); 1262*3be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_candidate_remote_view", "Remote Candidates", NULL, candidatesRemoteSize, candidatesRemote);CHKERRQ(ierr); 12637bffde78SMichael Lange } 1264*3be36e83SMatthew 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 */ 12657bffde78SMichael Lange { 1266*3be36e83SMatthew G. Knepley PetscHashIJKLRemote faceTable; 1267*3be36e83SMatthew G. Knepley PetscInt idx, idx2; 1268*3be36e83SMatthew G. Knepley 1269*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteCreate(&faceTable);CHKERRQ(ierr); 12702e72742cSMatthew G. Knepley /* There is a section point for every leaf attached to a given root point */ 1271*3be36e83SMatthew G. Knepley for (r = 0, idx = 0, idx2 = 0; r < Nr; ++r) { 12722e72742cSMatthew G. Knepley PetscInt deg; 1273*3be36e83SMatthew G. Knepley 12742e72742cSMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx) { 12752e72742cSMatthew G. Knepley PetscInt offset, dof, d; 12762e72742cSMatthew G. Knepley 1277*3be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx, &dof);CHKERRQ(ierr); 1278*3be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx, &offset);CHKERRQ(ierr); 1279*3be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 12802e72742cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1281*3be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 1282*3be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 1283*3be36e83SMatthew G. Knepley const PetscSFNode rface = candidatesRemote[hidx+1]; 1284*3be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 1285*3be36e83SMatthew G. Knepley PetscSFNode fcp0; 1286*3be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 12872e72742cSMatthew G. Knepley const PetscInt *join = NULL; 1288*3be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 1289*3be36e83SMatthew G. Knepley PetscHashIter iter; 1290*3be36e83SMatthew G. Knepley PetscBool missing; 12912e72742cSMatthew G. Knepley PetscInt points[1024], p, joinSize; 12922e72742cSMatthew G. Knepley 1293*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking face (%D, %D) at (%D, %D, %D) with cone size %D\n", rank, rface.index, rface.rank, r, idx, d, Np);CHKERRQ(ierr);} 1294*3be36e83SMatthew G. Knepley if (Np > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np); 1295*3be36e83SMatthew G. Knepley fcp0.rank = rank; 1296*3be36e83SMatthew G. Knepley fcp0.index = r; 1297*3be36e83SMatthew G. Knepley d += Np; 1298*3be36e83SMatthew G. Knepley /* Put remote face in hash table */ 1299*3be36e83SMatthew G. Knepley key.i = fcp0; 1300*3be36e83SMatthew G. Knepley key.j = fcone[0]; 1301*3be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 1302*3be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 1303*3be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 1304*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 1305*3be36e83SMatthew G. Knepley if (missing) { 1306*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Setting remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 1307*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 1308*3be36e83SMatthew G. Knepley } else { 1309*3be36e83SMatthew G. Knepley PetscSFNode oface; 1310*3be36e83SMatthew G. Knepley 1311*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 1312*3be36e83SMatthew G. Knepley if ((rface.rank < oface.rank) || (rface.rank == oface.rank && rface.index < oface.index)) { 1313*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Replacing with remote face (%D, %D)\n", rank, rface.index, rface.rank);CHKERRQ(ierr);} 1314*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, rface);CHKERRQ(ierr); 1315*3be36e83SMatthew G. Knepley } 1316*3be36e83SMatthew G. Knepley } 1317*3be36e83SMatthew G. Knepley /* Check for local face */ 13182e72742cSMatthew G. Knepley points[0] = r; 1319*3be36e83SMatthew G. Knepley for (p = 1; p < Np; ++p) { 1320*3be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, fcone[p-1], &points[p]); 1321*3be36e83SMatthew G. Knepley if (ierr) break; /* We got a point not in our overlap */ 1322*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Checking local candidate %D\n", rank, points[p]);CHKERRQ(ierr);} 13237bffde78SMichael Lange } 13242e72742cSMatthew G. Knepley if (ierr) continue; 1325*3be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 13267bffde78SMichael Lange if (joinSize == 1) { 1327*3be36e83SMatthew G. Knepley PetscSFNode lface; 1328*3be36e83SMatthew G. Knepley PetscSFNode oface; 1329*3be36e83SMatthew G. Knepley 1330*3be36e83SMatthew G. Knepley /* Always replace with local face */ 1331*3be36e83SMatthew G. Knepley lface.rank = rank; 1332*3be36e83SMatthew G. Knepley lface.index = join[0]; 1333*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &oface);CHKERRQ(ierr); 1334*3be36e83SMatthew 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);} 1335*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteIterSet(faceTable, iter, lface);CHKERRQ(ierr); 13367bffde78SMichael Lange } 1337*3be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np, points, &joinSize, &join);CHKERRQ(ierr); 1338*3be36e83SMatthew G. Knepley } 1339*3be36e83SMatthew G. Knepley } 1340*3be36e83SMatthew G. Knepley /* Put back faces for this root */ 1341*3be36e83SMatthew G. Knepley for (deg = 0; deg < rootdegree[r]; ++deg, ++idx2) { 1342*3be36e83SMatthew G. Knepley PetscInt offset, dof, d; 1343*3be36e83SMatthew G. Knepley 1344*3be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateRemoteSection, idx2, &dof);CHKERRQ(ierr); 1345*3be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateRemoteSection, idx2, &offset);CHKERRQ(ierr); 1346*3be36e83SMatthew G. Knepley /* dof may include many faces from the remote process */ 1347*3be36e83SMatthew G. Knepley for (d = 0; d < dof; ++d) { 1348*3be36e83SMatthew G. Knepley const PetscInt hidx = offset+d; 1349*3be36e83SMatthew G. Knepley const PetscInt Np = candidatesRemote[hidx].index+1; 1350*3be36e83SMatthew G. Knepley const PetscSFNode *fcone = &candidatesRemote[hidx+2]; 1351*3be36e83SMatthew G. Knepley PetscSFNode fcp0; 1352*3be36e83SMatthew G. Knepley const PetscSFNode pmax = {PETSC_MAX_INT, PETSC_MAX_INT}; 1353*3be36e83SMatthew G. Knepley PetscHashIJKLRemoteKey key; 1354*3be36e83SMatthew G. Knepley PetscHashIter iter; 1355*3be36e83SMatthew G. Knepley PetscBool missing; 1356*3be36e83SMatthew G. Knepley 1357*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Entering face at (%D, %D)\n", rank, r, idx);CHKERRQ(ierr);} 1358*3be36e83SMatthew G. Knepley if (Np > 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle faces with %D cone points", Np); 1359*3be36e83SMatthew G. Knepley fcp0.rank = rank; 1360*3be36e83SMatthew G. Knepley fcp0.index = r; 1361*3be36e83SMatthew G. Knepley d += Np; 1362*3be36e83SMatthew G. Knepley /* Find remote face in hash table */ 1363*3be36e83SMatthew G. Knepley key.i = fcp0; 1364*3be36e83SMatthew G. Knepley key.j = fcone[0]; 1365*3be36e83SMatthew G. Knepley key.k = Np > 2 ? fcone[1] : pmax; 1366*3be36e83SMatthew G. Knepley key.l = Np > 3 ? fcone[2] : pmax; 1367*3be36e83SMatthew G. Knepley ierr = PetscSortSFNode(Np, (PetscSFNode *) &key);CHKERRQ(ierr); 1368*3be36e83SMatthew 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);} 1369*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemotePut(faceTable, key, &iter, &missing);CHKERRQ(ierr); 1370*3be36e83SMatthew G. Knepley if (missing) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Root %D Idx %D ought to have an assoicated face", r, idx2); 1371*3be36e83SMatthew G. Knepley else {ierr = PetscHashIJKLRemoteIterGet(faceTable, iter, &candidatesRemote[hidx]);CHKERRQ(ierr);} 13727bffde78SMichael Lange } 13737bffde78SMichael Lange } 13747bffde78SMichael Lange } 13752e72742cSMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), NULL);CHKERRQ(ierr);} 1376*3be36e83SMatthew G. Knepley ierr = PetscHashIJKLRemoteDestroy(&faceTable);CHKERRQ(ierr); 13777bffde78SMichael Lange } 1378*3be36e83SMatthew G. Knepley /* Step 4: Push back owned faces */ 13797bffde78SMichael Lange { 13807bffde78SMichael Lange PetscSF sfMulti, sfClaims, sfPointNew; 13817bffde78SMichael Lange PetscSFNode *remotePointsNew; 13822e72742cSMatthew G. Knepley PetscInt *remoteOffsets, *localPointsNew; 1383*3be36e83SMatthew G. Knepley PetscInt pStart, pEnd, r, NlNew, p; 13842e72742cSMatthew G. Knepley 1385*3be36e83SMatthew G. Knepley /* 4) Push claims back to receiver via the MultiSF and derive new pointSF mapping on receiver */ 13867bffde78SMichael Lange ierr = PetscSFGetMultiSF(pointSF, &sfMulti);CHKERRQ(ierr); 1387*3be36e83SMatthew G. Knepley ierr = PetscSectionCreate(comm, &claimSection);CHKERRQ(ierr); 1388*3be36e83SMatthew G. Knepley ierr = PetscSFDistributeSection(sfMulti, candidateRemoteSection, &remoteOffsets, claimSection);CHKERRQ(ierr); 1389*3be36e83SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfMulti, candidateRemoteSection, remoteOffsets, claimSection, &sfClaims);CHKERRQ(ierr); 13902e72742cSMatthew G. Knepley ierr = PetscSectionGetStorageSize(claimSection, &claimsSize);CHKERRQ(ierr); 13912e72742cSMatthew G. Knepley ierr = PetscMalloc1(claimsSize, &claims);CHKERRQ(ierr); 1392*3be36e83SMatthew G. Knepley for (p = 0; p < claimsSize; ++p) claims[p].rank = -1; 13937bffde78SMichael Lange ierr = PetscSFBcastBegin(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr); 13947bffde78SMichael Lange ierr = PetscSFBcastEnd(sfClaims, MPIU_2INT, candidatesRemote, claims);CHKERRQ(ierr); 13957bffde78SMichael Lange ierr = PetscSFDestroy(&sfClaims);CHKERRQ(ierr); 13967bffde78SMichael Lange ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 1397*3be36e83SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) claimSection, "Claim Section");CHKERRQ(ierr); 13982e72742cSMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) claimSection, NULL, "-petscsection_interp_claim_view");CHKERRQ(ierr); 1399*3be36e83SMatthew G. Knepley ierr = SFNodeArrayViewFromOptions(comm, "-petscsection_interp_claim_view", "Claims", NULL, claimsSize, claims);CHKERRQ(ierr); 1400*3be36e83SMatthew G. Knepley /* Step 5) Walk the original section of local supports and add an SF entry for each updated item */ 1401*3be36e83SMatthew 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 */ 1402e8f14785SLisandro Dalcin ierr = PetscHMapICreate(&claimshash);CHKERRQ(ierr); 1403*3be36e83SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1404*3be36e83SMatthew G. Knepley PetscInt dof, off, d; 14052e72742cSMatthew G. Knepley 1406*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Checking root for claims %D\n", rank, r);CHKERRQ(ierr);} 1407*3be36e83SMatthew G. Knepley ierr = PetscSectionGetDof(candidateSection, r, &dof);CHKERRQ(ierr); 1408*3be36e83SMatthew G. Knepley ierr = PetscSectionGetOffset(candidateSection, r, &off);CHKERRQ(ierr); 14092e72742cSMatthew G. Knepley for (d = 0; d < dof;) { 1410*3be36e83SMatthew G. Knepley if (claims[off+d].rank >= 0) { 1411*3be36e83SMatthew G. Knepley const PetscInt faceInd = off+d; 1412*3be36e83SMatthew G. Knepley const PetscInt Np = candidates[off+d].index; 14132e72742cSMatthew G. Knepley const PetscInt *join = NULL; 14142e72742cSMatthew G. Knepley PetscInt joinSize, points[1024], c; 14152e72742cSMatthew G. Knepley 1416*3be36e83SMatthew 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);} 1417*3be36e83SMatthew G. Knepley points[0] = r; 1418*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[0]);CHKERRQ(ierr);} 1419*3be36e83SMatthew G. Knepley for (c = 0, d += 2; c < Np; ++c, ++d) { 1420*3be36e83SMatthew G. Knepley ierr = DMPlexMapToLocalPoint(dm, remoteHash, candidates[off+d], &points[c+1]);CHKERRQ(ierr); 1421*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] point %D\n", rank, points[c+1]);CHKERRQ(ierr);} 14222e72742cSMatthew G. Knepley } 1423*3be36e83SMatthew G. Knepley ierr = DMPlexGetJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 14242e72742cSMatthew G. Knepley if (joinSize == 1) { 1425*3be36e83SMatthew G. Knepley if (claims[faceInd].rank == rank) { 1426*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Ignoring local face %D for non-remote partner\n", rank, join[0]);CHKERRQ(ierr);} 1427*3be36e83SMatthew G. Knepley } else { 1428*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Found local face %D\n", rank, join[0]);CHKERRQ(ierr);} 14292e72742cSMatthew G. Knepley ierr = PetscHMapISet(claimshash, join[0], faceInd);CHKERRQ(ierr); 14302e72742cSMatthew G. Knepley } 1431*3be36e83SMatthew G. Knepley } else { 1432*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] Failed to find face\n", rank);CHKERRQ(ierr);} 1433*3be36e83SMatthew G. Knepley } 1434*3be36e83SMatthew G. Knepley ierr = DMPlexRestoreJoin(dm, Np+1, points, &joinSize, &join);CHKERRQ(ierr); 1435*3be36e83SMatthew G. Knepley } else { 1436*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedPrintf(comm, "[%d] No claim for point %D\n", rank, r);CHKERRQ(ierr);} 1437*3be36e83SMatthew G. Knepley d += claims[off+d].index+1; 14387bffde78SMichael Lange } 14397bffde78SMichael Lange } 1440*3be36e83SMatthew G. Knepley } 1441*3be36e83SMatthew G. Knepley if (debug) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 1442*3be36e83SMatthew G. Knepley /* Step 6) Create new pointSF from hashed claims */ 1443*3be36e83SMatthew G. Knepley ierr = PetscHMapIGetSize(claimshash, &NlNew);CHKERRQ(ierr); 14447bffde78SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1445*3be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &localPointsNew);CHKERRQ(ierr); 1446*3be36e83SMatthew G. Knepley ierr = PetscMalloc1(Nl + NlNew, &remotePointsNew);CHKERRQ(ierr); 1447*3be36e83SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1448*3be36e83SMatthew G. Knepley localPointsNew[l] = localPoints[l]; 1449*3be36e83SMatthew G. Knepley remotePointsNew[l].index = remotePoints[l].index; 1450*3be36e83SMatthew G. Knepley remotePointsNew[l].rank = remotePoints[l].rank; 14517bffde78SMichael Lange } 1452*3be36e83SMatthew G. Knepley p = Nl; 1453e8f14785SLisandro Dalcin ierr = PetscHMapIGetKeys(claimshash, &p, localPointsNew);CHKERRQ(ierr); 1454*3be36e83SMatthew G. Knepley /* We sort new points, and assume they are numbered after all existing points */ 1455*3be36e83SMatthew G. Knepley ierr = PetscSortInt(NlNew, &localPointsNew[Nl]);CHKERRQ(ierr); 1456*3be36e83SMatthew G. Knepley for (p = Nl; p < Nl + NlNew; ++p) { 1457*3be36e83SMatthew G. Knepley PetscInt off; 1458*3be36e83SMatthew G. Knepley ierr = PetscHMapIGet(claimshash, localPointsNew[p], &off);CHKERRQ(ierr); 1459*3be36e83SMatthew 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); 1460*3be36e83SMatthew G. Knepley remotePointsNew[p] = claims[off]; 14617bffde78SMichael Lange } 1462*3be36e83SMatthew G. Knepley ierr = PetscSFCreate(comm, &sfPointNew);CHKERRQ(ierr); 1463*3be36e83SMatthew G. Knepley ierr = PetscSFSetGraph(sfPointNew, pEnd-pStart, Nl+NlNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 1464*3be36e83SMatthew G. Knepley ierr = PetscSFSetUp(sfPointNew);CHKERRQ(ierr); 14657bffde78SMichael Lange ierr = DMSetPointSF(dm, sfPointNew);CHKERRQ(ierr); 1466*3be36e83SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) sfPointNew, NULL, "-petscsf_interp_view");CHKERRQ(ierr); 14677bffde78SMichael Lange ierr = PetscSFDestroy(&sfPointNew);CHKERRQ(ierr); 1468e8f14785SLisandro Dalcin ierr = PetscHMapIDestroy(&claimshash);CHKERRQ(ierr); 14697bffde78SMichael Lange } 1470*3be36e83SMatthew G. Knepley ierr = PetscHMapIJDestroy(&remoteHash);CHKERRQ(ierr); 14717bffde78SMichael Lange ierr = PetscSectionDestroy(&candidateSection);CHKERRQ(ierr); 1472*3be36e83SMatthew G. Knepley ierr = PetscSectionDestroy(&candidateRemoteSection);CHKERRQ(ierr); 14737bffde78SMichael Lange ierr = PetscSectionDestroy(&claimSection);CHKERRQ(ierr); 14747bffde78SMichael Lange ierr = PetscFree(candidates);CHKERRQ(ierr); 14757bffde78SMichael Lange ierr = PetscFree(candidatesRemote);CHKERRQ(ierr); 14767bffde78SMichael Lange ierr = PetscFree(claims);CHKERRQ(ierr); 147725afeb17SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolateSF,dm,0,0,0);CHKERRQ(ierr); 14787bffde78SMichael Lange PetscFunctionReturn(0); 14797bffde78SMichael Lange } 14807bffde78SMichael Lange 1481248eb259SVaclav Hapla /*@ 148280330477SMatthew G. Knepley DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. 148380330477SMatthew G. Knepley 1484d083f849SBarry Smith Collective on dm 148580330477SMatthew G. Knepley 1486e56d480eSMatthew G. Knepley Input Parameters: 1487e56d480eSMatthew G. Knepley + dm - The DMPlex object with only cells and vertices 148810a67516SMatthew G. Knepley - dmInt - The interpolated DM 148980330477SMatthew G. Knepley 149080330477SMatthew G. Knepley Output Parameter: 14914e3744c5SMatthew G. Knepley . dmInt - The complete DMPlex object 149280330477SMatthew G. Knepley 149380330477SMatthew G. Knepley Level: intermediate 149480330477SMatthew G. Knepley 149595452b02SPatrick Sanan Notes: 149695452b02SPatrick Sanan It does not copy over the coordinates. 149743eeeb2dSStefano Zampini 14989ade3219SVaclav Hapla Developer Notes: 14999ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_FULL. 15009ade3219SVaclav Hapla 150143eeeb2dSStefano Zampini .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellList(), DMPlexCopyCoordinates() 150280330477SMatthew G. Knepley @*/ 15039f074e33SMatthew G Knepley PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) 15049f074e33SMatthew G Knepley { 1505a7748839SVaclav Hapla DMPlexInterpolatedFlag interpolated; 15069a5b13a2SMatthew G Knepley DM idm, odm = dm; 15077bffde78SMichael Lange PetscSF sfPoint; 15082e1b13c2SMatthew G. Knepley PetscInt depth, dim, d; 150910a67516SMatthew G. Knepley const char *name; 1510b325530aSVaclav Hapla PetscBool flg=PETSC_TRUE; 15119f074e33SMatthew G Knepley PetscErrorCode ierr; 15129f074e33SMatthew G Knepley 15139f074e33SMatthew G Knepley PetscFunctionBegin; 151410a67516SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 151510a67516SMatthew G. Knepley PetscValidPointer(dmInt, 2); 1516a72f3261SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 15172e1b13c2SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1518c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1519827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1520827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1521827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_FULL) { 152276b791aaSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 152376b791aaSMatthew G. Knepley idm = dm; 1524b21b8912SMatthew G. Knepley } else { 15259a5b13a2SMatthew G Knepley for (d = 1; d < dim; ++d) { 15269a5b13a2SMatthew G Knepley /* Create interpolated mesh */ 152710a67516SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 15289a5b13a2SMatthew G Knepley ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 1529c73cfb54SMatthew G. Knepley ierr = DMSetDimension(idm, dim);CHKERRQ(ierr); 15307bffde78SMichael Lange if (depth > 0) { 15317bffde78SMichael Lange ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr); 15327bffde78SMichael Lange ierr = DMGetPointSF(odm, &sfPoint);CHKERRQ(ierr); 153394488200SVaclav Hapla { 1534*3be36e83SMatthew G. Knepley /* TODO: We need to systematically fix cases of distributed Plexes with no graph set */ 153594488200SVaclav Hapla PetscInt nroots; 153694488200SVaclav Hapla ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 153794488200SVaclav Hapla if (nroots >= 0) {ierr = DMPlexInterpolatePointSF(idm, sfPoint);CHKERRQ(ierr);} 153894488200SVaclav Hapla } 15397bffde78SMichael Lange } 15409a5b13a2SMatthew G Knepley if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);} 15419a5b13a2SMatthew G Knepley odm = idm; 15429f074e33SMatthew G Knepley } 154310a67516SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 154410a67516SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) idm, name);CHKERRQ(ierr); 154510a67516SMatthew G. Knepley ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr); 15465d80c0bfSVaclav Hapla ierr = DMCopyLabels(dm, idm, PETSC_COPY_VALUES, PETSC_FALSE);CHKERRQ(ierr); 1547b325530aSVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_interpolate_orient_interfaces", &flg, NULL);CHKERRQ(ierr); 154827d0e99aSVaclav Hapla if (flg) {ierr = DMPlexOrientInterface_Internal(idm);CHKERRQ(ierr);} 154984699f70SSatish Balay } 155043eeeb2dSStefano Zampini { 155143eeeb2dSStefano Zampini PetscBool isper; 155243eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 155343eeeb2dSStefano Zampini const DMBoundaryType *bd; 155443eeeb2dSStefano Zampini 155543eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 155643eeeb2dSStefano Zampini ierr = DMSetPeriodicity(idm,isper,maxCell,L,bd);CHKERRQ(ierr); 155743eeeb2dSStefano Zampini } 1558827c4036SVaclav Hapla /* This function makes the mesh fully interpolated on all ranks */ 1559827c4036SVaclav Hapla { 1560d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) idm->data; 1561827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_FULL; 1562827c4036SVaclav Hapla } 15639a5b13a2SMatthew G Knepley *dmInt = idm; 1564a72f3261SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); 15659f074e33SMatthew G Knepley PetscFunctionReturn(0); 15669f074e33SMatthew G Knepley } 156707b0a1fcSMatthew G Knepley 156880330477SMatthew G. Knepley /*@ 156980330477SMatthew G. Knepley DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices 157080330477SMatthew G. Knepley 1571d083f849SBarry Smith Collective on dmA 157280330477SMatthew G. Knepley 157380330477SMatthew G. Knepley Input Parameter: 157480330477SMatthew G. Knepley . dmA - The DMPlex object with initial coordinates 157580330477SMatthew G. Knepley 157680330477SMatthew G. Knepley Output Parameter: 157780330477SMatthew G. Knepley . dmB - The DMPlex object with copied coordinates 157880330477SMatthew G. Knepley 157980330477SMatthew G. Knepley Level: intermediate 158080330477SMatthew G. Knepley 158180330477SMatthew G. Knepley Note: This is typically used when adding pieces other than vertices to a mesh 158280330477SMatthew G. Knepley 158365f90189SJed Brown .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 158480330477SMatthew G. Knepley @*/ 158507b0a1fcSMatthew G Knepley PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) 158607b0a1fcSMatthew G Knepley { 158707b0a1fcSMatthew G Knepley Vec coordinatesA, coordinatesB; 158843eeeb2dSStefano Zampini VecType vtype; 158907b0a1fcSMatthew G Knepley PetscSection coordSectionA, coordSectionB; 159007b0a1fcSMatthew G Knepley PetscScalar *coordsA, *coordsB; 15910bedd6beSMatthew G. Knepley PetscInt spaceDim, Nf, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; 159243eeeb2dSStefano Zampini PetscInt cStartA, cEndA, cStartB, cEndB, cS, cE; 159343eeeb2dSStefano Zampini PetscBool lc = PETSC_FALSE; 159407b0a1fcSMatthew G Knepley PetscErrorCode ierr; 159507b0a1fcSMatthew G Knepley 159607b0a1fcSMatthew G Knepley PetscFunctionBegin; 159743eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 159843eeeb2dSStefano Zampini PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 159976b791aaSMatthew G. Knepley if (dmA == dmB) PetscFunctionReturn(0); 160007b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr); 160107b0a1fcSMatthew G Knepley ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr); 160207b0a1fcSMatthew 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); 160343eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmA, 0, &cStartA, &cEndA);CHKERRQ(ierr); 160443eeeb2dSStefano Zampini ierr = DMPlexGetHeightStratum(dmB, 0, &cStartB, &cEndB);CHKERRQ(ierr); 160569d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr); 160669d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr); 1607972bc18aSToby Isaac if (coordSectionA == coordSectionB) PetscFunctionReturn(0); 16080bedd6beSMatthew G. Knepley ierr = PetscSectionGetNumFields(coordSectionA, &Nf);CHKERRQ(ierr); 16090bedd6beSMatthew G. Knepley if (!Nf) PetscFunctionReturn(0); 16100bedd6beSMatthew G. Knepley if (Nf > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of coordinate fields must be 1, not %D", Nf); 1611df26b574SMatthew G. Knepley if (!coordSectionB) { 1612df26b574SMatthew G. Knepley PetscInt dim; 1613df26b574SMatthew G. Knepley 1614df26b574SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr); 1615df26b574SMatthew G. Knepley ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr); 1616df26b574SMatthew G. Knepley ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr); 1617df26b574SMatthew G. Knepley ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr); 1618df26b574SMatthew G. Knepley } 161907b0a1fcSMatthew G Knepley ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); 162007b0a1fcSMatthew G Knepley ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr); 162107b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr); 162243eeeb2dSStefano Zampini ierr = PetscSectionGetChart(coordSectionA, &cS, &cE);CHKERRQ(ierr); 162343eeeb2dSStefano Zampini if (cStartA <= cS && cS < cEndA) { /* localized coordinates */ 1624367003a6SStefano 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); 162543eeeb2dSStefano Zampini cS = cS - cStartA + cStartB; 162643eeeb2dSStefano Zampini cE = vEndB; 162743eeeb2dSStefano Zampini lc = PETSC_TRUE; 162843eeeb2dSStefano Zampini } else { 162943eeeb2dSStefano Zampini cS = vStartB; 163043eeeb2dSStefano Zampini cE = vEndB; 163143eeeb2dSStefano Zampini } 163243eeeb2dSStefano Zampini ierr = PetscSectionSetChart(coordSectionB, cS, cE);CHKERRQ(ierr); 163307b0a1fcSMatthew G Knepley for (v = vStartB; v < vEndB; ++v) { 163407b0a1fcSMatthew G Knepley ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr); 163507b0a1fcSMatthew G Knepley ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr); 163607b0a1fcSMatthew G Knepley } 163743eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 163843eeeb2dSStefano Zampini PetscInt c; 163943eeeb2dSStefano Zampini 164043eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 164143eeeb2dSStefano Zampini PetscInt dof; 164243eeeb2dSStefano Zampini 164343eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 164443eeeb2dSStefano Zampini ierr = PetscSectionSetDof(coordSectionB, c + cStartB, dof);CHKERRQ(ierr); 164543eeeb2dSStefano Zampini ierr = PetscSectionSetFieldDof(coordSectionB, c + cStartB, 0, dof);CHKERRQ(ierr); 164643eeeb2dSStefano Zampini } 164743eeeb2dSStefano Zampini } 164807b0a1fcSMatthew G Knepley ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); 164907b0a1fcSMatthew G Knepley ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr); 165007b0a1fcSMatthew G Knepley ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr); 16518b9ced59SLisandro Dalcin ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr); 165207b0a1fcSMatthew G Knepley ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); 165307b0a1fcSMatthew G Knepley ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr); 165443eeeb2dSStefano Zampini ierr = VecGetBlockSize(coordinatesA, &d);CHKERRQ(ierr); 165543eeeb2dSStefano Zampini ierr = VecSetBlockSize(coordinatesB, d);CHKERRQ(ierr); 165643eeeb2dSStefano Zampini ierr = VecGetType(coordinatesA, &vtype);CHKERRQ(ierr); 165743eeeb2dSStefano Zampini ierr = VecSetType(coordinatesB, vtype);CHKERRQ(ierr); 165807b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr); 165907b0a1fcSMatthew G Knepley ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); 166007b0a1fcSMatthew G Knepley for (v = 0; v < vEndB-vStartB; ++v) { 166143eeeb2dSStefano Zampini PetscInt offA, offB; 166243eeeb2dSStefano Zampini 166343eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, v + vStartA, &offA);CHKERRQ(ierr); 166443eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, v + vStartB, &offB);CHKERRQ(ierr); 166507b0a1fcSMatthew G Knepley for (d = 0; d < spaceDim; ++d) { 166643eeeb2dSStefano Zampini coordsB[offB+d] = coordsA[offA+d]; 166743eeeb2dSStefano Zampini } 166843eeeb2dSStefano Zampini } 166943eeeb2dSStefano Zampini if (lc) { /* localized coordinates */ 167043eeeb2dSStefano Zampini PetscInt c; 167143eeeb2dSStefano Zampini 167243eeeb2dSStefano Zampini for (c = cS-cStartB; c < cEndB-cStartB; c++) { 167343eeeb2dSStefano Zampini PetscInt dof, offA, offB; 167443eeeb2dSStefano Zampini 167543eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionA, c + cStartA, &offA);CHKERRQ(ierr); 167643eeeb2dSStefano Zampini ierr = PetscSectionGetOffset(coordSectionB, c + cStartB, &offB);CHKERRQ(ierr); 167743eeeb2dSStefano Zampini ierr = PetscSectionGetDof(coordSectionA, c + cStartA, &dof);CHKERRQ(ierr); 1678580bdb30SBarry Smith ierr = PetscArraycpy(coordsB + offB,coordsA + offA,dof);CHKERRQ(ierr); 167907b0a1fcSMatthew G Knepley } 168007b0a1fcSMatthew G Knepley } 168107b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr); 168207b0a1fcSMatthew G Knepley ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); 168307b0a1fcSMatthew G Knepley ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr); 168407b0a1fcSMatthew G Knepley ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); 168507b0a1fcSMatthew G Knepley PetscFunctionReturn(0); 168607b0a1fcSMatthew G Knepley } 16875c386225SMatthew G. Knepley 16884e3744c5SMatthew G. Knepley /*@ 16894e3744c5SMatthew G. Knepley DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh 16904e3744c5SMatthew G. Knepley 1691d083f849SBarry Smith Collective on dm 16924e3744c5SMatthew G. Knepley 16934e3744c5SMatthew G. Knepley Input Parameter: 16944e3744c5SMatthew G. Knepley . dm - The complete DMPlex object 16954e3744c5SMatthew G. Knepley 16964e3744c5SMatthew G. Knepley Output Parameter: 16974e3744c5SMatthew G. Knepley . dmUnint - The DMPlex object with only cells and vertices 16984e3744c5SMatthew G. Knepley 16994e3744c5SMatthew G. Knepley Level: intermediate 17004e3744c5SMatthew G. Knepley 170195452b02SPatrick Sanan Notes: 170295452b02SPatrick Sanan It does not copy over the coordinates. 170343eeeb2dSStefano Zampini 17049ade3219SVaclav Hapla Developer Notes: 17059ade3219SVaclav Hapla It sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 17069ade3219SVaclav Hapla 170743eeeb2dSStefano Zampini .seealso: DMPlexInterpolate(), DMPlexCreateFromCellList(), DMPlexCopyCoordinates() 17084e3744c5SMatthew G. Knepley @*/ 17094e3744c5SMatthew G. Knepley PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) 17104e3744c5SMatthew G. Knepley { 1711827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 17124e3744c5SMatthew G. Knepley DM udm; 1713c9f63434SStefano Zampini PetscInt dim, vStart, vEnd, cStart, cEnd, cMax, c, maxConeSize = 0, *cone; 17144e3744c5SMatthew G. Knepley PetscErrorCode ierr; 17154e3744c5SMatthew G. Knepley 17164e3744c5SMatthew G. Knepley PetscFunctionBegin; 171743eeeb2dSStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 171843eeeb2dSStefano Zampini PetscValidPointer(dmUnint, 2); 1719c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1720827c4036SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 1721827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 1722827c4036SVaclav Hapla if (interpolated == DMPLEX_INTERPOLATED_NONE || dim <= 1) { 1723827c4036SVaclav Hapla /* in case dim <= 1 just keep the DMPLEX_INTERPOLATED_FULL flag */ 17244e3744c5SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 1725595d4abbSMatthew G. Knepley *dmUnint = dm; 1726595d4abbSMatthew G. Knepley PetscFunctionReturn(0); 17274e3744c5SMatthew G. Knepley } 1728595d4abbSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1729595d4abbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1730c9f63434SStefano Zampini ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 17314e3744c5SMatthew G. Knepley ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr); 17324e3744c5SMatthew G. Knepley ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr); 1733c73cfb54SMatthew G. Knepley ierr = DMSetDimension(udm, dim);CHKERRQ(ierr); 17344e3744c5SMatthew G. Knepley ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr); 17354e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1736595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 17374e3744c5SMatthew G. Knepley 17384e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17394e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 17404e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 17414e3744c5SMatthew G. Knepley 17424e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++coneSize; 17434e3744c5SMatthew G. Knepley } 17444e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17454e3744c5SMatthew G. Knepley ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr); 1746595d4abbSMatthew G. Knepley maxConeSize = PetscMax(maxConeSize, coneSize); 17474e3744c5SMatthew G. Knepley } 17484e3744c5SMatthew G. Knepley ierr = DMSetUp(udm);CHKERRQ(ierr); 1749785e854fSJed Brown ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr); 17504e3744c5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1751595d4abbSMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 17524e3744c5SMatthew G. Knepley 17534e3744c5SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17544e3744c5SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 17554e3744c5SMatthew G. Knepley const PetscInt p = closure[cl]; 17564e3744c5SMatthew G. Knepley 17574e3744c5SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; 17584e3744c5SMatthew G. Knepley } 17594e3744c5SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 17604e3744c5SMatthew G. Knepley ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr); 17614e3744c5SMatthew G. Knepley } 17624e3744c5SMatthew G. Knepley ierr = PetscFree(cone);CHKERRQ(ierr); 1763c9f63434SStefano Zampini ierr = DMPlexSetHybridBounds(udm, cMax, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 17644e3744c5SMatthew G. Knepley ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr); 17654e3744c5SMatthew G. Knepley ierr = DMPlexStratify(udm);CHKERRQ(ierr); 17665c7de58aSMatthew G. Knepley /* Reduce SF */ 17675c7de58aSMatthew G. Knepley { 17685c7de58aSMatthew G. Knepley PetscSF sfPoint, sfPointUn; 17695c7de58aSMatthew G. Knepley const PetscSFNode *remotePoints; 17705c7de58aSMatthew G. Knepley const PetscInt *localPoints; 17715c7de58aSMatthew G. Knepley PetscSFNode *remotePointsUn; 17725c7de58aSMatthew G. Knepley PetscInt *localPointsUn; 17735c7de58aSMatthew G. Knepley PetscInt vEnd, numRoots, numLeaves, l; 17745c7de58aSMatthew G. Knepley PetscInt numLeavesUn = 0, n = 0; 17755c7de58aSMatthew G. Knepley PetscErrorCode ierr; 17765c7de58aSMatthew G. Knepley 17775c7de58aSMatthew G. Knepley /* Get original SF information */ 17785c7de58aSMatthew G. Knepley ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 17795c7de58aSMatthew G. Knepley ierr = DMGetPointSF(udm, &sfPointUn);CHKERRQ(ierr); 17805c7de58aSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, NULL, &vEnd);CHKERRQ(ierr); 17815c7de58aSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 17825c7de58aSMatthew G. Knepley /* Allocate space for cells and vertices */ 17835c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) if (localPoints[l] < vEnd) numLeavesUn++; 17845c7de58aSMatthew G. Knepley /* Fill in leaves */ 17855c7de58aSMatthew G. Knepley if (vEnd >= 0) { 17865c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &remotePointsUn);CHKERRQ(ierr); 17875c7de58aSMatthew G. Knepley ierr = PetscMalloc1(numLeavesUn, &localPointsUn);CHKERRQ(ierr); 17885c7de58aSMatthew G. Knepley for (l = 0; l < numLeaves; l++) { 17895c7de58aSMatthew G. Knepley if (localPoints[l] < vEnd) { 17905c7de58aSMatthew G. Knepley localPointsUn[n] = localPoints[l]; 17915c7de58aSMatthew G. Knepley remotePointsUn[n].rank = remotePoints[l].rank; 17925c7de58aSMatthew G. Knepley remotePointsUn[n].index = remotePoints[l].index; 17935c7de58aSMatthew G. Knepley ++n; 17945c7de58aSMatthew G. Knepley } 17955c7de58aSMatthew G. Knepley } 17965c7de58aSMatthew G. Knepley if (n != numLeavesUn) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent number of leaves %d != %d", n, numLeavesUn); 17975c7de58aSMatthew G. Knepley ierr = PetscSFSetGraph(sfPointUn, vEnd, numLeavesUn, localPointsUn, PETSC_OWN_POINTER, remotePointsUn, PETSC_OWN_POINTER);CHKERRQ(ierr); 17985c7de58aSMatthew G. Knepley } 17995c7de58aSMatthew G. Knepley } 180043eeeb2dSStefano Zampini { 180143eeeb2dSStefano Zampini PetscBool isper; 180243eeeb2dSStefano Zampini const PetscReal *maxCell, *L; 180343eeeb2dSStefano Zampini const DMBoundaryType *bd; 180443eeeb2dSStefano Zampini 180543eeeb2dSStefano Zampini ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 180643eeeb2dSStefano Zampini ierr = DMSetPeriodicity(udm,isper,maxCell,L,bd);CHKERRQ(ierr); 180743eeeb2dSStefano Zampini } 1808827c4036SVaclav Hapla /* This function makes the mesh fully uninterpolated on all ranks */ 1809827c4036SVaclav Hapla { 1810d6e9e4f7SVaclav Hapla DM_Plex *plex = (DM_Plex *) udm->data; 1811827c4036SVaclav Hapla plex->interpolated = plex->interpolatedCollective = DMPLEX_INTERPOLATED_NONE; 1812827c4036SVaclav Hapla } 18134e3744c5SMatthew G. Knepley *dmUnint = udm; 18144e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 18154e3744c5SMatthew G. Knepley } 1816a7748839SVaclav Hapla 1817a7748839SVaclav Hapla static PetscErrorCode DMPlexIsInterpolated_Internal(DM dm, DMPlexInterpolatedFlag *interpolated) 1818a7748839SVaclav Hapla { 1819a7748839SVaclav Hapla PetscInt coneSize, depth, dim, h, p, pStart, pEnd; 1820a7748839SVaclav Hapla MPI_Comm comm; 1821a7748839SVaclav Hapla PetscErrorCode ierr; 1822a7748839SVaclav Hapla 1823a7748839SVaclav Hapla PetscFunctionBegin; 1824a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1825a7748839SVaclav Hapla ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1826a7748839SVaclav Hapla ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1827a7748839SVaclav Hapla 1828a7748839SVaclav Hapla if (depth == dim) { 1829a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_FULL; 1830a7748839SVaclav Hapla if (!dim) goto finish; 1831a7748839SVaclav Hapla 1832a7748839SVaclav Hapla /* Check points at height = dim are vertices (have no cones) */ 1833a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, dim, &pStart, &pEnd);CHKERRQ(ierr); 1834a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1835a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1836a7748839SVaclav Hapla if (coneSize) { 1837a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1838a7748839SVaclav Hapla goto finish; 1839a7748839SVaclav Hapla } 1840a7748839SVaclav Hapla } 1841a7748839SVaclav Hapla 1842a7748839SVaclav Hapla /* Check points at height < dim have cones */ 1843a7748839SVaclav Hapla for (h=0; h<dim; h++) { 1844a7748839SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 1845a7748839SVaclav Hapla for (p=pStart; p<pEnd; p++) { 1846a7748839SVaclav Hapla ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1847a7748839SVaclav Hapla if (!coneSize) { 1848a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1849a7748839SVaclav Hapla goto finish; 1850a7748839SVaclav Hapla } 1851a7748839SVaclav Hapla } 1852a7748839SVaclav Hapla } 1853a7748839SVaclav Hapla } else if (depth == 1) { 1854a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_NONE; 1855a7748839SVaclav Hapla } else { 1856a7748839SVaclav Hapla *interpolated = DMPLEX_INTERPOLATED_PARTIAL; 1857a7748839SVaclav Hapla } 1858a7748839SVaclav Hapla finish: 1859a7748839SVaclav Hapla PetscFunctionReturn(0); 1860a7748839SVaclav Hapla } 1861a7748839SVaclav Hapla 1862a7748839SVaclav Hapla /*@ 18639ade3219SVaclav Hapla DMPlexIsInterpolated - Find out to what extent the DMPlex is topologically interpolated. 1864a7748839SVaclav Hapla 1865a7748839SVaclav Hapla Not Collective 1866a7748839SVaclav Hapla 1867a7748839SVaclav Hapla Input Parameter: 1868a7748839SVaclav Hapla . dm - The DM object 1869a7748839SVaclav Hapla 1870a7748839SVaclav Hapla Output Parameter: 1871a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1872a7748839SVaclav Hapla 1873a7748839SVaclav Hapla Level: intermediate 1874a7748839SVaclav Hapla 1875a7748839SVaclav Hapla Notes: 18769ade3219SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this is NOT collective 18779ade3219SVaclav Hapla so the results can be different on different ranks in special cases. 1878a7748839SVaclav Hapla However, DMPlexInterpolate() guarantees the result is the same on all. 18799ade3219SVaclav Hapla 1880a7748839SVaclav Hapla Unlike DMPlexIsInterpolatedCollective(), this cannot return DMPLEX_INTERPOLATED_MIXED. 1881a7748839SVaclav Hapla 18829ade3219SVaclav Hapla Developer Notes: 18839ade3219SVaclav Hapla Initially, plex->interpolated = DMPLEX_INTERPOLATED_INVALID. 18849ade3219SVaclav Hapla 18859ade3219SVaclav Hapla If plex->interpolated == DMPLEX_INTERPOLATED_INVALID, DMPlexIsInterpolated_Internal() is called. 18869ade3219SVaclav Hapla It checks the actual topology and sets plex->interpolated on each rank separately to one of 18879ade3219SVaclav Hapla DMPLEX_INTERPOLATED_NONE, DMPLEX_INTERPOLATED_PARTIAL or DMPLEX_INTERPOLATED_FULL. 18889ade3219SVaclav Hapla 18899ade3219SVaclav Hapla If plex->interpolated != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolated. 18909ade3219SVaclav Hapla 18919ade3219SVaclav Hapla DMPlexInterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_FULL, 18929ade3219SVaclav Hapla and DMPlexUninterpolate() sets plex->interpolated = DMPLEX_INTERPOLATED_NONE. 18939ade3219SVaclav Hapla 1894a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolatedCollective() 1895a7748839SVaclav Hapla @*/ 1896a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolated(DM dm, DMPlexInterpolatedFlag *interpolated) 1897a7748839SVaclav Hapla { 1898a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1899a7748839SVaclav Hapla PetscErrorCode ierr; 1900a7748839SVaclav Hapla 1901a7748839SVaclav Hapla PetscFunctionBegin; 1902a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1903a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1904a7748839SVaclav Hapla if (plex->interpolated < 0) { 1905a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &plex->interpolated);CHKERRQ(ierr); 1906a7748839SVaclav Hapla } else { 1907a7748839SVaclav Hapla #if defined (PETSC_USE_DEBUG) 1908a7748839SVaclav Hapla DMPlexInterpolatedFlag flg; 1909a7748839SVaclav Hapla 1910a7748839SVaclav Hapla ierr = DMPlexIsInterpolated_Internal(dm, &flg);CHKERRQ(ierr); 19117fc06600SVaclav 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]); 1912a7748839SVaclav Hapla #endif 1913a7748839SVaclav Hapla } 1914a7748839SVaclav Hapla *interpolated = plex->interpolated; 1915a7748839SVaclav Hapla PetscFunctionReturn(0); 1916a7748839SVaclav Hapla } 1917a7748839SVaclav Hapla 1918a7748839SVaclav Hapla /*@ 19199ade3219SVaclav Hapla DMPlexIsInterpolatedCollective - Find out to what extent the DMPlex is topologically interpolated (in collective manner). 1920a7748839SVaclav Hapla 19212666ff3cSVaclav Hapla Collective 1922a7748839SVaclav Hapla 1923a7748839SVaclav Hapla Input Parameter: 1924a7748839SVaclav Hapla . dm - The DM object 1925a7748839SVaclav Hapla 1926a7748839SVaclav Hapla Output Parameter: 1927a7748839SVaclav Hapla . interpolated - Flag whether the DM is interpolated 1928a7748839SVaclav Hapla 1929a7748839SVaclav Hapla Level: intermediate 1930a7748839SVaclav Hapla 1931a7748839SVaclav Hapla Notes: 19329ade3219SVaclav Hapla Unlike DMPlexIsInterpolated(), this is collective so the results are guaranteed to be the same on all ranks. 19339ade3219SVaclav Hapla 19349ade3219SVaclav Hapla This function will return DMPLEX_INTERPOLATED_MIXED if the results of DMPlexIsInterpolated() are different on different ranks. 19359ade3219SVaclav Hapla 19369ade3219SVaclav Hapla Developer Notes: 19379ade3219SVaclav Hapla Initially, plex->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID. 19389ade3219SVaclav Hapla 19399ade3219SVaclav Hapla If plex->interpolatedCollective == DMPLEX_INTERPOLATED_INVALID, this function calls DMPlexIsInterpolated() which sets plex->interpolated. 19409ade3219SVaclav Hapla MPI_Allreduce() is then called and collectively consistent flag plex->interpolatedCollective is set and returned; 19419ade3219SVaclav Hapla if plex->interpolated varies on different ranks, plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED, 19429ade3219SVaclav Hapla otherwise sets plex->interpolatedCollective = plex->interpolated. 19439ade3219SVaclav Hapla 19449ade3219SVaclav Hapla If plex->interpolatedCollective != DMPLEX_INTERPOLATED_INVALID, this function just returns plex->interpolatedCollective. 1945a7748839SVaclav Hapla 1946a7748839SVaclav Hapla .seealso: DMPlexInterpolate(), DMPlexIsInterpolated() 1947a7748839SVaclav Hapla @*/ 1948a7748839SVaclav Hapla PetscErrorCode DMPlexIsInterpolatedCollective(DM dm, DMPlexInterpolatedFlag *interpolated) 1949a7748839SVaclav Hapla { 1950a7748839SVaclav Hapla DM_Plex *plex = (DM_Plex *) dm->data; 1951a7748839SVaclav Hapla PetscBool debug=PETSC_FALSE; 1952a7748839SVaclav Hapla PetscErrorCode ierr; 1953a7748839SVaclav Hapla 1954a7748839SVaclav Hapla PetscFunctionBegin; 1955a7748839SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1956a7748839SVaclav Hapla PetscValidPointer(interpolated,2); 1957a7748839SVaclav Hapla ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_is_interpolated_collective_debug", &debug, NULL);CHKERRQ(ierr); 1958a7748839SVaclav Hapla if (plex->interpolatedCollective < 0) { 1959a7748839SVaclav Hapla DMPlexInterpolatedFlag min, max; 1960a7748839SVaclav Hapla MPI_Comm comm; 1961a7748839SVaclav Hapla 1962a7748839SVaclav Hapla ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1963a7748839SVaclav Hapla ierr = DMPlexIsInterpolated(dm, &plex->interpolatedCollective);CHKERRQ(ierr); 1964a7748839SVaclav Hapla ierr = MPI_Allreduce(&plex->interpolatedCollective, &min, 1, MPIU_ENUM, MPI_MIN, comm);CHKERRQ(ierr); 1965a7748839SVaclav Hapla ierr = MPI_Allreduce(&plex->interpolatedCollective, &max, 1, MPIU_ENUM, MPI_MAX, comm);CHKERRQ(ierr); 1966a7748839SVaclav Hapla if (min != max) plex->interpolatedCollective = DMPLEX_INTERPOLATED_MIXED; 1967a7748839SVaclav Hapla if (debug) { 1968a7748839SVaclav Hapla PetscMPIInt rank; 1969a7748839SVaclav Hapla 1970a7748839SVaclav Hapla ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1971a7748839SVaclav Hapla ierr = PetscSynchronizedPrintf(comm, "[%d] interpolated=%s interpolatedCollective=%s\n", rank, DMPlexInterpolatedFlags[plex->interpolated], DMPlexInterpolatedFlags[plex->interpolatedCollective]);CHKERRQ(ierr); 1972a7748839SVaclav Hapla ierr = PetscSynchronizedFlush(comm, PETSC_STDOUT);CHKERRQ(ierr); 1973a7748839SVaclav Hapla } 1974a7748839SVaclav Hapla } 1975a7748839SVaclav Hapla *interpolated = plex->interpolatedCollective; 1976a7748839SVaclav Hapla PetscFunctionReturn(0); 1977a7748839SVaclav Hapla } 1978