1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2abe9303eSLisandro Dalcin #include <petsc/private/partitionerimpl.h> 3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h> 470034214SMatthew G. Knepley 50134a67bSLisandro Dalcin PETSC_STATIC_INLINE PetscInt DMPlex_GlobalID(PetscInt point) { return point >= 0 ? point : -(point+1); } 60134a67bSLisandro Dalcin 7bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 8532c4e7dSMichael Lange { 9ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size; 10389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 118cfe4c1fSMichael Lange IS cellNumbering; 128cfe4c1fSMichael Lange const PetscInt *cellNum; 13532c4e7dSMichael Lange PetscBool useCone, useClosure; 14532c4e7dSMichael Lange PetscSection section; 15532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 168cfe4c1fSMichael Lange PetscSF sfPoint; 178f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL; 188f4e72b9SMatthew G. Knepley const PetscInt *local; 198f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l; 20532c4e7dSMichael Lange PetscMPIInt rank; 21532c4e7dSMichael Lange PetscErrorCode ierr; 22532c4e7dSMichael Lange 23532c4e7dSMichael Lange PetscFunctionBegin; 24532c4e7dSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 25ffbd6163SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 26ffbd6163SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 27ffbd6163SMatthew G. Knepley if (dim != depth) { 28ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 29ffbd6163SMatthew G. Knepley ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 30ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 31ffbd6163SMatthew G. Knepley if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 32ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */ 33ffbd6163SMatthew G. Knepley if (!*numVertices) { 34ffbd6163SMatthew G. Knepley ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 35ffbd6163SMatthew G. Knepley (*offsets)[0] = 0; 36ffbd6163SMatthew G. Knepley } 37ffbd6163SMatthew G. Knepley /* Broken in parallel */ 38ffbd6163SMatthew G. Knepley if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 39ffbd6163SMatthew G. Knepley PetscFunctionReturn(0); 40ffbd6163SMatthew G. Knepley } 418cfe4c1fSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 420134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 43532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 44532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 45532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 46532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 47532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 48b0441da4SMatthew G. Knepley ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr); 49b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 509886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering);CHKERRQ(ierr); 513fa7752dSToby Isaac if (globalNumbering) { 523fa7752dSToby Isaac ierr = PetscObjectReference((PetscObject)cellNumbering);CHKERRQ(ierr); 533fa7752dSToby Isaac *globalNumbering = cellNumbering; 543fa7752dSToby Isaac } 558cfe4c1fSMichael Lange ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 568f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells 578f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves) 588f4e72b9SMatthew G. Knepley */ 590134a67bSLisandro Dalcin ierr = PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL);CHKERRQ(ierr); 608f4e72b9SMatthew G. Knepley if (nroots >= 0) { 618f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f; 628f4e72b9SMatthew G. Knepley 638f4e72b9SMatthew G. Knepley ierr = PetscCalloc2(nroots, &adjCells, nroots, &remoteCells);CHKERRQ(ierr); 640134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 658f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3; 668f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 678f4e72b9SMatthew G. Knepley const PetscInt *support; 688f4e72b9SMatthew G. Knepley PetscInt supportSize; 698f4e72b9SMatthew G. Knepley 708f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 718f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 720134a67bSLisandro Dalcin if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 738f4e72b9SMatthew G. Knepley else if (supportSize == 2) { 748f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 750134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1]]); 768f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 770134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 780134a67bSLisandro Dalcin } 790134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 800134a67bSLisandro Dalcin if (supportSize > 2) { 810134a67bSLisandro Dalcin PetscInt numChildren, i; 820134a67bSLisandro Dalcin const PetscInt *children; 830134a67bSLisandro Dalcin 840134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, f, &numChildren, &children);CHKERRQ(ierr); 850134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 860134a67bSLisandro Dalcin const PetscInt child = children[i]; 870134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) { 880134a67bSLisandro Dalcin ierr = DMPlexGetSupport(dm, child, &support);CHKERRQ(ierr); 890134a67bSLisandro Dalcin ierr = DMPlexGetSupportSize(dm, child, &supportSize);CHKERRQ(ierr); 900134a67bSLisandro Dalcin if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 910134a67bSLisandro Dalcin else if (supportSize == 2) { 920134a67bSLisandro Dalcin ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 930134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1]]); 940134a67bSLisandro Dalcin ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 950134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 960134a67bSLisandro Dalcin } 970134a67bSLisandro Dalcin } 980134a67bSLisandro Dalcin } 998f4e72b9SMatthew G. Knepley } 1008f4e72b9SMatthew G. Knepley } 1018f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1; 1028f4e72b9SMatthew G. Knepley ierr = PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells);CHKERRQ(ierr); 1038f4e72b9SMatthew G. Knepley ierr = PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells);CHKERRQ(ierr); 1048f4e72b9SMatthew G. Knepley ierr = PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 1058f4e72b9SMatthew G. Knepley ierr = PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 1068f4e72b9SMatthew G. Knepley } 1078f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */ 1088cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 1098cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 1108cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 1118f4e72b9SMatthew G. Knepley /* Add remote cells */ 1128f4e72b9SMatthew G. Knepley if (remoteCells) { 1130134a67bSLisandro Dalcin const PetscInt gp = DMPlex_GlobalID(cellNum[p]); 1140134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 1150134a67bSLisandro Dalcin const PetscInt *cone, *children; 1160134a67bSLisandro Dalcin 1178f4e72b9SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1188f4e72b9SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1198f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1200134a67bSLisandro Dalcin const PetscInt point = cone[c]; 1210134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 1228f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 1238f4e72b9SMatthew G. Knepley ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 1248f4e72b9SMatthew G. Knepley ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1250134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 1260134a67bSLisandro Dalcin } 1270134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1280134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 1290134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1300134a67bSLisandro Dalcin const PetscInt child = children[i]; 1310134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 1320134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 1330134a67bSLisandro Dalcin ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 1340134a67bSLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1350134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 1360134a67bSLisandro Dalcin } 1378f4e72b9SMatthew G. Knepley } 1388f4e72b9SMatthew G. Knepley } 1398f4e72b9SMatthew G. Knepley } 1408f4e72b9SMatthew G. Knepley /* Add local cells */ 141532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 142532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 143532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 144532c4e7dSMichael Lange const PetscInt point = adj[a]; 145532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 146532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 147532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 148532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1490134a67bSLisandro Dalcin *pBuf = DMPlex_GlobalID(cellNum[point]); 150532c4e7dSMichael Lange } 151532c4e7dSMichael Lange } 1528cfe4c1fSMichael Lange (*numVertices)++; 153532c4e7dSMichael Lange } 1544e468a93SLisandro Dalcin ierr = PetscFree(adj);CHKERRQ(ierr); 1558f4e72b9SMatthew G. Knepley ierr = PetscFree2(adjCells, remoteCells);CHKERRQ(ierr); 156b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr); 1574e468a93SLisandro Dalcin 158532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 159532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 160532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 161389e55d8SMichael Lange ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 16243f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 16343f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 16443f7d02bSMichael Lange ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 16543f7d02bSMichael Lange } 166532c4e7dSMichael Lange vOffsets[*numVertices] = size; 167389e55d8SMichael Lange ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 1684e468a93SLisandro Dalcin 1694e468a93SLisandro Dalcin if (nroots >= 0) { 1704e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 1714e468a93SLisandro Dalcin ierr = PetscSectionReset(section);CHKERRQ(ierr); 1724e468a93SLisandro Dalcin ierr = PetscSectionSetChart(section, 0, *numVertices);CHKERRQ(ierr); 1734e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 1744e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 1754e468a93SLisandro Dalcin PetscInt numEdges = end-start, *PETSC_RESTRICT edges; 1764e468a93SLisandro Dalcin ierr = PetscSortRemoveDupsInt(&numEdges, &graph[start]);CHKERRQ(ierr); 1774e468a93SLisandro Dalcin ierr = PetscSectionSetDof(section, p, numEdges);CHKERRQ(ierr); 1784e468a93SLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, numEdges, &edges);CHKERRQ(ierr); 179580bdb30SBarry Smith ierr = PetscArraycpy(edges, &graph[start], numEdges);CHKERRQ(ierr); 1804e468a93SLisandro Dalcin } 1814e468a93SLisandro Dalcin ierr = PetscFree(vOffsets);CHKERRQ(ierr); 1824e468a93SLisandro Dalcin ierr = PetscFree(graph);CHKERRQ(ierr); 1834e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 1844e468a93SLisandro Dalcin ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 1854e468a93SLisandro Dalcin ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 1864e468a93SLisandro Dalcin ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 1874e468a93SLisandro Dalcin for (idx = 0, p = 0; p < *numVertices; p++) { 1884e468a93SLisandro Dalcin ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 1894e468a93SLisandro Dalcin } 1904e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 1914e468a93SLisandro Dalcin ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 1924e468a93SLisandro Dalcin } else { 1934e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 1944e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 1954e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 1964e468a93SLisandro Dalcin ierr = PetscSortInt(end-start, &graph[start]);CHKERRQ(ierr); 1974e468a93SLisandro Dalcin } 1984e468a93SLisandro Dalcin } 1994e468a93SLisandro Dalcin 2004e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 201389e55d8SMichael Lange if (adjacency) *adjacency = graph; 2024e468a93SLisandro Dalcin 203532c4e7dSMichael Lange /* Cleanup */ 204532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 205532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 2064e468a93SLisandro Dalcin ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 2074e468a93SLisandro Dalcin ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr); 208532c4e7dSMichael Lange PetscFunctionReturn(0); 209532c4e7dSMichael Lange } 210532c4e7dSMichael Lange 211bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 212bbbc8e51SStefano Zampini { 213bbbc8e51SStefano Zampini Mat conn, CSR; 214bbbc8e51SStefano Zampini IS fis, cis, cis_own; 215bbbc8e51SStefano Zampini PetscSF sfPoint; 216bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj; 217bbbc8e51SStefano Zampini PetscInt *idxs,*idxs2; 21883c5d788SMatthew G. Knepley PetscInt dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd; 219bbbc8e51SStefano Zampini PetscMPIInt rank; 220bbbc8e51SStefano Zampini PetscBool flg; 221bbbc8e51SStefano Zampini PetscErrorCode ierr; 222bbbc8e51SStefano Zampini 223bbbc8e51SStefano Zampini PetscFunctionBegin; 224bbbc8e51SStefano Zampini ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 225bbbc8e51SStefano Zampini ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 226bbbc8e51SStefano Zampini ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 227bbbc8e51SStefano Zampini if (dim != depth) { 228bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 229bbbc8e51SStefano Zampini ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 230bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 231bbbc8e51SStefano Zampini if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 232bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 233bbbc8e51SStefano Zampini if (!*numVertices) { 234bbbc8e51SStefano Zampini ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 235bbbc8e51SStefano Zampini (*offsets)[0] = 0; 236bbbc8e51SStefano Zampini } 237bbbc8e51SStefano Zampini /* Broken in parallel */ 238bbbc8e51SStefano Zampini if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 239bbbc8e51SStefano Zampini PetscFunctionReturn(0); 240bbbc8e51SStefano Zampini } 241bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 242bbbc8e51SStefano Zampini 243bbbc8e51SStefano Zampini /* numbering */ 244bbbc8e51SStefano Zampini ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 245bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height, &cStart, &cEnd);CHKERRQ(ierr); 246bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 2479886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis);CHKERRQ(ierr); 2489886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis);CHKERRQ(ierr); 249bbbc8e51SStefano Zampini if (globalNumbering) { 250bbbc8e51SStefano Zampini ierr = ISDuplicate(cis, globalNumbering);CHKERRQ(ierr); 251bbbc8e51SStefano Zampini } 252bbbc8e51SStefano Zampini 253bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 254bbbc8e51SStefano Zampini ierr = ISGetLocalSize(fis, &m);CHKERRQ(ierr); 255bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 256bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 257bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 258bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 259bbbc8e51SStefano Zampini 260bbbc8e51SStefano Zampini if (p < 0) { 261bbbc8e51SStefano Zampini idxs[i] = -(p+1); 262bbbc8e51SStefano Zampini } else { 263bbbc8e51SStefano Zampini idxs[i] = p; 264bbbc8e51SStefano Zampini floc += 1; 265bbbc8e51SStefano Zampini } 266bbbc8e51SStefano Zampini } 267bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 268bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 269bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 270bbbc8e51SStefano Zampini 271bbbc8e51SStefano Zampini ierr = ISGetLocalSize(cis, &m);CHKERRQ(ierr); 272bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 273bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 274bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs2);CHKERRQ(ierr); 275bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 276bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 277bbbc8e51SStefano Zampini 278bbbc8e51SStefano Zampini if (p < 0) { 279bbbc8e51SStefano Zampini idxs[i] = -(p+1); 280bbbc8e51SStefano Zampini } else { 281bbbc8e51SStefano Zampini idxs[i] = p; 282bbbc8e51SStefano Zampini idxs2[cloc++] = p; 283bbbc8e51SStefano Zampini } 284bbbc8e51SStefano Zampini } 285bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 286bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 287bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 288bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own);CHKERRQ(ierr); 289bbbc8e51SStefano Zampini 290bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 291bbbc8e51SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)dm), &conn);CHKERRQ(ierr); 292bbbc8e51SStefano Zampini ierr = MatSetSizes(conn, floc, cloc, M, N);CHKERRQ(ierr); 293bbbc8e51SStefano Zampini ierr = MatSetType(conn, MATMPIAIJ);CHKERRQ(ierr); 29483c5d788SMatthew G. Knepley ierr = DMPlexGetMaxSizes(dm, NULL, &lm);CHKERRQ(ierr); 29583c5d788SMatthew G. Knepley ierr = MPI_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 296bbbc8e51SStefano Zampini ierr = MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL);CHKERRQ(ierr); 297bbbc8e51SStefano Zampini 298bbbc8e51SStefano Zampini /* Assemble matrix */ 299bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 300bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 301bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 302bbbc8e51SStefano Zampini const PetscInt *cone; 303bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 304bbbc8e51SStefano Zampini 305bbbc8e51SStefano Zampini col = cols[c-cStart]; 306bbbc8e51SStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 307bbbc8e51SStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 308bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 309bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 310bbbc8e51SStefano Zampini const PetscInt *children; 311bbbc8e51SStefano Zampini PetscInt numChildren, ch; 312bbbc8e51SStefano Zampini 313bbbc8e51SStefano Zampini row = rows[cone[f]-fStart]; 314bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 315bbbc8e51SStefano Zampini 316bbbc8e51SStefano Zampini /* non-conforming meshes */ 317bbbc8e51SStefano Zampini ierr = DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children);CHKERRQ(ierr); 318bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 319bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 320bbbc8e51SStefano Zampini 321bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 322bbbc8e51SStefano Zampini row = rows[child-fStart]; 323bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 324bbbc8e51SStefano Zampini } 325bbbc8e51SStefano Zampini } 326bbbc8e51SStefano Zampini } 327bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 328bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 329bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 330bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 331bbbc8e51SStefano Zampini ierr = MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 332bbbc8e51SStefano Zampini ierr = MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 333bbbc8e51SStefano Zampini 334bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 335bbbc8e51SStefano Zampini ierr = MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR);CHKERRQ(ierr); 336bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 337bbbc8e51SStefano Zampini 338bbbc8e51SStefano Zampini /* extract local part of the CSR */ 339bbbc8e51SStefano Zampini ierr = MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn);CHKERRQ(ierr); 340bbbc8e51SStefano Zampini ierr = MatDestroy(&CSR);CHKERRQ(ierr); 341bbbc8e51SStefano Zampini ierr = MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 342bbbc8e51SStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 343bbbc8e51SStefano Zampini 344bbbc8e51SStefano Zampini /* get back requested output */ 345bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 346bbbc8e51SStefano Zampini if (offsets) { 347bbbc8e51SStefano Zampini ierr = PetscCalloc1(m+1, &idxs);CHKERRQ(ierr); 348bbbc8e51SStefano Zampini for (i = 1; i < m+1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 349bbbc8e51SStefano Zampini *offsets = idxs; 350bbbc8e51SStefano Zampini } 351bbbc8e51SStefano Zampini if (adjacency) { 352bbbc8e51SStefano Zampini ierr = PetscMalloc1(ii[m] - m, &idxs);CHKERRQ(ierr); 353bbbc8e51SStefano Zampini ierr = ISGetIndices(cis_own, &rows);CHKERRQ(ierr); 354bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 355bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 356bbbc8e51SStefano Zampini 357bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i+1]; j++) { 358bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 359bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 360bbbc8e51SStefano Zampini } 361bbbc8e51SStefano Zampini } 362bbbc8e51SStefano Zampini if (c != ii[m] - m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %D != %D",c,ii[m]-m); 363bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis_own, &rows);CHKERRQ(ierr); 364bbbc8e51SStefano Zampini *adjacency = idxs; 365bbbc8e51SStefano Zampini } 366bbbc8e51SStefano Zampini 367bbbc8e51SStefano Zampini /* cleanup */ 368bbbc8e51SStefano Zampini ierr = ISDestroy(&cis_own);CHKERRQ(ierr); 369bbbc8e51SStefano Zampini ierr = MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 370bbbc8e51SStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 371bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 372bbbc8e51SStefano Zampini PetscFunctionReturn(0); 373bbbc8e51SStefano Zampini } 374bbbc8e51SStefano Zampini 375bbbc8e51SStefano Zampini /*@C 376bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 377bbbc8e51SStefano Zampini 378bbbc8e51SStefano Zampini Input Parameters: 379bbbc8e51SStefano Zampini + dm - The mesh DM dm 380bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 381bbbc8e51SStefano Zampini 382bbbc8e51SStefano Zampini Output Parameter: 383bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 384bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 385bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 386bbbc8e51SStefano Zampini - globalNumbering - A map from the local cell numbering to the global numbering used in "adjacency". Negative indicates that the cell is a duplicate from another process. 387bbbc8e51SStefano Zampini 388bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 389bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 390bbbc8e51SStefano Zampini 391bbbc8e51SStefano Zampini Level: developer 392bbbc8e51SStefano Zampini 393bbbc8e51SStefano Zampini .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency() 394bbbc8e51SStefano Zampini @*/ 395bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 396bbbc8e51SStefano Zampini { 397bbbc8e51SStefano Zampini PetscErrorCode ierr; 398bbbc8e51SStefano Zampini PetscBool usemat = PETSC_FALSE; 399bbbc8e51SStefano Zampini 400bbbc8e51SStefano Zampini PetscFunctionBegin; 401bbbc8e51SStefano Zampini ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_csr_via_mat", &usemat, NULL);CHKERRQ(ierr); 402bbbc8e51SStefano Zampini if (usemat) { 403bbbc8e51SStefano Zampini ierr = DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr); 404bbbc8e51SStefano Zampini } else { 405bbbc8e51SStefano Zampini ierr = DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr); 406bbbc8e51SStefano Zampini } 407bbbc8e51SStefano Zampini PetscFunctionReturn(0); 408bbbc8e51SStefano Zampini } 409bbbc8e51SStefano Zampini 410d5577e40SMatthew G. Knepley /*@C 411d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 412d5577e40SMatthew G. Knepley 413fe2efc57SMark Collective on DM 414d5577e40SMatthew G. Knepley 415d5577e40SMatthew G. Knepley Input Arguments: 416d5577e40SMatthew G. Knepley + dm - The DMPlex 417d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 418d5577e40SMatthew G. Knepley 419d5577e40SMatthew G. Knepley Output Arguments: 420d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 421d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 422d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 423d5577e40SMatthew G. Knepley 424d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 425d5577e40SMatthew G. Knepley 426d5577e40SMatthew G. Knepley Level: advanced 427d5577e40SMatthew G. Knepley 428d5577e40SMatthew G. Knepley .seealso: DMPlexCreate() 429d5577e40SMatthew G. Knepley @*/ 43070034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 43170034214SMatthew G. Knepley { 43270034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 43370034214SMatthew G. Knepley PetscInt numFaceCases = 0; 43470034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 43570034214SMatthew G. Knepley PetscInt *off, *adj; 43670034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 43770034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 43870034214SMatthew G. Knepley PetscErrorCode ierr; 43970034214SMatthew G. Knepley 44070034214SMatthew G. Knepley PetscFunctionBegin; 44170034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 442c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 44370034214SMatthew G. Knepley cellDim = dim - cellHeight; 44470034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 44570034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 44670034214SMatthew G. Knepley if (cEnd - cStart == 0) { 44770034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 44870034214SMatthew G. Knepley if (offsets) *offsets = NULL; 44970034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 45070034214SMatthew G. Knepley PetscFunctionReturn(0); 45170034214SMatthew G. Knepley } 45270034214SMatthew G. Knepley numCells = cEnd - cStart; 45370034214SMatthew G. Knepley faceDepth = depth - cellHeight; 45470034214SMatthew G. Knepley if (dim == depth) { 45570034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 45670034214SMatthew G. Knepley 45770034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 45870034214SMatthew G. Knepley /* Count neighboring cells */ 45970034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 46070034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 46170034214SMatthew G. Knepley const PetscInt *support; 46270034214SMatthew G. Knepley PetscInt supportSize; 46370034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 46470034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 46570034214SMatthew G. Knepley if (supportSize == 2) { 4669ffc88e4SToby Isaac PetscInt numChildren; 4679ffc88e4SToby Isaac 4689ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 4699ffc88e4SToby Isaac if (!numChildren) { 47070034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 47170034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 47270034214SMatthew G. Knepley } 47370034214SMatthew G. Knepley } 4749ffc88e4SToby Isaac } 47570034214SMatthew G. Knepley /* Prefix sum */ 47670034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 47770034214SMatthew G. Knepley if (adjacency) { 47870034214SMatthew G. Knepley PetscInt *tmp; 47970034214SMatthew G. Knepley 48070034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 481854ce69bSBarry Smith ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr); 482580bdb30SBarry Smith ierr = PetscArraycpy(tmp, off, numCells+1);CHKERRQ(ierr); 48370034214SMatthew G. Knepley /* Get neighboring cells */ 48470034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 48570034214SMatthew G. Knepley const PetscInt *support; 48670034214SMatthew G. Knepley PetscInt supportSize; 48770034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 48870034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 48970034214SMatthew G. Knepley if (supportSize == 2) { 4909ffc88e4SToby Isaac PetscInt numChildren; 4919ffc88e4SToby Isaac 4929ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 4939ffc88e4SToby Isaac if (!numChildren) { 49470034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 49570034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 49670034214SMatthew G. Knepley } 49770034214SMatthew G. Knepley } 4989ffc88e4SToby Isaac } 49976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 50070034214SMatthew G. Knepley for (c = 0; c < cEnd-cStart; ++c) if (tmp[c] != off[c+1]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %d != %d for cell %d", tmp[c], off[c], c+cStart); 50176bd3646SJed Brown } 50270034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 50370034214SMatthew G. Knepley } 50470034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 50570034214SMatthew G. Knepley if (offsets) *offsets = off; 50670034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 50770034214SMatthew G. Knepley PetscFunctionReturn(0); 50870034214SMatthew G. Knepley } 50970034214SMatthew G. Knepley /* Setup face recognition */ 51070034214SMatthew G. Knepley if (faceDepth == 1) { 51170034214SMatthew G. Knepley PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */ 51270034214SMatthew G. Knepley 51370034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 51470034214SMatthew G. Knepley PetscInt corners; 51570034214SMatthew G. Knepley 51670034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 51770034214SMatthew G. Knepley if (!cornersSeen[corners]) { 51870034214SMatthew G. Knepley PetscInt nFV; 51970034214SMatthew G. Knepley 52070034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 52170034214SMatthew G. Knepley cornersSeen[corners] = 1; 52270034214SMatthew G. Knepley 52370034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 52470034214SMatthew G. Knepley 52570034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 52670034214SMatthew G. Knepley } 52770034214SMatthew G. Knepley } 52870034214SMatthew G. Knepley } 52970034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 53070034214SMatthew G. Knepley /* Count neighboring cells */ 53170034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 53270034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 53370034214SMatthew G. Knepley 5348b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 53570034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 53670034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 53770034214SMatthew G. Knepley PetscInt cellPair[2]; 53870034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 53970034214SMatthew G. Knepley PetscInt meetSize = 0; 54070034214SMatthew G. Knepley const PetscInt *meet = NULL; 54170034214SMatthew G. Knepley 54270034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 54370034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 54470034214SMatthew G. Knepley if (!found) { 54570034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 54670034214SMatthew G. Knepley if (meetSize) { 54770034214SMatthew G. Knepley PetscInt f; 54870034214SMatthew G. Knepley 54970034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 55070034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 55170034214SMatthew G. Knepley found = PETSC_TRUE; 55270034214SMatthew G. Knepley break; 55370034214SMatthew G. Knepley } 55470034214SMatthew G. Knepley } 55570034214SMatthew G. Knepley } 55670034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 55770034214SMatthew G. Knepley } 55870034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 55970034214SMatthew G. Knepley } 56070034214SMatthew G. Knepley } 56170034214SMatthew G. Knepley /* Prefix sum */ 56270034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 56370034214SMatthew G. Knepley 56470034214SMatthew G. Knepley if (adjacency) { 56570034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 56670034214SMatthew G. Knepley /* Get neighboring cells */ 56770034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 56870034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 56970034214SMatthew G. Knepley PetscInt cellOffset = 0; 57070034214SMatthew G. Knepley 5718b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 57270034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 57370034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 57470034214SMatthew G. Knepley PetscInt cellPair[2]; 57570034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 57670034214SMatthew G. Knepley PetscInt meetSize = 0; 57770034214SMatthew G. Knepley const PetscInt *meet = NULL; 57870034214SMatthew G. Knepley 57970034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 58070034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 58170034214SMatthew G. Knepley if (!found) { 58270034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 58370034214SMatthew G. Knepley if (meetSize) { 58470034214SMatthew G. Knepley PetscInt f; 58570034214SMatthew G. Knepley 58670034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 58770034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 58870034214SMatthew G. Knepley found = PETSC_TRUE; 58970034214SMatthew G. Knepley break; 59070034214SMatthew G. Knepley } 59170034214SMatthew G. Knepley } 59270034214SMatthew G. Knepley } 59370034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 59470034214SMatthew G. Knepley } 59570034214SMatthew G. Knepley if (found) { 59670034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 59770034214SMatthew G. Knepley ++cellOffset; 59870034214SMatthew G. Knepley } 59970034214SMatthew G. Knepley } 60070034214SMatthew G. Knepley } 60170034214SMatthew G. Knepley } 60270034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 60370034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 60470034214SMatthew G. Knepley if (offsets) *offsets = off; 60570034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 60670034214SMatthew G. Knepley PetscFunctionReturn(0); 60770034214SMatthew G. Knepley } 60870034214SMatthew G. Knepley 60977623264SMatthew G. Knepley /*@ 6103c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh 61177623264SMatthew G. Knepley 612fe2efc57SMark Collective on PetscPartitioner 61377623264SMatthew G. Knepley 61477623264SMatthew G. Knepley Input Parameters: 61577623264SMatthew G. Knepley + part - The PetscPartitioner 6163c41b853SStefano Zampini . targetSection - The PetscSection describing the absolute weight of each partition (can be NULL) 617f8987ae8SMichael Lange - dm - The mesh DM 61877623264SMatthew G. Knepley 61977623264SMatthew G. Knepley Output Parameters: 62077623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 621f8987ae8SMichael Lange - partition - The list of points by partition 62277623264SMatthew G. Knepley 6233c41b853SStefano Zampini Notes: 6243c41b853SStefano Zampini If the DM has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified 6253c41b853SStefano Zampini by the section in the transitive closure of the point. 62677623264SMatthew G. Knepley 62777623264SMatthew G. Knepley Level: developer 62877623264SMatthew G. Knepley 6293c41b853SStefano Zampini .seealso DMPlexDistribute(), PetscPartitionerCreate(), PetscSectionCreate(), PetscSectionSetChart(), PetscPartitionerPartition() 6304b15ede2SMatthew G. Knepley @*/ 6313c41b853SStefano Zampini PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition) 63277623264SMatthew G. Knepley { 63377623264SMatthew G. Knepley PetscMPIInt size; 6343c41b853SStefano Zampini PetscBool isplex; 63577623264SMatthew G. Knepley PetscErrorCode ierr; 6363c41b853SStefano Zampini PetscSection vertSection = NULL; 63777623264SMatthew G. Knepley 63877623264SMatthew G. Knepley PetscFunctionBegin; 63977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 64077623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 6413c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3); 64277623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 64377623264SMatthew G. Knepley PetscValidPointer(partition, 5); 6443c41b853SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr); 6453c41b853SStefano Zampini if (!isplex) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Not for type %s",((PetscObject)dm)->type_name); 64677623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 64777623264SMatthew G. Knepley if (size == 1) { 64877623264SMatthew G. Knepley PetscInt *points; 64977623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 65077623264SMatthew G. Knepley 65177623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 6523c41b853SStefano Zampini ierr = PetscSectionReset(partSection);CHKERRQ(ierr); 65377623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 65477623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 65577623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 65677623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 65777623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 65877623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 65977623264SMatthew G. Knepley PetscFunctionReturn(0); 66077623264SMatthew G. Knepley } 66177623264SMatthew G. Knepley if (part->height == 0) { 662074d466cSStefano Zampini PetscInt numVertices = 0; 66377623264SMatthew G. Knepley PetscInt *start = NULL; 66477623264SMatthew G. Knepley PetscInt *adjacency = NULL; 6653fa7752dSToby Isaac IS globalNumbering; 66677623264SMatthew G. Knepley 667074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 668074d466cSStefano Zampini ierr = DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr); 66913911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 670074d466cSStefano Zampini const PetscInt *idxs; 671074d466cSStefano Zampini PetscInt p, pStart, pEnd; 672074d466cSStefano Zampini 673074d466cSStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 6749886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering);CHKERRQ(ierr); 675074d466cSStefano Zampini ierr = ISGetIndices(globalNumbering, &idxs);CHKERRQ(ierr); 676074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 677074d466cSStefano Zampini ierr = ISRestoreIndices(globalNumbering, &idxs);CHKERRQ(ierr); 678074d466cSStefano Zampini } 6793c41b853SStefano Zampini if (part->usevwgt) { 6803c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL; 6813c41b853SStefano Zampini IS clPoints = NULL; 6823c41b853SStefano Zampini const PetscInt *gid,*clIdx; 6833c41b853SStefano Zampini PetscInt v, p, pStart, pEnd; 6840358368aSMatthew G. Knepley 6853c41b853SStefano Zampini /* dm->localSection encodes degrees of freedom per point, not per cell. We need to get the closure index to properly specify cell weights (aka dofs) */ 6863c41b853SStefano Zampini /* We do this only if the local section has been set */ 6873c41b853SStefano Zampini if (section) { 6883c41b853SStefano Zampini ierr = PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL);CHKERRQ(ierr); 6893c41b853SStefano Zampini if (!clSection) { 6903c41b853SStefano Zampini ierr = DMPlexCreateClosureIndex(dm,NULL);CHKERRQ(ierr); 6913c41b853SStefano Zampini } 6923c41b853SStefano Zampini ierr = PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints);CHKERRQ(ierr); 6933c41b853SStefano Zampini ierr = ISGetIndices(clPoints,&clIdx);CHKERRQ(ierr); 6943c41b853SStefano Zampini } 6953c41b853SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 6963c41b853SStefano Zampini ierr = PetscSectionCreate(PETSC_COMM_SELF, &vertSection);CHKERRQ(ierr); 6973c41b853SStefano Zampini ierr = PetscSectionSetChart(vertSection, 0, numVertices);CHKERRQ(ierr); 6983c41b853SStefano Zampini if (globalNumbering) { 6993c41b853SStefano Zampini ierr = ISGetIndices(globalNumbering,&gid);CHKERRQ(ierr); 7003c41b853SStefano Zampini } else gid = NULL; 7013c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) { 7023c41b853SStefano Zampini PetscInt dof = 1; 7030358368aSMatthew G. Knepley 7043c41b853SStefano Zampini /* skip cells in the overlap */ 7053c41b853SStefano Zampini if (gid && gid[p-pStart] < 0) continue; 7063c41b853SStefano Zampini 7073c41b853SStefano Zampini if (section) { 7083c41b853SStefano Zampini PetscInt cl, clSize, clOff; 7093c41b853SStefano Zampini 7103c41b853SStefano Zampini dof = 0; 7113c41b853SStefano Zampini ierr = PetscSectionGetDof(clSection, p, &clSize);CHKERRQ(ierr); 7123c41b853SStefano Zampini ierr = PetscSectionGetOffset(clSection, p, &clOff);CHKERRQ(ierr); 7133c41b853SStefano Zampini for (cl = 0; cl < clSize; cl+=2) { 7143c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */ 7153c41b853SStefano Zampini 7163c41b853SStefano Zampini ierr = PetscSectionGetDof(section, clPoint, &clDof);CHKERRQ(ierr); 7173c41b853SStefano Zampini dof += clDof; 7180358368aSMatthew G. Knepley } 7190358368aSMatthew G. Knepley } 7203c41b853SStefano Zampini if (!dof) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of dofs for point %D in the local section should be positive",p); 7213c41b853SStefano Zampini ierr = PetscSectionSetDof(vertSection, v, dof);CHKERRQ(ierr); 7223c41b853SStefano Zampini v++; 7233c41b853SStefano Zampini } 7243c41b853SStefano Zampini if (globalNumbering) { 7253c41b853SStefano Zampini ierr = ISRestoreIndices(globalNumbering,&gid);CHKERRQ(ierr); 7263c41b853SStefano Zampini } 7273c41b853SStefano Zampini if (clPoints) { 7283c41b853SStefano Zampini ierr = ISRestoreIndices(clPoints,&clIdx);CHKERRQ(ierr); 7293c41b853SStefano Zampini } 7303c41b853SStefano Zampini ierr = PetscSectionSetUp(vertSection);CHKERRQ(ierr); 7313c41b853SStefano Zampini } 7323c41b853SStefano Zampini ierr = PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition);CHKERRQ(ierr); 73377623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 73477623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 7353fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 7363fa7752dSToby Isaac const PetscInt *globalNum; 7373fa7752dSToby Isaac const PetscInt *partIdx; 7383fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 7393fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 7403fa7752dSToby Isaac IS newPartition; 7413fa7752dSToby Isaac 7423fa7752dSToby Isaac ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr); 7433fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr); 7443fa7752dSToby Isaac ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 7453fa7752dSToby Isaac ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr); 7463fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr); 7473fa7752dSToby Isaac ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 7483fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 7493fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 7503fa7752dSToby Isaac } 7513fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 7523fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 7533fa7752dSToby Isaac } 7543fa7752dSToby Isaac ierr = PetscFree(map);CHKERRQ(ierr); 7553fa7752dSToby Isaac ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr); 7563fa7752dSToby Isaac ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 7573fa7752dSToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr); 7583fa7752dSToby Isaac ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr); 7593fa7752dSToby Isaac ierr = ISDestroy(partition);CHKERRQ(ierr); 7603fa7752dSToby Isaac *partition = newPartition; 7613fa7752dSToby Isaac } 76277623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 7633c41b853SStefano Zampini ierr = PetscSectionDestroy(&vertSection);CHKERRQ(ierr); 76477623264SMatthew G. Knepley PetscFunctionReturn(0); 76577623264SMatthew G. Knepley } 76677623264SMatthew G. Knepley 7675680f57bSMatthew G. Knepley /*@ 7685680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 7695680f57bSMatthew G. Knepley 7705680f57bSMatthew G. Knepley Not collective 7715680f57bSMatthew G. Knepley 7725680f57bSMatthew G. Knepley Input Parameter: 7735680f57bSMatthew G. Knepley . dm - The DM 7745680f57bSMatthew G. Knepley 7755680f57bSMatthew G. Knepley Output Parameter: 7765680f57bSMatthew G. Knepley . part - The PetscPartitioner 7775680f57bSMatthew G. Knepley 7785680f57bSMatthew G. Knepley Level: developer 7795680f57bSMatthew G. Knepley 78098599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 78198599a47SLawrence Mitchell 7823c41b853SStefano Zampini .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerDMPlexPartition(), PetscPartitionerCreate() 7835680f57bSMatthew G. Knepley @*/ 7845680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 7855680f57bSMatthew G. Knepley { 7865680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 7875680f57bSMatthew G. Knepley 7885680f57bSMatthew G. Knepley PetscFunctionBegin; 7895680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7905680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 7915680f57bSMatthew G. Knepley *part = mesh->partitioner; 7925680f57bSMatthew G. Knepley PetscFunctionReturn(0); 7935680f57bSMatthew G. Knepley } 7945680f57bSMatthew G. Knepley 79571bb2955SLawrence Mitchell /*@ 79671bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 79771bb2955SLawrence Mitchell 798fe2efc57SMark logically collective on DM 79971bb2955SLawrence Mitchell 80071bb2955SLawrence Mitchell Input Parameters: 80171bb2955SLawrence Mitchell + dm - The DM 80271bb2955SLawrence Mitchell - part - The partitioner 80371bb2955SLawrence Mitchell 80471bb2955SLawrence Mitchell Level: developer 80571bb2955SLawrence Mitchell 80671bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 80771bb2955SLawrence Mitchell 80871bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 80971bb2955SLawrence Mitchell @*/ 81071bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 81171bb2955SLawrence Mitchell { 81271bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 81371bb2955SLawrence Mitchell PetscErrorCode ierr; 81471bb2955SLawrence Mitchell 81571bb2955SLawrence Mitchell PetscFunctionBegin; 81671bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81771bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 81871bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 81971bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 82071bb2955SLawrence Mitchell mesh->partitioner = part; 82171bb2955SLawrence Mitchell PetscFunctionReturn(0); 82271bb2955SLawrence Mitchell } 82371bb2955SLawrence Mitchell 8248e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) 8258e330a33SStefano Zampini { 8268e330a33SStefano Zampini const PetscInt *cone; 8278e330a33SStefano Zampini PetscInt coneSize, c; 8288e330a33SStefano Zampini PetscBool missing; 8298e330a33SStefano Zampini PetscErrorCode ierr; 8308e330a33SStefano Zampini 8318e330a33SStefano Zampini PetscFunctionBeginHot; 8328e330a33SStefano Zampini ierr = PetscHSetIQueryAdd(ht, point, &missing);CHKERRQ(ierr); 8338e330a33SStefano Zampini if (missing) { 8348e330a33SStefano Zampini ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8358e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8368e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 8378e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, cone[c]);CHKERRQ(ierr); 8388e330a33SStefano Zampini } 8398e330a33SStefano Zampini } 8408e330a33SStefano Zampini PetscFunctionReturn(0); 8418e330a33SStefano Zampini } 8428e330a33SStefano Zampini 8438e330a33SStefano Zampini PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 844270bba0cSToby Isaac { 845270bba0cSToby Isaac PetscErrorCode ierr; 846270bba0cSToby Isaac 847270bba0cSToby Isaac PetscFunctionBegin; 8486a5a2ffdSToby Isaac if (up) { 8496a5a2ffdSToby Isaac PetscInt parent; 8506a5a2ffdSToby Isaac 851270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 8526a5a2ffdSToby Isaac if (parent != point) { 8536a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 8546a5a2ffdSToby Isaac 855270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 856270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 857270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 858270bba0cSToby Isaac 859e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 8601b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 861270bba0cSToby Isaac } 862270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 8636a5a2ffdSToby Isaac } 8646a5a2ffdSToby Isaac } 8656a5a2ffdSToby Isaac if (down) { 8666a5a2ffdSToby Isaac PetscInt numChildren; 8676a5a2ffdSToby Isaac const PetscInt *children; 8686a5a2ffdSToby Isaac 8696a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 8706a5a2ffdSToby Isaac if (numChildren) { 8716a5a2ffdSToby Isaac PetscInt i; 8726a5a2ffdSToby Isaac 8736a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 8746a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 8756a5a2ffdSToby Isaac 876e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 8771b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 8786a5a2ffdSToby Isaac } 8796a5a2ffdSToby Isaac } 8806a5a2ffdSToby Isaac } 881270bba0cSToby Isaac PetscFunctionReturn(0); 882270bba0cSToby Isaac } 883270bba0cSToby Isaac 8848e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) 8858e330a33SStefano Zampini { 8868e330a33SStefano Zampini PetscInt parent; 8878e330a33SStefano Zampini PetscErrorCode ierr; 888825f8a23SLisandro Dalcin 8898e330a33SStefano Zampini PetscFunctionBeginHot; 8908e330a33SStefano Zampini ierr = DMPlexGetTreeParent(dm, point, &parent,NULL);CHKERRQ(ierr); 8918e330a33SStefano Zampini if (point != parent) { 8928e330a33SStefano Zampini const PetscInt *cone; 8938e330a33SStefano Zampini PetscInt coneSize, c; 8948e330a33SStefano Zampini 8958e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, parent);CHKERRQ(ierr); 8968e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, parent);CHKERRQ(ierr); 8978e330a33SStefano Zampini ierr = DMPlexGetCone(dm, parent, &cone);CHKERRQ(ierr); 8988e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, parent, &coneSize);CHKERRQ(ierr); 8998e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9008e330a33SStefano Zampini const PetscInt cp = cone[c]; 9018e330a33SStefano Zampini 9028e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, cp);CHKERRQ(ierr); 9038e330a33SStefano Zampini } 9048e330a33SStefano Zampini } 9058e330a33SStefano Zampini PetscFunctionReturn(0); 9068e330a33SStefano Zampini } 9078e330a33SStefano Zampini 9088e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) 9098e330a33SStefano Zampini { 9108e330a33SStefano Zampini PetscInt i, numChildren; 9118e330a33SStefano Zampini const PetscInt *children; 9128e330a33SStefano Zampini PetscErrorCode ierr; 9138e330a33SStefano Zampini 9148e330a33SStefano Zampini PetscFunctionBeginHot; 9158e330a33SStefano Zampini ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 9168e330a33SStefano Zampini for (i = 0; i < numChildren; i++) { 9178e330a33SStefano Zampini ierr = PetscHSetIAdd(ht, children[i]);CHKERRQ(ierr); 9188e330a33SStefano Zampini } 9198e330a33SStefano Zampini PetscFunctionReturn(0); 9208e330a33SStefano Zampini } 9218e330a33SStefano Zampini 9228e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) 9238e330a33SStefano Zampini { 9248e330a33SStefano Zampini const PetscInt *cone; 9258e330a33SStefano Zampini PetscInt coneSize, c; 9268e330a33SStefano Zampini PetscErrorCode ierr; 9278e330a33SStefano Zampini 9288e330a33SStefano Zampini PetscFunctionBeginHot; 9298e330a33SStefano Zampini ierr = PetscHSetIAdd(ht, point);CHKERRQ(ierr); 9308e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, point);CHKERRQ(ierr); 9318e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Down_Private(dm, ht, point);CHKERRQ(ierr); 9328e330a33SStefano Zampini ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 9338e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 9348e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9358e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Private(dm, ht, cone[c]);CHKERRQ(ierr); 9368e330a33SStefano Zampini } 9378e330a33SStefano Zampini PetscFunctionReturn(0); 9388e330a33SStefano Zampini } 9398e330a33SStefano Zampini 9408e330a33SStefano Zampini PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) 941825f8a23SLisandro Dalcin { 942825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 9438e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 9448e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 945825f8a23SLisandro Dalcin PetscHSetI ht; 946825f8a23SLisandro Dalcin PetscErrorCode ierr; 947825f8a23SLisandro Dalcin 948825f8a23SLisandro Dalcin PetscFunctionBegin; 949825f8a23SLisandro Dalcin ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 950825f8a23SLisandro Dalcin ierr = PetscHSetIResize(ht, numPoints*16);CHKERRQ(ierr); 9518e330a33SStefano Zampini if (!hasTree) { 9528e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 9538e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, points[p]);CHKERRQ(ierr); 9548e330a33SStefano Zampini } 9558e330a33SStefano Zampini } else { 9568e330a33SStefano Zampini #if 1 9578e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 9588e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Private(dm, ht, points[p]);CHKERRQ(ierr); 9598e330a33SStefano Zampini } 9608e330a33SStefano Zampini #else 9618e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 962825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 963825f8a23SLisandro Dalcin ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 964825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 965825f8a23SLisandro Dalcin ierr = PetscHSetIAdd(ht, closure[c]);CHKERRQ(ierr); 966825f8a23SLisandro Dalcin if (hasTree) {ierr = DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE);CHKERRQ(ierr);} 967825f8a23SLisandro Dalcin } 968825f8a23SLisandro Dalcin } 969825f8a23SLisandro Dalcin if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure);CHKERRQ(ierr);} 9708e330a33SStefano Zampini #endif 9718e330a33SStefano Zampini } 972825f8a23SLisandro Dalcin ierr = PetscHSetIGetSize(ht, &nelems);CHKERRQ(ierr); 973825f8a23SLisandro Dalcin ierr = PetscMalloc1(nelems, &elems);CHKERRQ(ierr); 974825f8a23SLisandro Dalcin ierr = PetscHSetIGetElems(ht, &off, elems);CHKERRQ(ierr); 975825f8a23SLisandro Dalcin ierr = PetscHSetIDestroy(&ht);CHKERRQ(ierr); 976825f8a23SLisandro Dalcin ierr = PetscSortInt(nelems, elems);CHKERRQ(ierr); 977825f8a23SLisandro Dalcin ierr = ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS);CHKERRQ(ierr); 978825f8a23SLisandro Dalcin PetscFunctionReturn(0); 979825f8a23SLisandro Dalcin } 980825f8a23SLisandro Dalcin 9815abbe4feSMichael Lange /*@ 9825abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 9835abbe4feSMichael Lange 9845abbe4feSMichael Lange Input Parameters: 9855abbe4feSMichael Lange + dm - The DM 9865abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 9875abbe4feSMichael Lange 9885abbe4feSMichael Lange Level: developer 9895abbe4feSMichael Lange 99030b0ce1bSStefano Zampini .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 9915abbe4feSMichael Lange @*/ 9925abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 9939ffc88e4SToby Isaac { 994825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 9955abbe4feSMichael Lange const PetscInt *ranks, *points; 996825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 9979ffc88e4SToby Isaac PetscErrorCode ierr; 9989ffc88e4SToby Isaac 9999ffc88e4SToby Isaac PetscFunctionBegin; 10005abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 10015abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 10025abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 10035abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 10045abbe4feSMichael Lange const PetscInt rank = ranks[r]; 10055abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 10065abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 10075abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 10088e330a33SStefano Zampini ierr = DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS);CHKERRQ(ierr); 10095abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 10105abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1011825f8a23SLisandro Dalcin ierr = DMLabelSetStratumIS(label, rank, closureIS);CHKERRQ(ierr); 1012825f8a23SLisandro Dalcin ierr = ISDestroy(&closureIS);CHKERRQ(ierr); 10139ffc88e4SToby Isaac } 10145abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 10155abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 10169ffc88e4SToby Isaac PetscFunctionReturn(0); 10179ffc88e4SToby Isaac } 10189ffc88e4SToby Isaac 101924d039d7SMichael Lange /*@ 102024d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 102124d039d7SMichael Lange 102224d039d7SMichael Lange Input Parameters: 102324d039d7SMichael Lange + dm - The DM 102424d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 102524d039d7SMichael Lange 102624d039d7SMichael Lange Level: developer 102724d039d7SMichael Lange 10282d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 102924d039d7SMichael Lange @*/ 103024d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 103170034214SMatthew G. Knepley { 103224d039d7SMichael Lange IS rankIS, pointIS; 103324d039d7SMichael Lange const PetscInt *ranks, *points; 103424d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 103524d039d7SMichael Lange PetscInt *adj = NULL; 103670034214SMatthew G. Knepley PetscErrorCode ierr; 103770034214SMatthew G. Knepley 103870034214SMatthew G. Knepley PetscFunctionBegin; 103924d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 104024d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 104124d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 104224d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 104324d039d7SMichael Lange const PetscInt rank = ranks[r]; 104470034214SMatthew G. Knepley 104524d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 104624d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 104724d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 104870034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 104924d039d7SMichael Lange adjSize = PETSC_DETERMINE; 105024d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 105124d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 105270034214SMatthew G. Knepley } 105324d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 105424d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 105570034214SMatthew G. Knepley } 105624d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 105724d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 105824d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 105924d039d7SMichael Lange PetscFunctionReturn(0); 106070034214SMatthew G. Knepley } 106170034214SMatthew G. Knepley 1062be200f8dSMichael Lange /*@ 1063be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 1064be200f8dSMichael Lange 1065be200f8dSMichael Lange Input Parameters: 1066be200f8dSMichael Lange + dm - The DM 1067be200f8dSMichael Lange - label - DMLabel assinging ranks to remote roots 1068be200f8dSMichael Lange 1069be200f8dSMichael Lange Level: developer 1070be200f8dSMichael Lange 1071be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 1072be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1073be200f8dSMichael Lange 10742d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 1075be200f8dSMichael Lange @*/ 1076be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 1077be200f8dSMichael Lange { 1078be200f8dSMichael Lange MPI_Comm comm; 1079be200f8dSMichael Lange PetscMPIInt rank; 1080be200f8dSMichael Lange PetscSF sfPoint; 10815d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1082be200f8dSMichael Lange IS rankIS, pointIS; 1083be200f8dSMichael Lange const PetscInt *ranks; 1084be200f8dSMichael Lange PetscInt numRanks, r; 1085be200f8dSMichael Lange PetscErrorCode ierr; 1086be200f8dSMichael Lange 1087be200f8dSMichael Lange PetscFunctionBegin; 1088be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1089be200f8dSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1090be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 10915d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 10925d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 10935d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 10945d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 10955d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 10965d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 10975d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 10985d04f6ebSMichael Lange if (remoteRank == rank) continue; 10995d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 11005d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 11015d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 11025d04f6ebSMichael Lange } 11035d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 11045d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 11055d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 1106be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 1107be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 1108be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 1109be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 1110be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 1111be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1112be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1113be200f8dSMichael Lange if (remoteRank == rank) continue; 1114be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 1115be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 1116be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1117be200f8dSMichael Lange } 1118be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 1119be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 1120be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 1121be200f8dSMichael Lange PetscFunctionReturn(0); 1122be200f8dSMichael Lange } 1123be200f8dSMichael Lange 11241fd9873aSMichael Lange /*@ 11251fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 11261fd9873aSMichael Lange 11271fd9873aSMichael Lange Input Parameters: 11281fd9873aSMichael Lange + dm - The DM 11291fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 1130fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank 11311fd9873aSMichael Lange 11321fd9873aSMichael Lange Output Parameter: 1133fe2efc57SMark . leafLabel - DMLabel assinging ranks to remote roots 11341fd9873aSMichael Lange 11351fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 11361fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 11371fd9873aSMichael Lange 11381fd9873aSMichael Lange Level: developer 11391fd9873aSMichael Lange 11402d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 11411fd9873aSMichael Lange @*/ 11421fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 11431fd9873aSMichael Lange { 11441fd9873aSMichael Lange MPI_Comm comm; 1145874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 1146874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 11471fd9873aSMichael Lange PetscSF sfPoint; 1148874ddda9SLisandro Dalcin PetscSection rootSection; 11491fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 11501fd9873aSMichael Lange const PetscSFNode *remote; 11511fd9873aSMichael Lange const PetscInt *local, *neighbors; 11521fd9873aSMichael Lange IS valueIS; 1153874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 11541fd9873aSMichael Lange PetscErrorCode ierr; 11551fd9873aSMichael Lange 11561fd9873aSMichael Lange PetscFunctionBegin; 115730b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr); 11581fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 11591fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 11609852e123SBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 11611fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 11621fd9873aSMichael Lange 11631fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 11641fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 11659852e123SBarry Smith ierr = PetscSectionSetChart(rootSection, 0, size);CHKERRQ(ierr); 11661fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 11671fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 11681fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 11691fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 11701fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 11711fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 11721fd9873aSMichael Lange } 11731fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 1174874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(rootSection, &rootSize);CHKERRQ(ierr); 1175874ddda9SLisandro Dalcin ierr = PetscMalloc1(rootSize, &rootPoints);CHKERRQ(ierr); 11761fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 11771fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 11781fd9873aSMichael Lange IS pointIS; 11791fd9873aSMichael Lange const PetscInt *points; 11801fd9873aSMichael Lange 11811fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 11821fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 11831fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 11841fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 11851fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 1186f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 1187f8987ae8SMichael Lange else {l = -1;} 11881fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 11891fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 11901fd9873aSMichael Lange } 11911fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 11921fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 11931fd9873aSMichael Lange } 1194874ddda9SLisandro Dalcin 1195874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 1196874ddda9SLisandro Dalcin if (!processSF) { 1197874ddda9SLisandro Dalcin PetscInt64 counter = 0; 1198874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 1199874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 1200874ddda9SLisandro Dalcin 1201874ddda9SLisandro Dalcin ierr = PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls);CHKERRQ(ierr); 1202874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 1203874ddda9SLisandro Dalcin ierr = PetscSectionGetDof(rootSection, neighbors[n], &dof);CHKERRQ(ierr); 1204874ddda9SLisandro Dalcin ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 1205874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 1206874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1207874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1208874ddda9SLisandro Dalcin #endif 1209874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 1210874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 1211874ddda9SLisandro Dalcin } 1212874ddda9SLisandro Dalcin ierr = MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm);CHKERRQ(ierr); 1213874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 1214874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 1215874ddda9SLisandro Dalcin ierr = MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRQ(ierr); 1216874ddda9SLisandro Dalcin if (!mpiOverflow) { 121794b10faeSStefano Zampini ierr = PetscInfo(dm,"Using Alltoallv for mesh distribution\n");CHKERRQ(ierr); 1218874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 1219874ddda9SLisandro Dalcin ierr = PetscMalloc1(leafSize, &leafPoints);CHKERRQ(ierr); 1220874ddda9SLisandro Dalcin ierr = MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm);CHKERRQ(ierr); 1221874ddda9SLisandro Dalcin } 1222874ddda9SLisandro Dalcin ierr = PetscFree4(scounts, sdispls, rcounts, rdispls);CHKERRQ(ierr); 1223874ddda9SLisandro Dalcin } 1224874ddda9SLisandro Dalcin 1225874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 1226874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 1227874ddda9SLisandro Dalcin PetscSF procSF; 1228874ddda9SLisandro Dalcin PetscSection leafSection; 1229874ddda9SLisandro Dalcin 1230874ddda9SLisandro Dalcin if (processSF) { 123194b10faeSStefano Zampini ierr = PetscInfo(dm,"Using processSF for mesh distribution\n");CHKERRQ(ierr); 1232874ddda9SLisandro Dalcin ierr = PetscObjectReference((PetscObject)processSF);CHKERRQ(ierr); 1233874ddda9SLisandro Dalcin procSF = processSF; 1234874ddda9SLisandro Dalcin } else { 123594b10faeSStefano Zampini ierr = PetscInfo(dm,"Using processSF for mesh distribution (MPI overflow)\n");CHKERRQ(ierr); 1236874ddda9SLisandro Dalcin ierr = PetscSFCreate(comm,&procSF);CHKERRQ(ierr); 1237900e0f05SJunchao Zhang ierr = PetscSFSetGraphWithPattern(procSF,NULL,PETSCSF_PATTERN_ALLTOALL);CHKERRQ(ierr); 1238874ddda9SLisandro Dalcin } 1239874ddda9SLisandro Dalcin 1240874ddda9SLisandro Dalcin ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection);CHKERRQ(ierr); 1241900e0f05SJunchao Zhang ierr = DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 1242874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(leafSection, &leafSize);CHKERRQ(ierr); 1243874ddda9SLisandro Dalcin ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 1244874ddda9SLisandro Dalcin ierr = PetscSFDestroy(&procSF);CHKERRQ(ierr); 1245874ddda9SLisandro Dalcin } 1246874ddda9SLisandro Dalcin 1247874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 12481fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 12491fd9873aSMichael Lange } 1250874ddda9SLisandro Dalcin 1251874ddda9SLisandro Dalcin ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 1252874ddda9SLisandro Dalcin ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 12531fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 1254874ddda9SLisandro Dalcin ierr = PetscFree(rootPoints);CHKERRQ(ierr); 12551fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 125630b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr); 12571fd9873aSMichael Lange PetscFunctionReturn(0); 12581fd9873aSMichael Lange } 12591fd9873aSMichael Lange 1260aa3148a8SMichael Lange /*@ 1261aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1262aa3148a8SMichael Lange 1263aa3148a8SMichael Lange Input Parameters: 1264aa3148a8SMichael Lange + dm - The DM 1265f0fc11ceSJed Brown - label - DMLabel assinging ranks to remote roots 1266aa3148a8SMichael Lange 1267aa3148a8SMichael Lange Output Parameter: 1268fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping 1269aa3148a8SMichael Lange 1270aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1271aa3148a8SMichael Lange 1272aa3148a8SMichael Lange Level: developer 1273aa3148a8SMichael Lange 127430b0ce1bSStefano Zampini .seealso: DMPlexDistribute(), DMPlexCreateOverlap() 1275aa3148a8SMichael Lange @*/ 1276aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1277aa3148a8SMichael Lange { 12786e203dd9SStefano Zampini PetscMPIInt rank; 12796e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 1280aa3148a8SMichael Lange PetscSFNode *remotePoints; 12816e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 12826e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 1283aa3148a8SMichael Lange PetscErrorCode ierr; 1284aa3148a8SMichael Lange 1285aa3148a8SMichael Lange PetscFunctionBegin; 128630b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr); 128743f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1288aa3148a8SMichael Lange 12896e203dd9SStefano Zampini ierr = DMLabelGetValueIS(label, &neighborsIS);CHKERRQ(ierr); 12906e203dd9SStefano Zampini #if 0 12916e203dd9SStefano Zampini { 12926e203dd9SStefano Zampini IS is; 12936e203dd9SStefano Zampini ierr = ISDuplicate(neighborsIS, &is);CHKERRQ(ierr); 12946e203dd9SStefano Zampini ierr = ISSort(is);CHKERRQ(ierr); 12956e203dd9SStefano Zampini ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr); 12966e203dd9SStefano Zampini neighborsIS = is; 12976e203dd9SStefano Zampini } 12986e203dd9SStefano Zampini #endif 12996e203dd9SStefano Zampini ierr = ISGetLocalSize(neighborsIS, &nNeighbors);CHKERRQ(ierr); 13006e203dd9SStefano Zampini ierr = ISGetIndices(neighborsIS, &neighbors);CHKERRQ(ierr); 13016e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 13026e203dd9SStefano Zampini ierr = DMLabelGetStratumSize(label, neighbors[n], &numPoints);CHKERRQ(ierr); 1303aa3148a8SMichael Lange numRemote += numPoints; 1304aa3148a8SMichael Lange } 1305aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 130643f7d02bSMichael Lange /* Put owned points first */ 130743f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 130843f7d02bSMichael Lange if (numPoints > 0) { 130943f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 131043f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 131143f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 131243f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 131343f7d02bSMichael Lange remotePoints[idx].rank = rank; 131443f7d02bSMichael Lange idx++; 131543f7d02bSMichael Lange } 131643f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 131743f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 131843f7d02bSMichael Lange } 131943f7d02bSMichael Lange /* Now add remote points */ 13206e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 13216e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 13226e203dd9SStefano Zampini 13236e203dd9SStefano Zampini ierr = DMLabelGetStratumSize(label, nn, &numPoints);CHKERRQ(ierr); 13246e203dd9SStefano Zampini if (nn == rank || numPoints <= 0) continue; 13256e203dd9SStefano Zampini ierr = DMLabelGetStratumIS(label, nn, &remoteRootIS);CHKERRQ(ierr); 1326aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1327aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1328aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 13296e203dd9SStefano Zampini remotePoints[idx].rank = nn; 1330aa3148a8SMichael Lange idx++; 1331aa3148a8SMichael Lange } 1332aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1333aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 1334aa3148a8SMichael Lange } 1335aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 1336aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1337aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 133830b0ce1bSStefano Zampini ierr = PetscSFSetUp(*sf);CHKERRQ(ierr); 13396e203dd9SStefano Zampini ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr); 134030b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr); 134170034214SMatthew G. Knepley PetscFunctionReturn(0); 134270034214SMatthew G. Knepley } 1343cb87ef4cSFlorian Wechsung 1344abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 1345abe9303eSLisandro Dalcin #include <parmetis.h> 1346abe9303eSLisandro Dalcin #endif 1347abe9303eSLisandro Dalcin 13486a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 13496a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 13506a3739e5SFlorian Wechsung * them out in that case. */ 13516a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 13527a82c785SFlorian Wechsung /*@C 13537f57c1a4SFlorian Wechsung 13547f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 13557f57c1a4SFlorian Wechsung 13567f57c1a4SFlorian Wechsung Input parameters: 13577f57c1a4SFlorian Wechsung + dm - The DMPlex object. 1358fe2efc57SMark . n - The number of points. 1359fe2efc57SMark . pointsToRewrite - The points in the SF whose ownership will change. 1360fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite. 1361fe2efc57SMark - degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 13627f57c1a4SFlorian Wechsung 13637f57c1a4SFlorian Wechsung Level: developer 13647f57c1a4SFlorian Wechsung 13657f57c1a4SFlorian Wechsung @*/ 13667f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 13677f57c1a4SFlorian Wechsung { 13687f57c1a4SFlorian Wechsung PetscInt ierr, pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 13697f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 13707f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 13717f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 13727f57c1a4SFlorian Wechsung const PetscInt *ilocal; 13737f57c1a4SFlorian Wechsung PetscBool *isLeaf; 13747f57c1a4SFlorian Wechsung PetscSF sf; 13757f57c1a4SFlorian Wechsung MPI_Comm comm; 13765a30b08bSFlorian Wechsung PetscMPIInt rank, size; 13777f57c1a4SFlorian Wechsung 13787f57c1a4SFlorian Wechsung PetscFunctionBegin; 13797f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 13807f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 13817f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 13827f57c1a4SFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 13837f57c1a4SFlorian Wechsung 13847f57c1a4SFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 13857f57c1a4SFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote);CHKERRQ(ierr); 13867f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 13877f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 13887f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 13897f57c1a4SFlorian Wechsung } 13907f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 13917f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 13927f57c1a4SFlorian Wechsung } 13937f57c1a4SFlorian Wechsung 13947f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart+1, &cumSumDegrees);CHKERRQ(ierr); 13957f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 13967f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 13977f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 13987f57c1a4SFlorian Wechsung } 13997f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 14007f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 14017f57c1a4SFlorian Wechsung 14027f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &locationsOfLeafs);CHKERRQ(ierr); 14037f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &rankOnLeafs);CHKERRQ(ierr); 14047f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14057f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 14067f57c1a4SFlorian Wechsung } 14077f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 14087f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 14097f57c1a4SFlorian Wechsung ierr = PetscFree(rankOnLeafs);CHKERRQ(ierr); 14107f57c1a4SFlorian Wechsung 14117f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 14127f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs);CHKERRQ(ierr); 14137f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &points);CHKERRQ(ierr); 14147f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14157f57c1a4SFlorian Wechsung points[i] = pStart+i; 14167f57c1a4SFlorian Wechsung } 14177f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 14187f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 14197f57c1a4SFlorian Wechsung ierr = PetscFree(points);CHKERRQ(ierr); 14207f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 14217f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newOwners);CHKERRQ(ierr); 14227f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newNumbers);CHKERRQ(ierr); 14237f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14247f57c1a4SFlorian Wechsung newOwners[i] = -1; 14257f57c1a4SFlorian Wechsung newNumbers[i] = -1; 14267f57c1a4SFlorian Wechsung } 14277f57c1a4SFlorian Wechsung { 14287f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 14297f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 14307f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 14317f57c1a4SFlorian Wechsung newNumber = -1; 14327f57c1a4SFlorian Wechsung oldOwner = rank; 14337f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 14347f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 14357f57c1a4SFlorian Wechsung newNumber = oldNumber; 14367f57c1a4SFlorian Wechsung } else { 14377f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 14387f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 14397f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 14407f57c1a4SFlorian Wechsung break; 14417f57c1a4SFlorian Wechsung } 14427f57c1a4SFlorian Wechsung } 14437f57c1a4SFlorian Wechsung } 14447f57c1a4SFlorian Wechsung if (newNumber == -1) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 14457f57c1a4SFlorian Wechsung 14467f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 14477f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 14487f57c1a4SFlorian Wechsung } 14497f57c1a4SFlorian Wechsung } 14507f57c1a4SFlorian Wechsung ierr = PetscFree(cumSumDegrees);CHKERRQ(ierr); 14517f57c1a4SFlorian Wechsung ierr = PetscFree(locationsOfLeafs);CHKERRQ(ierr); 14527f57c1a4SFlorian Wechsung ierr = PetscFree(remoteLocalPointOfLeafs);CHKERRQ(ierr); 14537f57c1a4SFlorian Wechsung 14547f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 14557f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 14567f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 14577f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 14587f57c1a4SFlorian Wechsung 14597f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 14607f57c1a4SFlorian Wechsung leafCounter=0; 14617f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14627f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 14637f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 14647f57c1a4SFlorian Wechsung leafCounter++; 14657f57c1a4SFlorian Wechsung } 14667f57c1a4SFlorian Wechsung } else { 14677f57c1a4SFlorian Wechsung if (isLeaf[i]) { 14687f57c1a4SFlorian Wechsung leafCounter++; 14697f57c1a4SFlorian Wechsung } 14707f57c1a4SFlorian Wechsung } 14717f57c1a4SFlorian Wechsung } 14727f57c1a4SFlorian Wechsung 14737f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 14747f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafsNew);CHKERRQ(ierr); 14757f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafLocationsNew);CHKERRQ(ierr); 14767f57c1a4SFlorian Wechsung 14777f57c1a4SFlorian Wechsung leafCounter = 0; 14787f57c1a4SFlorian Wechsung counter = 0; 14797f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14807f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 14817f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 14827f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 14837f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 14847f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 14857f57c1a4SFlorian Wechsung leafCounter++; 14867f57c1a4SFlorian Wechsung } 14877f57c1a4SFlorian Wechsung } else { 14887f57c1a4SFlorian Wechsung if (isLeaf[i]) { 14897f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 14907f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 14917f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 14927f57c1a4SFlorian Wechsung leafCounter++; 14937f57c1a4SFlorian Wechsung } 14947f57c1a4SFlorian Wechsung } 14957f57c1a4SFlorian Wechsung if (isLeaf[i]) { 14967f57c1a4SFlorian Wechsung counter++; 14977f57c1a4SFlorian Wechsung } 14987f57c1a4SFlorian Wechsung } 14997f57c1a4SFlorian Wechsung 15007f57c1a4SFlorian Wechsung ierr = PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 15017f57c1a4SFlorian Wechsung ierr = PetscFree(newOwners);CHKERRQ(ierr); 15027f57c1a4SFlorian Wechsung ierr = PetscFree(newNumbers);CHKERRQ(ierr); 15037f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 15047f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 15057f57c1a4SFlorian Wechsung } 15067f57c1a4SFlorian Wechsung 1507125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 1508125d2a8fSFlorian Wechsung { 15095a30b08bSFlorian Wechsung PetscInt *distribution, min, max, sum, i, ierr; 15105a30b08bSFlorian Wechsung PetscMPIInt rank, size; 1511125d2a8fSFlorian Wechsung PetscFunctionBegin; 1512125d2a8fSFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1513125d2a8fSFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1514125d2a8fSFlorian Wechsung ierr = PetscCalloc1(size, &distribution);CHKERRQ(ierr); 1515125d2a8fSFlorian Wechsung for (i=0; i<n; i++) { 1516125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 1517125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 1518125d2a8fSFlorian Wechsung } 1519125d2a8fSFlorian Wechsung ierr = MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 1520125d2a8fSFlorian Wechsung min = distribution[0]; 1521125d2a8fSFlorian Wechsung max = distribution[0]; 1522125d2a8fSFlorian Wechsung sum = distribution[0]; 1523125d2a8fSFlorian Wechsung for (i=1; i<size; i++) { 1524125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 1525125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 1526125d2a8fSFlorian Wechsung sum += distribution[i]; 1527125d2a8fSFlorian Wechsung } 1528125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum);CHKERRQ(ierr); 1529125d2a8fSFlorian Wechsung ierr = PetscFree(distribution);CHKERRQ(ierr); 1530125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 1531125d2a8fSFlorian Wechsung } 1532125d2a8fSFlorian Wechsung 15336a3739e5SFlorian Wechsung #endif 15346a3739e5SFlorian Wechsung 1535cb87ef4cSFlorian Wechsung /*@ 15365dc86ac1SFlorian Wechsung DMPlexRebalanceSharedPoints - Redistribute points in the plex that are shared in order to achieve better balancing. This routine updates the PointSF of the DM inplace. 1537cb87ef4cSFlorian Wechsung 1538cb87ef4cSFlorian Wechsung Input parameters: 1539ed44d270SFlorian Wechsung + dm - The DMPlex object. 1540fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices). 1541fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 1542fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 1543cb87ef4cSFlorian Wechsung 15448b879b41SFlorian Wechsung Output parameters: 1545fe2efc57SMark . success - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True. 15468b879b41SFlorian Wechsung 154790ea27d8SSatish Balay Level: intermediate 1548cb87ef4cSFlorian Wechsung 1549cb87ef4cSFlorian Wechsung @*/ 1550cb87ef4cSFlorian Wechsung 15518b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 1552cb87ef4cSFlorian Wechsung { 155341525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 1554cb87ef4cSFlorian Wechsung PetscSF sf; 15550faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 15567f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 15577f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 15587f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 1559cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 1560cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 1561cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 15627f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 15635dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 1564cb87ef4cSFlorian Wechsung PetscInt offset, counter; 15657f57c1a4SFlorian Wechsung PetscInt lenadjncy; 1566cb87ef4cSFlorian Wechsung PetscInt *xadj, *adjncy, *vtxwgt; 1567cb87ef4cSFlorian Wechsung PetscInt lenxadj; 1568cb87ef4cSFlorian Wechsung PetscInt *adjwgt = NULL; 1569cb87ef4cSFlorian Wechsung PetscInt *part, *options; 1570cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 1571cb87ef4cSFlorian Wechsung real_t *ubvec; 1572cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 1573cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 1574cb87ef4cSFlorian Wechsung MPI_Comm comm; 15754baf1206SFlorian Wechsung Mat A, Apre; 157612617df9SFlorian Wechsung const char *prefix = NULL; 15777d197802SFlorian Wechsung PetscViewer viewer; 15787d197802SFlorian Wechsung PetscViewerFormat format; 15795a30b08bSFlorian Wechsung PetscLayout layout; 158012617df9SFlorian Wechsung 158112617df9SFlorian Wechsung PetscFunctionBegin; 15828b879b41SFlorian Wechsung if (success) *success = PETSC_FALSE; 15837f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 15847f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 15857f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 15867f57c1a4SFlorian Wechsung if (size==1) PetscFunctionReturn(0); 15877f57c1a4SFlorian Wechsung 158841525646SFlorian Wechsung ierr = PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 158941525646SFlorian Wechsung 15905a30b08bSFlorian Wechsung ierr = PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL);CHKERRQ(ierr); 15915dc86ac1SFlorian Wechsung if (viewer) { 15925a30b08bSFlorian Wechsung ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 15937d197802SFlorian Wechsung } 15947d197802SFlorian Wechsung 1595ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 1596d5528e35SFlorian Wechsung ierr = DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd);CHKERRQ(ierr); 1597cb87ef4cSFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1598cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &toBalance);CHKERRQ(ierr); 1599cf818975SFlorian Wechsung 1600cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 16015a7e692eSFlorian Wechsung toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd); 1602cb87ef4cSFlorian Wechsung } 1603cb87ef4cSFlorian Wechsung 1604cf818975SFlorian Wechsung /* There are three types of points: 1605cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 1606cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 1607cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 1608cf818975SFlorian Wechsung */ 1609cb87ef4cSFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 1610cb87ef4cSFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote);CHKERRQ(ierr); 1611cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 1612cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned);CHKERRQ(ierr); 1613cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isExclusivelyOwned);CHKERRQ(ierr); 1614cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1615cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 1616cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 1617cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 1618cb87ef4cSFlorian Wechsung } 1619cf818975SFlorian Wechsung 1620cf818975SFlorian Wechsung /* start by marking all the leafs */ 1621cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 1622cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 1623cb87ef4cSFlorian Wechsung } 1624cb87ef4cSFlorian Wechsung 1625cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 1626cf818975SFlorian Wechsung * not by calculating its degree */ 16277f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeBegin(sf, °rees);CHKERRQ(ierr); 16287f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeEnd(sf, °rees);CHKERRQ(ierr); 1629cf818975SFlorian Wechsung 1630cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 1631cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 1632cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1633cb87ef4cSFlorian Wechsung if (toBalance[i]) { 16347f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1635cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 1636cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 1637cb87ef4cSFlorian Wechsung } else { 1638cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 1639cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 1640cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 1641cb87ef4cSFlorian Wechsung } 1642cb87ef4cSFlorian Wechsung } 1643cb87ef4cSFlorian Wechsung } 1644cb87ef4cSFlorian Wechsung } 1645cb87ef4cSFlorian Wechsung 1646cf818975SFlorian Wechsung /* We are going to build a graph with one vertex per core representing the 1647cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 1648cf818975SFlorian Wechsung * point. */ 1649cb87ef4cSFlorian Wechsung 16505dc86ac1SFlorian Wechsung ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 16515dc86ac1SFlorian Wechsung ierr = PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned);CHKERRQ(ierr); 16525dc86ac1SFlorian Wechsung ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 16535dc86ac1SFlorian Wechsung ierr = PetscLayoutGetRanges(layout, &cumSumVertices);CHKERRQ(ierr); 16545dc86ac1SFlorian Wechsung 1655cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 16565a427404SJunchao Zhang for (i=0; i<pEnd-pStart; i++) {globalNumbersOfLocalOwnedVertices[i] = pStart - 1;} 1657cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 1658cb87ef4cSFlorian Wechsung counter = 0; 1659cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1660cb87ef4cSFlorian Wechsung if (toBalance[i]) { 16617f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1662cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 1663cb87ef4cSFlorian Wechsung counter++; 1664cb87ef4cSFlorian Wechsung } 1665cb87ef4cSFlorian Wechsung } 1666cb87ef4cSFlorian Wechsung } 1667cb87ef4cSFlorian Wechsung 1668cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 1669cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &leafGlobalNumbers);CHKERRQ(ierr); 1670cb87ef4cSFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 1671cb87ef4cSFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 1672cb87ef4cSFlorian Wechsung 16730faf6628SFlorian Wechsung /* Now start building the data structure for ParMETIS */ 1674cb87ef4cSFlorian Wechsung 16754baf1206SFlorian Wechsung ierr = MatCreate(comm, &Apre);CHKERRQ(ierr); 16764baf1206SFlorian Wechsung ierr = MatSetType(Apre, MATPREALLOCATOR);CHKERRQ(ierr); 16774baf1206SFlorian Wechsung ierr = MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 16784baf1206SFlorian Wechsung ierr = MatSetUp(Apre);CHKERRQ(ierr); 16798c9a1619SFlorian Wechsung 16808c9a1619SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 16818c9a1619SFlorian Wechsung if (toBalance[i]) { 16820faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 16830faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 16840faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 16850faf6628SFlorian Wechsung else continue; 16860faf6628SFlorian Wechsung ierr = MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 16870faf6628SFlorian Wechsung ierr = MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 16884baf1206SFlorian Wechsung } 16894baf1206SFlorian Wechsung } 16904baf1206SFlorian Wechsung 16914baf1206SFlorian Wechsung ierr = MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 16924baf1206SFlorian Wechsung ierr = MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 16934baf1206SFlorian Wechsung 16944baf1206SFlorian Wechsung ierr = MatCreate(comm, &A);CHKERRQ(ierr); 16954baf1206SFlorian Wechsung ierr = MatSetType(A, MATMPIAIJ);CHKERRQ(ierr); 16964baf1206SFlorian Wechsung ierr = MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 16974baf1206SFlorian Wechsung ierr = MatPreallocatorPreallocate(Apre, PETSC_FALSE, A);CHKERRQ(ierr); 16984baf1206SFlorian Wechsung ierr = MatDestroy(&Apre);CHKERRQ(ierr); 16994baf1206SFlorian Wechsung 17004baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 17014baf1206SFlorian Wechsung if (toBalance[i]) { 17020faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 17030faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17040faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17050faf6628SFlorian Wechsung else continue; 17060faf6628SFlorian Wechsung ierr = MatSetValue(A, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 17070faf6628SFlorian Wechsung ierr = MatSetValue(A, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 17080941debbSFlorian Wechsung } 17090941debbSFlorian Wechsung } 17108c9a1619SFlorian Wechsung 17118c9a1619SFlorian Wechsung ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17128c9a1619SFlorian Wechsung ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17134baf1206SFlorian Wechsung ierr = PetscFree(leafGlobalNumbers);CHKERRQ(ierr); 17144baf1206SFlorian Wechsung ierr = PetscFree(globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 17154baf1206SFlorian Wechsung 171641525646SFlorian Wechsung nparts = size; 171741525646SFlorian Wechsung wgtflag = 2; 171841525646SFlorian Wechsung numflag = 0; 171941525646SFlorian Wechsung ncon = 2; 172041525646SFlorian Wechsung real_t *tpwgts; 172141525646SFlorian Wechsung ierr = PetscMalloc1(ncon * nparts, &tpwgts);CHKERRQ(ierr); 172241525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 172341525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 172441525646SFlorian Wechsung } 172541525646SFlorian Wechsung 172641525646SFlorian Wechsung ierr = PetscMalloc1(ncon, &ubvec);CHKERRQ(ierr); 172741525646SFlorian Wechsung ubvec[0] = 1.01; 17285a30b08bSFlorian Wechsung ubvec[1] = 1.01; 17298c9a1619SFlorian Wechsung lenadjncy = 0; 17308c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 17318c9a1619SFlorian Wechsung PetscInt temp=0; 17328c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 17338c9a1619SFlorian Wechsung lenadjncy += temp; 17348c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 17358c9a1619SFlorian Wechsung } 17368c9a1619SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy);CHKERRQ(ierr); 17377407ba93SFlorian Wechsung lenxadj = 2 + numNonExclusivelyOwned; 17380941debbSFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj);CHKERRQ(ierr); 17390941debbSFlorian Wechsung xadj[0] = 0; 17408c9a1619SFlorian Wechsung counter = 0; 17418c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 17422953a68cSFlorian Wechsung PetscInt temp=0; 17432953a68cSFlorian Wechsung const PetscInt *cols; 17448c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 1745580bdb30SBarry Smith ierr = PetscArraycpy(&adjncy[counter], cols, temp);CHKERRQ(ierr); 17468c9a1619SFlorian Wechsung counter += temp; 17470941debbSFlorian Wechsung xadj[i+1] = counter; 17488c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 17498c9a1619SFlorian Wechsung } 17508c9a1619SFlorian Wechsung 1751cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part);CHKERRQ(ierr); 175241525646SFlorian Wechsung ierr = PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt);CHKERRQ(ierr); 175341525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 175441525646SFlorian Wechsung if (ncon>1) vtxwgt[1] = 1; 175541525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 175641525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 175741525646SFlorian Wechsung if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0; 175841525646SFlorian Wechsung } 17598c9a1619SFlorian Wechsung 17605dc86ac1SFlorian Wechsung if (viewer) { 17617d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth);CHKERRQ(ierr); 17627d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size]);CHKERRQ(ierr); 176312617df9SFlorian Wechsung } 176441525646SFlorian Wechsung if (parallel) { 17655a30b08bSFlorian Wechsung ierr = PetscMalloc1(4, &options);CHKERRQ(ierr); 17665a30b08bSFlorian Wechsung options[0] = 1; 17675a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 17685a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 17695a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 17705dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n");CHKERRQ(ierr); } 17718c9a1619SFlorian Wechsung if (useInitialGuess) { 17725dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n");CHKERRQ(ierr); } 17738c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_RefineKway"); 17745dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 177506b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 17768c9a1619SFlorian Wechsung PetscStackPop; 17778c9a1619SFlorian Wechsung } else { 17788c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_PartKway"); 17795dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 17808c9a1619SFlorian Wechsung PetscStackPop; 178106b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 17828c9a1619SFlorian Wechsung } 1783ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 178441525646SFlorian Wechsung } else { 17855dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n");CHKERRQ(ierr); } 178641525646SFlorian Wechsung Mat As; 178741525646SFlorian Wechsung PetscInt numRows; 178841525646SFlorian Wechsung PetscInt *partGlobal; 178941525646SFlorian Wechsung ierr = MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As);CHKERRQ(ierr); 1790cb87ef4cSFlorian Wechsung 179141525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 179241525646SFlorian Wechsung ierr = PetscMalloc1(size, &numExclusivelyOwnedAll);CHKERRQ(ierr); 179341525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 17942953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm);CHKERRQ(ierr); 1795cb87ef4cSFlorian Wechsung 179641525646SFlorian Wechsung ierr = MatGetSize(As, &numRows, NULL);CHKERRQ(ierr); 179741525646SFlorian Wechsung ierr = PetscMalloc1(numRows, &partGlobal);CHKERRQ(ierr); 17985dc86ac1SFlorian Wechsung if (!rank) { 179941525646SFlorian Wechsung PetscInt *adjncy_g, *xadj_g, *vtxwgt_g; 180041525646SFlorian Wechsung lenadjncy = 0; 180141525646SFlorian Wechsung 180241525646SFlorian Wechsung for (i=0; i<numRows; i++) { 180341525646SFlorian Wechsung PetscInt temp=0; 180441525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 180541525646SFlorian Wechsung lenadjncy += temp; 180641525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 180741525646SFlorian Wechsung } 180841525646SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy_g);CHKERRQ(ierr); 180941525646SFlorian Wechsung lenxadj = 1 + numRows; 181041525646SFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj_g);CHKERRQ(ierr); 181141525646SFlorian Wechsung xadj_g[0] = 0; 181241525646SFlorian Wechsung counter = 0; 181341525646SFlorian Wechsung for (i=0; i<numRows; i++) { 18142953a68cSFlorian Wechsung PetscInt temp=0; 18152953a68cSFlorian Wechsung const PetscInt *cols; 181641525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 1817580bdb30SBarry Smith ierr = PetscArraycpy(&adjncy_g[counter], cols, temp);CHKERRQ(ierr); 181841525646SFlorian Wechsung counter += temp; 181941525646SFlorian Wechsung xadj_g[i+1] = counter; 182041525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 182141525646SFlorian Wechsung } 182241525646SFlorian Wechsung ierr = PetscMalloc1(2*numRows, &vtxwgt_g);CHKERRQ(ierr); 182341525646SFlorian Wechsung for (i=0; i<size; i++){ 182441525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 182541525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 182641525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 182741525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 182841525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 182941525646SFlorian Wechsung } 183041525646SFlorian Wechsung } 183141525646SFlorian Wechsung ierr = PetscMalloc1(64, &options);CHKERRQ(ierr); 183241525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 183306b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 183441525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 183541525646SFlorian Wechsung PetscStackPush("METIS_PartGraphKway"); 183606b3913eSFlorian Wechsung ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 183741525646SFlorian Wechsung PetscStackPop; 183806b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 1839ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 184041525646SFlorian Wechsung ierr = PetscFree(xadj_g);CHKERRQ(ierr); 184141525646SFlorian Wechsung ierr = PetscFree(adjncy_g);CHKERRQ(ierr); 184241525646SFlorian Wechsung ierr = PetscFree(vtxwgt_g);CHKERRQ(ierr); 184341525646SFlorian Wechsung } 184441525646SFlorian Wechsung ierr = PetscFree(numExclusivelyOwnedAll);CHKERRQ(ierr); 184541525646SFlorian Wechsung 18465dc86ac1SFlorian Wechsung /* Now scatter the parts array. */ 18475dc86ac1SFlorian Wechsung { 184881a13b52SFlorian Wechsung PetscMPIInt *counts, *mpiCumSumVertices; 18495dc86ac1SFlorian Wechsung ierr = PetscMalloc1(size, &counts);CHKERRQ(ierr); 185081a13b52SFlorian Wechsung ierr = PetscMalloc1(size+1, &mpiCumSumVertices);CHKERRQ(ierr); 18515dc86ac1SFlorian Wechsung for (i=0; i<size; i++) { 185281a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]));CHKERRQ(ierr); 185341525646SFlorian Wechsung } 185481a13b52SFlorian Wechsung for (i=0; i<=size; i++) { 185581a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]));CHKERRQ(ierr); 185681a13b52SFlorian Wechsung } 185781a13b52SFlorian Wechsung ierr = MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm);CHKERRQ(ierr); 18585dc86ac1SFlorian Wechsung ierr = PetscFree(counts);CHKERRQ(ierr); 185981a13b52SFlorian Wechsung ierr = PetscFree(mpiCumSumVertices);CHKERRQ(ierr); 18605dc86ac1SFlorian Wechsung } 18615dc86ac1SFlorian Wechsung 186241525646SFlorian Wechsung ierr = PetscFree(partGlobal);CHKERRQ(ierr); 18632953a68cSFlorian Wechsung ierr = MatDestroy(&As);CHKERRQ(ierr); 186441525646SFlorian Wechsung } 1865cb87ef4cSFlorian Wechsung 18662953a68cSFlorian Wechsung ierr = MatDestroy(&A);CHKERRQ(ierr); 1867cb87ef4cSFlorian Wechsung ierr = PetscFree(ubvec);CHKERRQ(ierr); 1868cb87ef4cSFlorian Wechsung ierr = PetscFree(tpwgts);CHKERRQ(ierr); 1869cb87ef4cSFlorian Wechsung 1870cb87ef4cSFlorian Wechsung /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 1871cb87ef4cSFlorian Wechsung 1872cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &firstVertices);CHKERRQ(ierr); 1873cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &renumbering);CHKERRQ(ierr); 1874cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 18752953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm);CHKERRQ(ierr); 1876cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 1877cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 1878cb87ef4cSFlorian Wechsung } 1879cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 1880cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 1881cb87ef4cSFlorian Wechsung } 1882cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 1883cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 18842953a68cSFlorian Wechsung ierr = MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 1885cb87ef4cSFlorian Wechsung 18867f57c1a4SFlorian Wechsung ierr = PetscFree(firstVertices);CHKERRQ(ierr); 18877f57c1a4SFlorian Wechsung ierr = PetscFree(renumbering);CHKERRQ(ierr); 18887f57c1a4SFlorian Wechsung 1889cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 18907f57c1a4SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 18917f57c1a4SFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 18927f57c1a4SFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 18937f57c1a4SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 18947f57c1a4SFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 18957f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 18967f57c1a4SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 18977f57c1a4SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 18987f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 18997f57c1a4SFlorian Wechsung if (viewer) { 190006b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 190106b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 19027f57c1a4SFlorian Wechsung } 19037f57c1a4SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 19048b879b41SFlorian Wechsung PetscFunctionReturn(0); 1905cb87ef4cSFlorian Wechsung } 1906cb87ef4cSFlorian Wechsung 19077407ba93SFlorian Wechsung /*Let's check how well we did distributing points*/ 19085dc86ac1SFlorian Wechsung if (viewer) { 19097d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Comparing number of owned entities of depth %D on each process before rebalancing, after rebalancing, and after consistency checks.\n", entityDepth);CHKERRQ(ierr); 1910125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Initial. ");CHKERRQ(ierr); 1911125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer);CHKERRQ(ierr); 1912125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Rebalanced. ");CHKERRQ(ierr); 1913125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 19147407ba93SFlorian Wechsung } 19157407ba93SFlorian Wechsung 1916cb87ef4cSFlorian Wechsung /* Now check that every vertex is owned by a process that it is actually connected to. */ 191741525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 1918cb87ef4cSFlorian Wechsung PetscInt loc = 0; 191941525646SFlorian Wechsung ierr = PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc);CHKERRQ(ierr); 19207407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 1921cb87ef4cSFlorian Wechsung if (loc<0) { 192241525646SFlorian Wechsung part[i] = rank; 1923cb87ef4cSFlorian Wechsung } 1924cb87ef4cSFlorian Wechsung } 1925cb87ef4cSFlorian Wechsung 19267407ba93SFlorian Wechsung /* Let's see how significant the influences of the previous fixing up step was.*/ 19275dc86ac1SFlorian Wechsung if (viewer) { 1928125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "After. ");CHKERRQ(ierr); 1929125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 19307407ba93SFlorian Wechsung } 19317407ba93SFlorian Wechsung 19325dc86ac1SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 1933cb87ef4cSFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 1934cb87ef4cSFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 193541525646SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 1936cb87ef4cSFlorian Wechsung 19377f57c1a4SFlorian Wechsung /* Almost done, now rewrite the SF to reflect the new ownership. */ 1938cf818975SFlorian Wechsung { 19397f57c1a4SFlorian Wechsung PetscInt *pointsToRewrite; 194006b3913eSFlorian Wechsung ierr = PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite);CHKERRQ(ierr); 19417f57c1a4SFlorian Wechsung counter = 0; 1942cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1943cb87ef4cSFlorian Wechsung if (toBalance[i]) { 1944cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 19457f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 1946cb87ef4cSFlorian Wechsung counter++; 1947cb87ef4cSFlorian Wechsung } 1948cb87ef4cSFlorian Wechsung } 1949cb87ef4cSFlorian Wechsung } 19507f57c1a4SFlorian Wechsung ierr = DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees);CHKERRQ(ierr); 19517f57c1a4SFlorian Wechsung ierr = PetscFree(pointsToRewrite);CHKERRQ(ierr); 1952cf818975SFlorian Wechsung } 1953cb87ef4cSFlorian Wechsung 1954cb87ef4cSFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 1955cb87ef4cSFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 1956cf818975SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 1957cf818975SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 19587f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 19595dc86ac1SFlorian Wechsung if (viewer) { 196006b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 196106b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 19627d197802SFlorian Wechsung } 19638b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 196441525646SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 1965*b458e8f1SJose E. Roman PetscFunctionReturn(0); 1966240408d3SFlorian Wechsung #else 19675f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 196841525646SFlorian Wechsung #endif 1969cb87ef4cSFlorian Wechsung } 1970