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
54b876568SBarry Smith const char *const DMPlexCSRAlgorithms[] = {"mat", "graph", "overlap", "DMPlexCSRAlgorithm", "DM_PLEX_CSR_", NULL};
65a107427SMatthew G. Knepley
DMPlex_GlobalID(PetscInt point)7d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlex_GlobalID(PetscInt point)
8d71ae5a4SJacob Faibussowitsch {
99371c9d4SSatish Balay return point >= 0 ? point : -(point + 1);
109371c9d4SSatish Balay }
110134a67bSLisandro Dalcin
DMPlexCreatePartitionerGraph_Overlap(DM dm,PetscInt height,PetscInt * numVertices,PetscInt ** offsets,PetscInt ** adjacency,IS * globalNumbering)12d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreatePartitionerGraph_Overlap(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering)
13d71ae5a4SJacob Faibussowitsch {
145a107427SMatthew G. Knepley DM ovdm;
155a107427SMatthew G. Knepley PetscSF sfPoint;
165a107427SMatthew G. Knepley IS cellNumbering;
175a107427SMatthew G. Knepley const PetscInt *cellNum;
185a107427SMatthew G. Knepley PetscInt *adj = NULL, *vOffsets = NULL, *vAdj = NULL;
195a107427SMatthew G. Knepley PetscBool useCone, useClosure;
205a107427SMatthew G. Knepley PetscInt dim, depth, overlap, cStart, cEnd, c, v;
215a107427SMatthew G. Knepley PetscMPIInt rank, size;
225a107427SMatthew G. Knepley
235a107427SMatthew G. Knepley PetscFunctionBegin;
249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
269566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
279566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
285a107427SMatthew G. Knepley if (dim != depth) {
295a107427SMatthew G. Knepley /* We do not handle the uninterpolated case here */
309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency));
315a107427SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */
32e2b8d0fcSMatthew G. Knepley if (globalNumbering) PetscCall(DMPlexCreateCellNumbering(dm, PETSC_TRUE, globalNumbering));
335a107427SMatthew G. Knepley /* Different behavior for empty graphs */
345a107427SMatthew G. Knepley if (!*numVertices) {
359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets));
365a107427SMatthew G. Knepley (*offsets)[0] = 0;
375a107427SMatthew G. Knepley }
385a107427SMatthew G. Knepley /* Broken in parallel */
395f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported");
403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
415a107427SMatthew G. Knepley }
425a107427SMatthew G. Knepley /* Always use FVM adjacency to create partitioner graph */
439566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure));
449566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE));
455a107427SMatthew G. Knepley /* Need overlap >= 1 */
469566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap));
475a107427SMatthew G. Knepley if (size && overlap < 1) {
489566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(dm, 1, NULL, &ovdm));
495a107427SMatthew G. Knepley } else {
509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm));
515a107427SMatthew G. Knepley ovdm = dm;
525a107427SMatthew G. Knepley }
539566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(ovdm, &sfPoint));
549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(ovdm, height, &cStart, &cEnd));
559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(ovdm, cStart, cEnd, 0, NULL, sfPoint, &cellNumbering));
565a107427SMatthew G. Knepley if (globalNumbering) {
579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cellNumbering));
585a107427SMatthew G. Knepley *globalNumbering = cellNumbering;
595a107427SMatthew G. Knepley }
609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum));
615a107427SMatthew G. Knepley /* Determine sizes */
625a107427SMatthew G. Knepley for (*numVertices = 0, c = cStart; c < cEnd; ++c) {
635a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
64b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue;
655a107427SMatthew G. Knepley (*numVertices)++;
665a107427SMatthew G. Knepley }
679566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(*numVertices + 1, &vOffsets));
685a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) {
695a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, vsize = 0;
705a107427SMatthew G. Knepley
71b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue;
729566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj));
735a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) {
745a107427SMatthew G. Knepley const PetscInt point = adj[a];
755a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) ++vsize;
765a107427SMatthew G. Knepley }
775a107427SMatthew G. Knepley vOffsets[v + 1] = vOffsets[v] + vsize;
785a107427SMatthew G. Knepley ++v;
795a107427SMatthew G. Knepley }
805a107427SMatthew G. Knepley /* Determine adjacency */
819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(vOffsets[*numVertices], &vAdj));
825a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) {
835a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, off = vOffsets[v];
845a107427SMatthew G. Knepley
855a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
86b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue;
879566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj));
885a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) {
895a107427SMatthew G. Knepley const PetscInt point = adj[a];
90ad540459SPierre Jolivet if (point != c && cStart <= point && point < cEnd) vAdj[off++] = DMPlex_GlobalID(cellNum[point - cStart]);
915a107427SMatthew G. Knepley }
9263a3b9bcSJacob Faibussowitsch PetscCheck(off == vOffsets[v + 1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Offsets %" PetscInt_FMT " should be %" PetscInt_FMT, off, vOffsets[v + 1]);
935a107427SMatthew G. Knepley /* Sort adjacencies (not strictly necessary) */
949566063dSJacob Faibussowitsch PetscCall(PetscSortInt(off - vOffsets[v], &vAdj[vOffsets[v]]));
955a107427SMatthew G. Knepley ++v;
965a107427SMatthew G. Knepley }
979566063dSJacob Faibussowitsch PetscCall(PetscFree(adj));
989566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellNumbering, &cellNum));
999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellNumbering));
1009566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure));
1019566063dSJacob Faibussowitsch PetscCall(DMDestroy(&ovdm));
1029371c9d4SSatish Balay if (offsets) {
1039371c9d4SSatish Balay *offsets = vOffsets;
1049371c9d4SSatish Balay } else PetscCall(PetscFree(vOffsets));
1059371c9d4SSatish Balay if (adjacency) {
1069371c9d4SSatish Balay *adjacency = vAdj;
1079371c9d4SSatish Balay } else PetscCall(PetscFree(vAdj));
1083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1095a107427SMatthew G. Knepley }
1105a107427SMatthew G. Knepley
DMPlexCreatePartitionerGraph_Native(DM dm,PetscInt height,PetscInt * numVertices,PetscInt ** offsets,PetscInt ** adjacency,IS * globalNumbering)111d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering)
112d71ae5a4SJacob Faibussowitsch {
113ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size;
114389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL;
1158cfe4c1fSMichael Lange IS cellNumbering;
1168cfe4c1fSMichael Lange const PetscInt *cellNum;
117532c4e7dSMichael Lange PetscBool useCone, useClosure;
118532c4e7dSMichael Lange PetscSection section;
119532c4e7dSMichael Lange PetscSegBuffer adjBuffer;
1208cfe4c1fSMichael Lange PetscSF sfPoint;
1218f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL;
1228f4e72b9SMatthew G. Knepley const PetscInt *local;
1238f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l;
124532c4e7dSMichael Lange PetscMPIInt rank;
125532c4e7dSMichael Lange
126532c4e7dSMichael Lange PetscFunctionBegin;
1279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1289566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
1299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
130ffbd6163SMatthew G. Knepley if (dim != depth) {
131ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */
1329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency));
133ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */
134e2b8d0fcSMatthew G. Knepley if (globalNumbering) PetscCall(DMPlexCreateCellNumbering(dm, PETSC_TRUE, globalNumbering));
135ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */
136ffbd6163SMatthew G. Knepley if (!*numVertices) {
1379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets));
138ffbd6163SMatthew G. Knepley (*offsets)[0] = 0;
139ffbd6163SMatthew G. Knepley }
140ffbd6163SMatthew G. Knepley /* Broken in parallel */
1415f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported");
1423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
143ffbd6163SMatthew G. Knepley }
1449566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint));
1459566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height, &pStart, &pEnd));
146532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */
1479566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion));
1489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd));
1499566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 1000, &adjBuffer));
150532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */
1519566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure));
1529566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE));
1539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering));
1543fa7752dSToby Isaac if (globalNumbering) {
1559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cellNumbering));
1563fa7752dSToby Isaac *globalNumbering = cellNumbering;
1573fa7752dSToby Isaac }
1589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum));
1598f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells
1608f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves)
1618f4e72b9SMatthew G. Knepley */
1629566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL));
1638f4e72b9SMatthew G. Knepley if (nroots >= 0) {
1648f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f;
1658f4e72b9SMatthew G. Knepley
1669566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nroots, &adjCells, nroots, &remoteCells));
1679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height + 1, &fStart, &fEnd));
1688f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3;
1698f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) {
1708f4e72b9SMatthew G. Knepley const PetscInt *support;
1718f4e72b9SMatthew G. Knepley PetscInt supportSize;
1728f4e72b9SMatthew G. Knepley
1739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support));
1749566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize));
175b68380d8SVaclav Hapla if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0] - pStart]);
1768f4e72b9SMatthew G. Knepley else if (supportSize == 2) {
1779566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[0], nleaves, local, &p));
178b68380d8SVaclav Hapla if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1] - pStart]);
1799566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[1], nleaves, local, &p));
180b68380d8SVaclav Hapla if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0] - pStart]);
1810134a67bSLisandro Dalcin }
1820134a67bSLisandro Dalcin /* Handle non-conforming meshes */
1830134a67bSLisandro Dalcin if (supportSize > 2) {
1840134a67bSLisandro Dalcin PetscInt numChildren, i;
1850134a67bSLisandro Dalcin const PetscInt *children;
1860134a67bSLisandro Dalcin
1879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, &children));
1880134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) {
1890134a67bSLisandro Dalcin const PetscInt child = children[i];
1900134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) {
1919566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, child, &support));
1929566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, child, &supportSize));
193b68380d8SVaclav Hapla if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0] - pStart]);
1940134a67bSLisandro Dalcin else if (supportSize == 2) {
1959566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[0], nleaves, local, &p));
196b68380d8SVaclav Hapla if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1] - pStart]);
1979566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[1], nleaves, local, &p));
198b68380d8SVaclav Hapla if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0] - pStart]);
1990134a67bSLisandro Dalcin }
2000134a67bSLisandro Dalcin }
2010134a67bSLisandro Dalcin }
2028f4e72b9SMatthew G. Knepley }
2038f4e72b9SMatthew G. Knepley }
2048f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1;
2059566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_REPLACE));
2069566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_REPLACE));
2079566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX));
2089566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX));
2098f4e72b9SMatthew G. Knepley }
2108f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */
2118cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) {
2128cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2139371c9d4SSatish Balay if (nroots > 0) {
2149371c9d4SSatish Balay if (cellNum[p - pStart] < 0) continue;
2159371c9d4SSatish Balay }
2168f4e72b9SMatthew G. Knepley /* Add remote cells */
2178f4e72b9SMatthew G. Knepley if (remoteCells) {
218b68380d8SVaclav Hapla const PetscInt gp = DMPlex_GlobalID(cellNum[p - pStart]);
2190134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i;
2200134a67bSLisandro Dalcin const PetscInt *cone, *children;
2210134a67bSLisandro Dalcin
2229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
2248f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) {
2250134a67bSLisandro Dalcin const PetscInt point = cone[c];
2260134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) {
2278f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf;
2289566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1));
2299566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf));
2300134a67bSLisandro Dalcin *pBuf = remoteCells[point];
2310134a67bSLisandro Dalcin }
2320134a67bSLisandro Dalcin /* Handle non-conforming meshes */
2339566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children));
2340134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) {
2350134a67bSLisandro Dalcin const PetscInt child = children[i];
2360134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) {
2370134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf;
2389566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1));
2399566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf));
2400134a67bSLisandro Dalcin *pBuf = remoteCells[child];
2410134a67bSLisandro Dalcin }
2428f4e72b9SMatthew G. Knepley }
2438f4e72b9SMatthew G. Knepley }
2448f4e72b9SMatthew G. Knepley }
2458f4e72b9SMatthew G. Knepley /* Add local cells */
246532c4e7dSMichael Lange adjSize = PETSC_DETERMINE;
2479566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
248532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) {
249532c4e7dSMichael Lange const PetscInt point = adj[a];
250532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) {
251532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf;
2529566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1));
2539566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf));
254b68380d8SVaclav Hapla *pBuf = DMPlex_GlobalID(cellNum[point - pStart]);
255532c4e7dSMichael Lange }
256532c4e7dSMichael Lange }
2578cfe4c1fSMichael Lange (*numVertices)++;
258532c4e7dSMichael Lange }
2599566063dSJacob Faibussowitsch PetscCall(PetscFree(adj));
2609566063dSJacob Faibussowitsch PetscCall(PetscFree2(adjCells, remoteCells));
2619566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure));
2624e468a93SLisandro Dalcin
263532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */
2649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section));
2659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size));
2669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numVertices + 1, &vOffsets));
26743f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) {
2689371c9d4SSatish Balay if (nroots > 0) {
2699371c9d4SSatish Balay if (cellNum[p - pStart] < 0) continue;
2709371c9d4SSatish Balay }
271f4f49eeaSPierre Jolivet PetscCall(PetscSectionGetOffset(section, p, &vOffsets[idx++]));
27243f7d02bSMichael Lange }
273532c4e7dSMichael Lange vOffsets[*numVertices] = size;
2749566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &graph));
2754e468a93SLisandro Dalcin
2764e468a93SLisandro Dalcin if (nroots >= 0) {
2774e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */
2789566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(section));
2799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, 0, *numVertices));
2804e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) {
2814e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p + 1];
2824e468a93SLisandro Dalcin PetscInt numEdges = end - start, *PETSC_RESTRICT edges;
2839566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&numEdges, &graph[start]));
2849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, numEdges));
2859566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, numEdges, &edges));
2869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(edges, &graph[start], numEdges));
2874e468a93SLisandro Dalcin }
2889566063dSJacob Faibussowitsch PetscCall(PetscFree(vOffsets));
2899566063dSJacob Faibussowitsch PetscCall(PetscFree(graph));
2904e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */
2919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section));
2929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size));
2939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numVertices + 1, &vOffsets));
294f4f49eeaSPierre Jolivet for (idx = 0, p = 0; p < *numVertices; p++) PetscCall(PetscSectionGetOffset(section, p, &vOffsets[idx++]));
2954e468a93SLisandro Dalcin vOffsets[*numVertices] = size;
2969566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &graph));
2974e468a93SLisandro Dalcin } else {
2984e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */
2994e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) {
3004e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p + 1];
3019566063dSJacob Faibussowitsch PetscCall(PetscSortInt(end - start, &graph[start]));
3024e468a93SLisandro Dalcin }
3034e468a93SLisandro Dalcin }
3044e468a93SLisandro Dalcin
3054e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets;
306389e55d8SMichael Lange if (adjacency) *adjacency = graph;
3074e468a93SLisandro Dalcin
308532c4e7dSMichael Lange /* Cleanup */
3099566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer));
3109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion));
3119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellNumbering, &cellNum));
3129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellNumbering));
3133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
314532c4e7dSMichael Lange }
315532c4e7dSMichael Lange
DMPlexCreatePartitionerGraph_ViaMat(DM dm,PetscInt height,PetscInt * numVertices,PetscInt ** offsets,PetscInt ** adjacency,IS * globalNumbering)316d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering)
317d71ae5a4SJacob Faibussowitsch {
318bbbc8e51SStefano Zampini Mat conn, CSR;
319bbbc8e51SStefano Zampini IS fis, cis, cis_own;
320bbbc8e51SStefano Zampini PetscSF sfPoint;
321bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj;
322bbbc8e51SStefano Zampini PetscInt *idxs, *idxs2;
32383c5d788SMatthew G. Knepley PetscInt dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd;
324bbbc8e51SStefano Zampini PetscMPIInt rank;
325bbbc8e51SStefano Zampini PetscBool flg;
326bbbc8e51SStefano Zampini
327bbbc8e51SStefano Zampini PetscFunctionBegin;
3289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
3299566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
3309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
331bbbc8e51SStefano Zampini if (dim != depth) {
332bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */
3339566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency));
334bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */
335e2b8d0fcSMatthew G. Knepley if (globalNumbering) PetscCall(DMPlexCreateCellNumbering(dm, PETSC_TRUE, globalNumbering));
336bbbc8e51SStefano Zampini /* Different behavior for empty graphs */
337bbbc8e51SStefano Zampini if (!*numVertices) {
3389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets));
339bbbc8e51SStefano Zampini (*offsets)[0] = 0;
340bbbc8e51SStefano Zampini }
341bbbc8e51SStefano Zampini /* Broken in parallel */
3425f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported");
3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
344bbbc8e51SStefano Zampini }
345bbbc8e51SStefano Zampini /* Interpolated and parallel case */
346bbbc8e51SStefano Zampini
347bbbc8e51SStefano Zampini /* numbering */
348e0459489SJames Wright PetscCall(DMGetIsoperiodicPointSF_Internal(dm, &sfPoint));
3499566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd));
3509566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height + 1, &fStart, &fEnd));
3519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis));
3529566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis));
3531baa6e33SBarry Smith if (globalNumbering) PetscCall(ISDuplicate(cis, globalNumbering));
354bbbc8e51SStefano Zampini
355bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */
3569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fis, &m));
3579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows));
3589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs));
359bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) {
360bbbc8e51SStefano Zampini const PetscInt p = rows[i];
361bbbc8e51SStefano Zampini
362bbbc8e51SStefano Zampini if (p < 0) {
363bbbc8e51SStefano Zampini idxs[i] = -(p + 1);
364bbbc8e51SStefano Zampini } else {
365bbbc8e51SStefano Zampini idxs[i] = p;
366bbbc8e51SStefano Zampini floc += 1;
367bbbc8e51SStefano Zampini }
368bbbc8e51SStefano Zampini }
3699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows));
3709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis));
3719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis));
372bbbc8e51SStefano Zampini
3739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cis, &m));
3749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols));
3759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs));
3769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs2));
377bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) {
378bbbc8e51SStefano Zampini const PetscInt p = cols[i];
379bbbc8e51SStefano Zampini
380bbbc8e51SStefano Zampini if (p < 0) {
381bbbc8e51SStefano Zampini idxs[i] = -(p + 1);
382bbbc8e51SStefano Zampini } else {
383bbbc8e51SStefano Zampini idxs[i] = p;
384bbbc8e51SStefano Zampini idxs2[cloc++] = p;
385bbbc8e51SStefano Zampini }
386bbbc8e51SStefano Zampini }
3879566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols));
3889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis));
3899566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis));
3909566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own));
391bbbc8e51SStefano Zampini
392bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */
3939566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), &conn));
3949566063dSJacob Faibussowitsch PetscCall(MatSetSizes(conn, floc, cloc, M, N));
3959566063dSJacob Faibussowitsch PetscCall(MatSetType(conn, MATMPIAIJ));
3969566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, NULL, &lm));
397462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
3989566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL));
399bbbc8e51SStefano Zampini
400bbbc8e51SStefano Zampini /* Assemble matrix */
4019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows));
4029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols));
403bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) {
404bbbc8e51SStefano Zampini const PetscInt *cone;
405bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f;
406bbbc8e51SStefano Zampini
407bbbc8e51SStefano Zampini col = cols[c - cStart];
4089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone));
4099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
410bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) {
411bbbc8e51SStefano Zampini const PetscScalar v = 1.0;
412bbbc8e51SStefano Zampini const PetscInt *children;
413bbbc8e51SStefano Zampini PetscInt numChildren, ch;
414bbbc8e51SStefano Zampini
415bbbc8e51SStefano Zampini row = rows[cone[f] - fStart];
4169566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES));
417bbbc8e51SStefano Zampini
418bbbc8e51SStefano Zampini /* non-conforming meshes */
4199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children));
420bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) {
421bbbc8e51SStefano Zampini const PetscInt child = children[ch];
422bbbc8e51SStefano Zampini
423bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue;
424bbbc8e51SStefano Zampini row = rows[child - fStart];
4259566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES));
426bbbc8e51SStefano Zampini }
427bbbc8e51SStefano Zampini }
428bbbc8e51SStefano Zampini }
4299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows));
4309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols));
4319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis));
4329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis));
4339566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY));
4349566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY));
435bbbc8e51SStefano Zampini
436bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */
437fb842aefSJose E. Roman PetscCall(MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &CSR));
4389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn));
439bbbc8e51SStefano Zampini
440bbbc8e51SStefano Zampini /* extract local part of the CSR */
4419566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn));
4429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CSR));
4439566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg));
4445f80ce2aSJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format");
445bbbc8e51SStefano Zampini
446bbbc8e51SStefano Zampini /* get back requested output */
447bbbc8e51SStefano Zampini if (numVertices) *numVertices = m;
448bbbc8e51SStefano Zampini if (offsets) {
4499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m + 1, &idxs));
450bbbc8e51SStefano Zampini for (i = 1; i < m + 1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */
451bbbc8e51SStefano Zampini *offsets = idxs;
452bbbc8e51SStefano Zampini }
453bbbc8e51SStefano Zampini if (adjacency) {
4549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ii[m] - m, &idxs));
4559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis_own, &rows));
456bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) {
457bbbc8e51SStefano Zampini PetscInt j, g = rows[i];
458bbbc8e51SStefano Zampini
459bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) {
460bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */
461bbbc8e51SStefano Zampini idxs[c++] = jj[j];
462bbbc8e51SStefano Zampini }
463bbbc8e51SStefano Zampini }
46463a3b9bcSJacob Faibussowitsch PetscCheck(c == ii[m] - m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, c, ii[m] - m);
4659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis_own, &rows));
466bbbc8e51SStefano Zampini *adjacency = idxs;
467bbbc8e51SStefano Zampini }
468bbbc8e51SStefano Zampini
469bbbc8e51SStefano Zampini /* cleanup */
4709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis_own));
4719566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg));
4725f80ce2aSJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format");
4739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn));
4743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
475bbbc8e51SStefano Zampini }
476bbbc8e51SStefano Zampini
477bbbc8e51SStefano Zampini /*@C
478bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner
479bbbc8e51SStefano Zampini
48020f4b53cSBarry Smith Collective
481a1cb98faSBarry Smith
482bbbc8e51SStefano Zampini Input Parameters:
483a1cb98faSBarry Smith + dm - The mesh `DM`
484bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph
485bbbc8e51SStefano Zampini
486d8d19677SJose E. Roman Output Parameters:
487bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph
488bbbc8e51SStefano Zampini . offsets - Point offsets in the graph
489bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph
490bbbc8e51SStefano 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.
491bbbc8e51SStefano Zampini
49220f4b53cSBarry Smith Options Database Key:
4935a107427SMatthew G. Knepley . -dm_plex_csr_alg <mat,graph,overlap> - Choose the algorithm for computing the CSR graph
4945a107427SMatthew G. Knepley
495bbbc8e51SStefano Zampini Level: developer
496bbbc8e51SStefano Zampini
497a1cb98faSBarry Smith Note:
498a1cb98faSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function
499a1cb98faSBarry Smith representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree().
500a1cb98faSBarry Smith
5011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPartitionerGetType()`, `PetscPartitionerCreate()`, `DMSetAdjacency()`
502bbbc8e51SStefano Zampini @*/
DMPlexCreatePartitionerGraph(DM dm,PetscInt height,PetscInt * numVertices,PetscInt ** offsets,PetscInt ** adjacency,IS * globalNumbering)503d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering)
504d71ae5a4SJacob Faibussowitsch {
5055a107427SMatthew G. Knepley DMPlexCSRAlgorithm alg = DM_PLEX_CSR_GRAPH;
506bbbc8e51SStefano Zampini
507bbbc8e51SStefano Zampini PetscFunctionBegin;
5089566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_csr_alg", DMPlexCSRAlgorithms, (PetscEnum *)&alg, NULL));
5095a107427SMatthew G. Knepley switch (alg) {
510d71ae5a4SJacob Faibussowitsch case DM_PLEX_CSR_MAT:
511d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering));
512d71ae5a4SJacob Faibussowitsch break;
513d71ae5a4SJacob Faibussowitsch case DM_PLEX_CSR_GRAPH:
514d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering));
515d71ae5a4SJacob Faibussowitsch break;
516d71ae5a4SJacob Faibussowitsch case DM_PLEX_CSR_OVERLAP:
517d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_Overlap(dm, height, numVertices, offsets, adjacency, globalNumbering));
518d71ae5a4SJacob Faibussowitsch break;
519bbbc8e51SStefano Zampini }
5203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
521bbbc8e51SStefano Zampini }
522bbbc8e51SStefano Zampini
523d5577e40SMatthew G. Knepley /*@C
524d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format.
525d5577e40SMatthew G. Knepley
52620f4b53cSBarry Smith Collective
527d5577e40SMatthew G. Knepley
5284165533cSJose E. Roman Input Parameters:
529a1cb98faSBarry Smith + dm - The `DMPLEX`
530d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0)
531d5577e40SMatthew G. Knepley
5324165533cSJose E. Roman Output Parameters:
533d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh.
534d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell
535d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells
536d5577e40SMatthew G. Knepley
537d5577e40SMatthew G. Knepley Level: advanced
538d5577e40SMatthew G. Knepley
539a1cb98faSBarry Smith Note:
540a1cb98faSBarry Smith This is suitable for input to a mesh partitioner like ParMetis.
541a1cb98faSBarry Smith
5421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`
543d5577e40SMatthew G. Knepley @*/
DMPlexCreateNeighborCSR(DM dm,PetscInt cellHeight,PetscInt * numVertices,PetscInt ** offsets,PetscInt ** adjacency)544d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency)
545d71ae5a4SJacob Faibussowitsch {
54670034214SMatthew G. Knepley const PetscInt maxFaceCases = 30;
54770034214SMatthew G. Knepley PetscInt numFaceCases = 0;
54870034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */
54970034214SMatthew G. Knepley PetscInt *off, *adj;
55070034214SMatthew G. Knepley PetscInt *neighborCells = NULL;
55170034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell;
55270034214SMatthew G. Knepley
55370034214SMatthew G. Knepley PetscFunctionBegin;
55470034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */
5559566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
55670034214SMatthew G. Knepley cellDim = dim - cellHeight;
5579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
5589566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
55970034214SMatthew G. Knepley if (cEnd - cStart == 0) {
56070034214SMatthew G. Knepley if (numVertices) *numVertices = 0;
56170034214SMatthew G. Knepley if (offsets) *offsets = NULL;
56270034214SMatthew G. Knepley if (adjacency) *adjacency = NULL;
5633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
56470034214SMatthew G. Knepley }
56570034214SMatthew G. Knepley numCells = cEnd - cStart;
56670034214SMatthew G. Knepley faceDepth = depth - cellHeight;
56770034214SMatthew G. Knepley if (dim == depth) {
56870034214SMatthew G. Knepley PetscInt f, fStart, fEnd;
56970034214SMatthew G. Knepley
5709566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells + 1, &off));
57170034214SMatthew G. Knepley /* Count neighboring cells */
5729566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight + 1, &fStart, &fEnd));
57370034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) {
57470034214SMatthew G. Knepley const PetscInt *support;
57570034214SMatthew G. Knepley PetscInt supportSize;
5769566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize));
5779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support));
57870034214SMatthew G. Knepley if (supportSize == 2) {
5799ffc88e4SToby Isaac PetscInt numChildren;
5809ffc88e4SToby Isaac
5819566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, NULL));
5829ffc88e4SToby Isaac if (!numChildren) {
58370034214SMatthew G. Knepley ++off[support[0] - cStart + 1];
58470034214SMatthew G. Knepley ++off[support[1] - cStart + 1];
58570034214SMatthew G. Knepley }
58670034214SMatthew G. Knepley }
5879ffc88e4SToby Isaac }
58870034214SMatthew G. Knepley /* Prefix sum */
58970034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c - 1];
59070034214SMatthew G. Knepley if (adjacency) {
59170034214SMatthew G. Knepley PetscInt *tmp;
59270034214SMatthew G. Knepley
5939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj));
5949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells + 1, &tmp));
5959566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(tmp, off, numCells + 1));
59670034214SMatthew G. Knepley /* Get neighboring cells */
59770034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) {
59870034214SMatthew G. Knepley const PetscInt *support;
59970034214SMatthew G. Knepley PetscInt supportSize;
6009566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize));
6019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support));
60270034214SMatthew G. Knepley if (supportSize == 2) {
6039ffc88e4SToby Isaac PetscInt numChildren;
6049ffc88e4SToby Isaac
6059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, NULL));
6069ffc88e4SToby Isaac if (!numChildren) {
60770034214SMatthew G. Knepley adj[tmp[support[0] - cStart]++] = support[1];
60870034214SMatthew G. Knepley adj[tmp[support[1] - cStart]++] = support[0];
60970034214SMatthew G. Knepley }
61070034214SMatthew G. Knepley }
6119ffc88e4SToby Isaac }
61263a3b9bcSJacob Faibussowitsch for (c = 0; c < cEnd - cStart; ++c) PetscAssert(tmp[c] == off[c + 1], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %" PetscInt_FMT " != %" PetscInt_FMT " for cell %" PetscInt_FMT, tmp[c], off[c], c + cStart);
6139566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp));
61470034214SMatthew G. Knepley }
61570034214SMatthew G. Knepley if (numVertices) *numVertices = numCells;
61670034214SMatthew G. Knepley if (offsets) *offsets = off;
61770034214SMatthew G. Knepley if (adjacency) *adjacency = adj;
6183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
61970034214SMatthew G. Knepley }
62070034214SMatthew G. Knepley /* Setup face recognition */
62170034214SMatthew G. Knepley if (faceDepth == 1) {
62270034214SMatthew 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 */
62370034214SMatthew G. Knepley
62470034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
62570034214SMatthew G. Knepley PetscInt corners;
62670034214SMatthew G. Knepley
6279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &corners));
62870034214SMatthew G. Knepley if (!cornersSeen[corners]) {
62970034214SMatthew G. Knepley PetscInt nFV;
63070034214SMatthew G. Knepley
6315f80ce2aSJacob Faibussowitsch PetscCheck(numFaceCases < maxFaceCases, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases");
63270034214SMatthew G. Knepley cornersSeen[corners] = 1;
63370034214SMatthew G. Knepley
6349566063dSJacob Faibussowitsch PetscCall(DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV));
63570034214SMatthew G. Knepley
63670034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV;
63770034214SMatthew G. Knepley }
63870034214SMatthew G. Knepley }
63970034214SMatthew G. Knepley }
6409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells + 1, &off));
64170034214SMatthew G. Knepley /* Count neighboring cells */
64270034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) {
64370034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n;
64470034214SMatthew G. Knepley
6459566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells));
64670034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
64770034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) {
64870034214SMatthew G. Knepley PetscInt cellPair[2];
64970034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE;
65070034214SMatthew G. Knepley PetscInt meetSize = 0;
65170034214SMatthew G. Knepley const PetscInt *meet = NULL;
65270034214SMatthew G. Knepley
6539371c9d4SSatish Balay cellPair[0] = cell;
6549371c9d4SSatish Balay cellPair[1] = neighborCells[n];
65570034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue;
65670034214SMatthew G. Knepley if (!found) {
6579566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet));
65870034214SMatthew G. Knepley if (meetSize) {
65970034214SMatthew G. Knepley PetscInt f;
66070034214SMatthew G. Knepley
66170034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) {
66270034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) {
66370034214SMatthew G. Knepley found = PETSC_TRUE;
66470034214SMatthew G. Knepley break;
66570034214SMatthew G. Knepley }
66670034214SMatthew G. Knepley }
66770034214SMatthew G. Knepley }
6689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet));
66970034214SMatthew G. Knepley }
67070034214SMatthew G. Knepley if (found) ++off[cell - cStart + 1];
67170034214SMatthew G. Knepley }
67270034214SMatthew G. Knepley }
67370034214SMatthew G. Knepley /* Prefix sum */
67470034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell - 1];
67570034214SMatthew G. Knepley
67670034214SMatthew G. Knepley if (adjacency) {
6779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj));
67870034214SMatthew G. Knepley /* Get neighboring cells */
67970034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) {
68070034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n;
68170034214SMatthew G. Knepley PetscInt cellOffset = 0;
68270034214SMatthew G. Knepley
6839566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells));
68470034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
68570034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) {
68670034214SMatthew G. Knepley PetscInt cellPair[2];
68770034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE;
68870034214SMatthew G. Knepley PetscInt meetSize = 0;
68970034214SMatthew G. Knepley const PetscInt *meet = NULL;
69070034214SMatthew G. Knepley
6919371c9d4SSatish Balay cellPair[0] = cell;
6929371c9d4SSatish Balay cellPair[1] = neighborCells[n];
69370034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue;
69470034214SMatthew G. Knepley if (!found) {
6959566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet));
69670034214SMatthew G. Knepley if (meetSize) {
69770034214SMatthew G. Knepley PetscInt f;
69870034214SMatthew G. Knepley
69970034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) {
70070034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) {
70170034214SMatthew G. Knepley found = PETSC_TRUE;
70270034214SMatthew G. Knepley break;
70370034214SMatthew G. Knepley }
70470034214SMatthew G. Knepley }
70570034214SMatthew G. Knepley }
7069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet));
70770034214SMatthew G. Knepley }
70870034214SMatthew G. Knepley if (found) {
70970034214SMatthew G. Knepley adj[off[cell - cStart] + cellOffset] = neighborCells[n];
71070034214SMatthew G. Knepley ++cellOffset;
71170034214SMatthew G. Knepley }
71270034214SMatthew G. Knepley }
71370034214SMatthew G. Knepley }
71470034214SMatthew G. Knepley }
7159566063dSJacob Faibussowitsch PetscCall(PetscFree(neighborCells));
71670034214SMatthew G. Knepley if (numVertices) *numVertices = numCells;
71770034214SMatthew G. Knepley if (offsets) *offsets = off;
71870034214SMatthew G. Knepley if (adjacency) *adjacency = adj;
7193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
72070034214SMatthew G. Knepley }
72170034214SMatthew G. Knepley
72277623264SMatthew G. Knepley /*@
7233c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh
72477623264SMatthew G. Knepley
72520f4b53cSBarry Smith Collective
72677623264SMatthew G. Knepley
72777623264SMatthew G. Knepley Input Parameters:
728a1cb98faSBarry Smith + part - The `PetscPartitioner`
72920f4b53cSBarry Smith . targetSection - The `PetscSection` describing the absolute weight of each partition (can be `NULL`)
730a1cb98faSBarry Smith - dm - The mesh `DM`
73177623264SMatthew G. Knepley
73277623264SMatthew G. Knepley Output Parameters:
733a1cb98faSBarry Smith + partSection - The `PetscSection` giving the division of points by partition
734f8987ae8SMichael Lange - partition - The list of points by partition
73577623264SMatthew G. Knepley
73677623264SMatthew G. Knepley Level: developer
73777623264SMatthew G. Knepley
738a1cb98faSBarry Smith Note:
739a1cb98faSBarry Smith If the `DM` has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified
740a1cb98faSBarry Smith by the section in the transitive closure of the point.
741a1cb98faSBarry Smith
7421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPartitioner`, `PetscSection`, `DMPlexDistribute()`, `PetscPartitionerCreate()`, `PetscSectionCreate()`,
743a1cb98faSBarry Smith `PetscSectionSetChart()`, `PetscPartitionerPartition()`
7444b15ede2SMatthew G. Knepley @*/
PetscPartitionerDMPlexPartition(PetscPartitioner part,DM dm,PetscSection targetSection,PetscSection partSection,IS * partition)745d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition)
746d71ae5a4SJacob Faibussowitsch {
74777623264SMatthew G. Knepley PetscMPIInt size;
7483c41b853SStefano Zampini PetscBool isplex;
74921c92275SMatthew G. Knepley PetscSection vertSection = NULL, edgeSection = NULL;
75077623264SMatthew G. Knepley
75177623264SMatthew G. Knepley PetscFunctionBegin;
75277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
75377623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
7543c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3);
75577623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4);
7564f572ea9SToby Isaac PetscAssertPointer(partition, 5);
7579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isplex));
7585f80ce2aSJacob Faibussowitsch PetscCheck(isplex, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not for type %s", ((PetscObject)dm)->type_name);
7599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)part), &size));
76077623264SMatthew G. Knepley if (size == 1) {
76177623264SMatthew G. Knepley PetscInt *points;
76277623264SMatthew G. Knepley PetscInt cStart, cEnd, c;
76377623264SMatthew G. Knepley
7649566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd));
7659566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(partSection));
7669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(partSection, 0, size));
7679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(partSection, 0, cEnd - cStart));
7689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(partSection));
7699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &points));
77077623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c;
7719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)part), cEnd - cStart, points, PETSC_OWN_POINTER, partition));
7723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
77377623264SMatthew G. Knepley }
77477623264SMatthew G. Knepley if (part->height == 0) {
775074d466cSStefano Zampini PetscInt numVertices = 0;
77677623264SMatthew G. Knepley PetscInt *start = NULL;
77777623264SMatthew G. Knepley PetscInt *adjacency = NULL;
7783fa7752dSToby Isaac IS globalNumbering;
77977623264SMatthew G. Knepley
7803b9d9b65SStefano Zampini if (!part->noGraph || part->viewerGraph) {
7819566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering));
78213911537SStefano Zampini } else { /* only compute the number of owned local vertices */
783074d466cSStefano Zampini const PetscInt *idxs;
784074d466cSStefano Zampini PetscInt p, pStart, pEnd;
785074d466cSStefano Zampini
7869566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd));
7879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering));
7889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &idxs));
789074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1;
7909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering, &idxs));
791074d466cSStefano Zampini }
7923c41b853SStefano Zampini if (part->usevwgt) {
7933c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL;
7943c41b853SStefano Zampini IS clPoints = NULL;
7953c41b853SStefano Zampini const PetscInt *gid, *clIdx;
7963c41b853SStefano Zampini PetscInt v, p, pStart, pEnd;
7970358368aSMatthew G. Knepley
7983c41b853SStefano 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) */
7993c41b853SStefano Zampini /* We do this only if the local section has been set */
8003c41b853SStefano Zampini if (section) {
8019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL));
80248a46eb9SPierre Jolivet if (!clSection) PetscCall(DMPlexCreateClosureIndex(dm, NULL));
8039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints));
8049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(clPoints, &clIdx));
8053c41b853SStefano Zampini }
8069566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd));
8079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &vertSection));
8089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(vertSection, 0, numVertices));
809ac530a7eSPierre Jolivet if (globalNumbering) PetscCall(ISGetIndices(globalNumbering, &gid));
810ac530a7eSPierre Jolivet else gid = NULL;
8113c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) {
8123c41b853SStefano Zampini PetscInt dof = 1;
8130358368aSMatthew G. Knepley
8143c41b853SStefano Zampini /* skip cells in the overlap */
8153c41b853SStefano Zampini if (gid && gid[p - pStart] < 0) continue;
8163c41b853SStefano Zampini
8173c41b853SStefano Zampini if (section) {
8183c41b853SStefano Zampini PetscInt cl, clSize, clOff;
8193c41b853SStefano Zampini
8203c41b853SStefano Zampini dof = 0;
8219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(clSection, p, &clSize));
8229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(clSection, p, &clOff));
8233c41b853SStefano Zampini for (cl = 0; cl < clSize; cl += 2) {
8243c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */
8253c41b853SStefano Zampini
8269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, clPoint, &clDof));
8273c41b853SStefano Zampini dof += clDof;
8280358368aSMatthew G. Knepley }
8290358368aSMatthew G. Knepley }
83063a3b9bcSJacob Faibussowitsch PetscCheck(dof, PETSC_COMM_SELF, PETSC_ERR_SUP, "Number of dofs for point %" PetscInt_FMT " in the local section should be positive", p);
8319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(vertSection, v, dof));
8323c41b853SStefano Zampini v++;
8333c41b853SStefano Zampini }
83448a46eb9SPierre Jolivet if (globalNumbering) PetscCall(ISRestoreIndices(globalNumbering, &gid));
83548a46eb9SPierre Jolivet if (clPoints) PetscCall(ISRestoreIndices(clPoints, &clIdx));
8369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(vertSection));
8373c41b853SStefano Zampini }
83821c92275SMatthew G. Knepley if (part->useewgt) {
83921c92275SMatthew G. Knepley const PetscInt numEdges = start[numVertices];
84021c92275SMatthew G. Knepley
84121c92275SMatthew G. Knepley PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &edgeSection));
84221c92275SMatthew G. Knepley PetscCall(PetscSectionSetChart(edgeSection, 0, numEdges));
84321c92275SMatthew G. Knepley for (PetscInt e = 0; e < start[numVertices]; ++e) PetscCall(PetscSectionSetDof(edgeSection, e, 1));
84421c92275SMatthew G. Knepley for (PetscInt v = 0; v < numVertices; ++v) {
84521c92275SMatthew G. Knepley DMPolytopeType ct;
84621c92275SMatthew G. Knepley
84721c92275SMatthew G. Knepley // Assume v is the cell number
84821c92275SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, v, &ct));
84921c92275SMatthew G. Knepley if (ct != DM_POLYTOPE_POINT_PRISM_TENSOR && ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) continue;
85021c92275SMatthew G. Knepley
85121c92275SMatthew G. Knepley for (PetscInt e = start[v]; e < start[v + 1]; ++e) PetscCall(PetscSectionSetDof(edgeSection, e, 3));
85221c92275SMatthew G. Knepley }
85321c92275SMatthew G. Knepley PetscCall(PetscSectionSetUp(edgeSection));
85421c92275SMatthew G. Knepley }
85521c92275SMatthew G. Knepley PetscCall(PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, edgeSection, targetSection, partSection, partition));
8569566063dSJacob Faibussowitsch PetscCall(PetscFree(start));
8579566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency));
8583fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */
8593fa7752dSToby Isaac const PetscInt *globalNum;
8603fa7752dSToby Isaac const PetscInt *partIdx;
8613fa7752dSToby Isaac PetscInt *map, cStart, cEnd;
8623fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset;
8633fa7752dSToby Isaac IS newPartition;
8643fa7752dSToby Isaac
8659566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*partition, &localSize));
8669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize, &adjusted));
8679566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &globalNum));
8689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*partition, &partIdx));
8699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize, &map));
8709566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd));
8713fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) {
8723fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i;
8733fa7752dSToby Isaac }
874ad540459SPierre Jolivet for (i = 0; i < localSize; i++) adjusted[i] = map[partIdx[i]];
8759566063dSJacob Faibussowitsch PetscCall(PetscFree(map));
8769566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*partition, &partIdx));
8779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering, &globalNum));
8789566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, localSize, adjusted, PETSC_OWN_POINTER, &newPartition));
8799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalNumbering));
8809566063dSJacob Faibussowitsch PetscCall(ISDestroy(partition));
8813fa7752dSToby Isaac *partition = newPartition;
8823fa7752dSToby Isaac }
88363a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %" PetscInt_FMT " for points to partition", part->height);
8849566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&vertSection));
88521c92275SMatthew G. Knepley PetscCall(PetscSectionDestroy(&edgeSection));
8863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
88777623264SMatthew G. Knepley }
88877623264SMatthew G. Knepley
8895680f57bSMatthew G. Knepley /*@
8905680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner
8915680f57bSMatthew G. Knepley
89220f4b53cSBarry Smith Not Collective
8935680f57bSMatthew G. Knepley
8945680f57bSMatthew G. Knepley Input Parameter:
895a1cb98faSBarry Smith . dm - The `DM`
8965680f57bSMatthew G. Knepley
8975680f57bSMatthew G. Knepley Output Parameter:
898a1cb98faSBarry Smith . part - The `PetscPartitioner`
8995680f57bSMatthew G. Knepley
9005680f57bSMatthew G. Knepley Level: developer
9015680f57bSMatthew G. Knepley
902a1cb98faSBarry Smith Note:
903a1cb98faSBarry Smith This gets a borrowed reference, so the user should not destroy this `PetscPartitioner`.
90498599a47SLawrence Mitchell
9051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPartitioner`, `PetscSection`, `DMPlexDistribute()`, `DMPlexSetPartitioner()`, `PetscPartitionerDMPlexPartition()`, `PetscPartitionerCreate()`
9065680f57bSMatthew G. Knepley @*/
DMPlexGetPartitioner(DM dm,PetscPartitioner * part)907d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part)
908d71ae5a4SJacob Faibussowitsch {
9095680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
9105680f57bSMatthew G. Knepley
9115680f57bSMatthew G. Knepley PetscFunctionBegin;
9125680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9134f572ea9SToby Isaac PetscAssertPointer(part, 2);
9145680f57bSMatthew G. Knepley *part = mesh->partitioner;
9153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9165680f57bSMatthew G. Knepley }
9175680f57bSMatthew G. Knepley
91871bb2955SLawrence Mitchell /*@
91971bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner
92071bb2955SLawrence Mitchell
92120f4b53cSBarry Smith logically Collective
92271bb2955SLawrence Mitchell
92371bb2955SLawrence Mitchell Input Parameters:
924a1cb98faSBarry Smith + dm - The `DM`
92571bb2955SLawrence Mitchell - part - The partitioner
92671bb2955SLawrence Mitchell
92771bb2955SLawrence Mitchell Level: developer
92871bb2955SLawrence Mitchell
929a1cb98faSBarry Smith Note:
930a1cb98faSBarry Smith Any existing `PetscPartitioner` will be destroyed.
93171bb2955SLawrence Mitchell
9321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPartitioner`,`DMPlexDistribute()`, `DMPlexGetPartitioner()`, `PetscPartitionerCreate()`
93371bb2955SLawrence Mitchell @*/
DMPlexSetPartitioner(DM dm,PetscPartitioner part)934d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part)
935d71ae5a4SJacob Faibussowitsch {
93671bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data;
93771bb2955SLawrence Mitchell
93871bb2955SLawrence Mitchell PetscFunctionBegin;
93971bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94071bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2);
9419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)part));
9429566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
94371bb2955SLawrence Mitchell mesh->partitioner = part;
9443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
94571bb2955SLawrence Mitchell }
94671bb2955SLawrence Mitchell
DMPlexAddClosure_Private(DM dm,PetscHSetI ht,PetscInt point)947d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point)
948d71ae5a4SJacob Faibussowitsch {
9498e330a33SStefano Zampini const PetscInt *cone;
9508e330a33SStefano Zampini PetscInt coneSize, c;
9518e330a33SStefano Zampini PetscBool missing;
9528e330a33SStefano Zampini
9538e330a33SStefano Zampini PetscFunctionBeginHot;
9549566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht, point, &missing));
9558e330a33SStefano Zampini if (missing) {
9569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone));
9579566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
95848a46eb9SPierre Jolivet for (c = 0; c < coneSize; c++) PetscCall(DMPlexAddClosure_Private(dm, ht, cone[c]));
9598e330a33SStefano Zampini }
9603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9618e330a33SStefano Zampini }
9628e330a33SStefano Zampini
DMPlexAddClosure_Tree(DM dm,PetscHSetI ht,PetscInt point,PetscBool up,PetscBool down)963d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down)
964d71ae5a4SJacob Faibussowitsch {
965270bba0cSToby Isaac PetscFunctionBegin;
9666a5a2ffdSToby Isaac if (up) {
9676a5a2ffdSToby Isaac PetscInt parent;
9686a5a2ffdSToby Isaac
9699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL));
9706a5a2ffdSToby Isaac if (parent != point) {
9716a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i;
9726a5a2ffdSToby Isaac
9739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure));
974270bba0cSToby Isaac for (i = 0; i < closureSize; i++) {
975270bba0cSToby Isaac PetscInt cpoint = closure[2 * i];
976270bba0cSToby Isaac
9779566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint));
9789566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm, ht, cpoint, PETSC_TRUE, PETSC_FALSE));
979270bba0cSToby Isaac }
9809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure));
9816a5a2ffdSToby Isaac }
9826a5a2ffdSToby Isaac }
9836a5a2ffdSToby Isaac if (down) {
9846a5a2ffdSToby Isaac PetscInt numChildren;
9856a5a2ffdSToby Isaac const PetscInt *children;
9866a5a2ffdSToby Isaac
9879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children));
9886a5a2ffdSToby Isaac if (numChildren) {
9896a5a2ffdSToby Isaac PetscInt i;
9906a5a2ffdSToby Isaac
9916a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) {
9926a5a2ffdSToby Isaac PetscInt cpoint = children[i];
9936a5a2ffdSToby Isaac
9949566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint));
9959566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm, ht, cpoint, PETSC_FALSE, PETSC_TRUE));
9966a5a2ffdSToby Isaac }
9976a5a2ffdSToby Isaac }
9986a5a2ffdSToby Isaac }
9993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1000270bba0cSToby Isaac }
1001270bba0cSToby Isaac
DMPlexAddClosureTree_Up_Private(DM dm,PetscHSetI ht,PetscInt point)1002d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point)
1003d71ae5a4SJacob Faibussowitsch {
10048e330a33SStefano Zampini PetscInt parent;
1005825f8a23SLisandro Dalcin
10068e330a33SStefano Zampini PetscFunctionBeginHot;
10079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL));
10088e330a33SStefano Zampini if (point != parent) {
10098e330a33SStefano Zampini const PetscInt *cone;
10108e330a33SStefano Zampini PetscInt coneSize, c;
10118e330a33SStefano Zampini
10129566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, parent));
10139566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, parent));
10149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, parent, &cone));
10159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize));
10168e330a33SStefano Zampini for (c = 0; c < coneSize; c++) {
10178e330a33SStefano Zampini const PetscInt cp = cone[c];
10188e330a33SStefano Zampini
10199566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, cp));
10208e330a33SStefano Zampini }
10218e330a33SStefano Zampini }
10223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10238e330a33SStefano Zampini }
10248e330a33SStefano Zampini
DMPlexAddClosureTree_Down_Private(DM dm,PetscHSetI ht,PetscInt point)1025d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point)
1026d71ae5a4SJacob Faibussowitsch {
10278e330a33SStefano Zampini PetscInt i, numChildren;
10288e330a33SStefano Zampini const PetscInt *children;
10298e330a33SStefano Zampini
10308e330a33SStefano Zampini PetscFunctionBeginHot;
10319566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children));
103248a46eb9SPierre Jolivet for (i = 0; i < numChildren; i++) PetscCall(PetscHSetIAdd(ht, children[i]));
10333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10348e330a33SStefano Zampini }
10358e330a33SStefano Zampini
DMPlexAddClosureTree_Private(DM dm,PetscHSetI ht,PetscInt point)1036d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point)
1037d71ae5a4SJacob Faibussowitsch {
10388e330a33SStefano Zampini const PetscInt *cone;
10398e330a33SStefano Zampini PetscInt coneSize, c;
10408e330a33SStefano Zampini
10418e330a33SStefano Zampini PetscFunctionBeginHot;
10429566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, point));
10439566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, point));
10449566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Down_Private(dm, ht, point));
10459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone));
10469566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
104748a46eb9SPierre Jolivet for (c = 0; c < coneSize; c++) PetscCall(DMPlexAddClosureTree_Private(dm, ht, cone[c]));
10483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10498e330a33SStefano Zampini }
10508e330a33SStefano Zampini
DMPlexClosurePoints_Private(DM dm,PetscInt numPoints,const PetscInt points[],IS * closureIS)1051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS)
1052d71ae5a4SJacob Faibussowitsch {
1053825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data;
10548e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE;
10558e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p;
105627104ee2SJacob Faibussowitsch PetscHSetI ht = NULL;
1057825f8a23SLisandro Dalcin
1058825f8a23SLisandro Dalcin PetscFunctionBegin;
10599566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht));
10609566063dSJacob Faibussowitsch PetscCall(PetscHSetIResize(ht, numPoints * 16));
10618e330a33SStefano Zampini if (!hasTree) {
106248a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexAddClosure_Private(dm, ht, points[p]));
10638e330a33SStefano Zampini } else {
10648e330a33SStefano Zampini #if 1
106548a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexAddClosureTree_Private(dm, ht, points[p]));
10668e330a33SStefano Zampini #else
10678e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c;
1068825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) {
10699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure));
1070825f8a23SLisandro Dalcin for (c = 0; c < closureSize * 2; c += 2) {
10719566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, closure[c]));
10729566063dSJacob Faibussowitsch if (hasTree) PetscCall(DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE));
1073825f8a23SLisandro Dalcin }
1074825f8a23SLisandro Dalcin }
10759566063dSJacob Faibussowitsch if (closure) PetscCall(DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure));
10768e330a33SStefano Zampini #endif
10778e330a33SStefano Zampini }
10789566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nelems));
10799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nelems, &elems));
10809566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &off, elems));
10819566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht));
10829566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nelems, elems));
10839566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS));
10843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1085825f8a23SLisandro Dalcin }
1086825f8a23SLisandro Dalcin
10875abbe4feSMichael Lange /*@
10885abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label
10895abbe4feSMichael Lange
10905abbe4feSMichael Lange Input Parameters:
1091a1cb98faSBarry Smith + dm - The `DM`
1092a1cb98faSBarry Smith - label - `DMLabel` assigning ranks to remote roots
10935abbe4feSMichael Lange
10945abbe4feSMichael Lange Level: developer
10955abbe4feSMichael Lange
1096*7d7af440SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`
10975abbe4feSMichael Lange @*/
DMPlexPartitionLabelClosure(DM dm,DMLabel label)1098d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label)
1099d71ae5a4SJacob Faibussowitsch {
1100825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS;
11015abbe4feSMichael Lange const PetscInt *ranks, *points;
1102825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r;
11039ffc88e4SToby Isaac
11049ffc88e4SToby Isaac PetscFunctionBegin;
11059566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS));
11069566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks));
11079566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks));
11085abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) {
11095abbe4feSMichael Lange const PetscInt rank = ranks[r];
11109566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS));
11119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints));
11129566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points));
11139566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS));
11149566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points));
11159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
11169566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, rank, closureIS));
11179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&closureIS));
11189ffc88e4SToby Isaac }
11199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks));
11209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS));
11213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
11229ffc88e4SToby Isaac }
11239ffc88e4SToby Isaac
112424d039d7SMichael Lange /*@
112524d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label
112624d039d7SMichael Lange
112724d039d7SMichael Lange Input Parameters:
1128a1cb98faSBarry Smith + dm - The `DM`
1129a1cb98faSBarry Smith - label - `DMLabel` assigning ranks to remote roots
113024d039d7SMichael Lange
113124d039d7SMichael Lange Level: developer
113224d039d7SMichael Lange
1133*7d7af440SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`
113424d039d7SMichael Lange @*/
DMPlexPartitionLabelAdjacency(DM dm,DMLabel label)1135d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label)
1136d71ae5a4SJacob Faibussowitsch {
113724d039d7SMichael Lange IS rankIS, pointIS;
113824d039d7SMichael Lange const PetscInt *ranks, *points;
113924d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize;
114024d039d7SMichael Lange PetscInt *adj = NULL;
114170034214SMatthew G. Knepley
114270034214SMatthew G. Knepley PetscFunctionBegin;
11439566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS));
11449566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks));
11459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks));
114624d039d7SMichael Lange for (r = 0; r < numRanks; ++r) {
114724d039d7SMichael Lange const PetscInt rank = ranks[r];
114870034214SMatthew G. Knepley
11499566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS));
11509566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints));
11519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points));
115270034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) {
115324d039d7SMichael Lange adjSize = PETSC_DETERMINE;
11549566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, points[p], &adjSize, &adj));
11559566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(label, adj[a], rank));
115670034214SMatthew G. Knepley }
11579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points));
11589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
115970034214SMatthew G. Knepley }
11609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks));
11619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS));
11629566063dSJacob Faibussowitsch PetscCall(PetscFree(adj));
11633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
116470034214SMatthew G. Knepley }
116570034214SMatthew G. Knepley
1166be200f8dSMichael Lange /*@
1167a1cb98faSBarry Smith DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point `PetscSF`
1168be200f8dSMichael Lange
1169be200f8dSMichael Lange Input Parameters:
1170a1cb98faSBarry Smith + dm - The `DM`
1171a1cb98faSBarry Smith - label - `DMLabel` assigning ranks to remote roots
1172be200f8dSMichael Lange
1173be200f8dSMichael Lange Level: developer
1174be200f8dSMichael Lange
1175a1cb98faSBarry Smith Note:
1176a1cb98faSBarry Smith This is required when generating multi-level overlaps to capture
1177be200f8dSMichael Lange overlap points from non-neighbouring partitions.
1178be200f8dSMichael Lange
1179*7d7af440SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`
1180be200f8dSMichael Lange @*/
DMPlexPartitionLabelPropagate(DM dm,DMLabel label)1181d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label)
1182d71ae5a4SJacob Faibussowitsch {
1183be200f8dSMichael Lange MPI_Comm comm;
1184be200f8dSMichael Lange PetscMPIInt rank;
1185be200f8dSMichael Lange PetscSF sfPoint;
11865d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves;
1187be200f8dSMichael Lange IS rankIS, pointIS;
1188be200f8dSMichael Lange const PetscInt *ranks;
1189be200f8dSMichael Lange PetscInt numRanks, r;
1190be200f8dSMichael Lange
1191be200f8dSMichael Lange PetscFunctionBegin;
11929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
11949566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint));
11955d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */
11969566063dSJacob Faibussowitsch PetscCall(DMLabelGather(label, sfPoint, &lblLeaves));
11979566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblLeaves, &rankIS));
11989566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks));
11999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks));
12005d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) {
12015d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r];
12025d04f6ebSMichael Lange if (remoteRank == rank) continue;
12039566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS));
12049566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank));
12059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
12065d04f6ebSMichael Lange }
12079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks));
12089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS));
12099566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblLeaves));
1210be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */
12119566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, sfPoint, &lblRoots));
12129566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblRoots, &rankIS));
12139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks));
12149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks));
1215be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) {
1216be200f8dSMichael Lange const PetscInt remoteRank = ranks[r];
1217be200f8dSMichael Lange if (remoteRank == rank) continue;
12189566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS));
12199566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank));
12209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
1221be200f8dSMichael Lange }
12229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks));
12239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS));
12249566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblRoots));
12253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1226be200f8dSMichael Lange }
1227be200f8dSMichael Lange
12281fd9873aSMichael Lange /*@
12291fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label
12301fd9873aSMichael Lange
12311fd9873aSMichael Lange Input Parameters:
1232a1cb98faSBarry Smith + dm - The `DM`
1233a1cb98faSBarry Smith . rootLabel - `DMLabel` assigning ranks to local roots
1234fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank
12351fd9873aSMichael Lange
12361fd9873aSMichael Lange Output Parameter:
1237a1cb98faSBarry Smith . leafLabel - `DMLabel` assigning ranks to remote roots
12381fd9873aSMichael Lange
12391fd9873aSMichael Lange Level: developer
12401fd9873aSMichael Lange
1241a1cb98faSBarry Smith Note:
1242a1cb98faSBarry Smith The rootLabel defines a send pattern by mapping local points to remote target ranks. The
1243a1cb98faSBarry Smith resulting leafLabel is a receiver mapping of remote roots to their parent rank.
1244a1cb98faSBarry Smith
1245*7d7af440SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`
12461fd9873aSMichael Lange @*/
DMPlexPartitionLabelInvert(DM dm,DMLabel rootLabel,PetscSF processSF,DMLabel leafLabel)1247d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel)
1248d71ae5a4SJacob Faibussowitsch {
12491fd9873aSMichael Lange MPI_Comm comm;
1250874ddda9SLisandro Dalcin PetscMPIInt rank, size, r;
1251874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize;
12521fd9873aSMichael Lange PetscSF sfPoint;
1253874ddda9SLisandro Dalcin PetscSection rootSection;
12541fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints;
12551fd9873aSMichael Lange const PetscSFNode *remote;
12561fd9873aSMichael Lange const PetscInt *local, *neighbors;
12571fd9873aSMichael Lange IS valueIS;
1258874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE;
12591fd9873aSMichael Lange
12601fd9873aSMichael Lange PetscFunctionBegin;
12619566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelInvert, dm, 0, 0, 0));
12629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
12639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
12649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
12659566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint));
12661fd9873aSMichael Lange
12671fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */
12689566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSection));
12699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, 0, size));
12709566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(rootLabel, &valueIS));
12719566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numNeighbors));
12729566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &neighbors));
12731fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) {
12749566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints));
12759566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(rootSection, neighbors[n], numPoints));
12761fd9873aSMichael Lange }
12779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection));
12789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &rootSize));
12799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rootSize, &rootPoints));
12809566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote));
12811fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) {
12821fd9873aSMichael Lange IS pointIS;
12831fd9873aSMichael Lange const PetscInt *points;
12841fd9873aSMichael Lange
12859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off));
12869566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS));
12879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints));
12889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points));
12891fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) {
12909566063dSJacob Faibussowitsch if (local) PetscCall(PetscFindInt(points[p], nleaves, local, &l));
1291ad540459SPierre Jolivet else l = -1;
12929371c9d4SSatish Balay if (l >= 0) {
12939371c9d4SSatish Balay rootPoints[off + p] = remote[l];
12949371c9d4SSatish Balay } else {
12959371c9d4SSatish Balay rootPoints[off + p].index = points[p];
12969371c9d4SSatish Balay rootPoints[off + p].rank = rank;
12979371c9d4SSatish Balay }
12981fd9873aSMichael Lange }
12999566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points));
13009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
13011fd9873aSMichael Lange }
1302874ddda9SLisandro Dalcin
1303874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */
1304874ddda9SLisandro Dalcin if (!processSF) {
13056497c311SBarry Smith PetscCount counter = 0;
1306874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE;
1307874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls;
1308874ddda9SLisandro Dalcin
13099566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls));
1310874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) {
13119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, neighbors[n], &dof));
13129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off));
1313874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES)
13149371c9d4SSatish Balay if (dof > PETSC_MPI_INT_MAX) {
13159371c9d4SSatish Balay locOverflow = PETSC_TRUE;
13169371c9d4SSatish Balay break;
13179371c9d4SSatish Balay }
13189371c9d4SSatish Balay if (off > PETSC_MPI_INT_MAX) {
13199371c9d4SSatish Balay locOverflow = PETSC_TRUE;
13209371c9d4SSatish Balay break;
13219371c9d4SSatish Balay }
1322874ddda9SLisandro Dalcin #endif
1323835f2295SStefano Zampini PetscCall(PetscMPIIntCast(dof, &scounts[neighbors[n]]));
1324835f2295SStefano Zampini PetscCall(PetscMPIIntCast(off, &sdispls[neighbors[n]]));
1325874ddda9SLisandro Dalcin }
13269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm));
13279371c9d4SSatish Balay for (r = 0; r < size; ++r) {
1328835f2295SStefano Zampini PetscCall(PetscMPIIntCast(counter, &rdispls[r]));
13299371c9d4SSatish Balay counter += rcounts[r];
13309371c9d4SSatish Balay }
1331874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE;
13325440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&locOverflow, &mpiOverflow, 1, MPI_C_BOOL, MPI_LOR, comm));
1333874ddda9SLisandro Dalcin if (!mpiOverflow) {
13346497c311SBarry Smith PetscCall(PetscInfo(dm, "Using MPI_Alltoallv() for mesh distribution\n"));
1335835f2295SStefano Zampini PetscCall(PetscIntCast(counter, &leafSize));
13369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafSize, &leafPoints));
13376497c311SBarry Smith PetscCallMPI(MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_SF_NODE, leafPoints, rcounts, rdispls, MPIU_SF_NODE, comm));
1338874ddda9SLisandro Dalcin }
13399566063dSJacob Faibussowitsch PetscCall(PetscFree4(scounts, sdispls, rcounts, rdispls));
1340874ddda9SLisandro Dalcin }
1341874ddda9SLisandro Dalcin
1342874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */
1343874ddda9SLisandro Dalcin if (processSF || mpiOverflow) {
1344874ddda9SLisandro Dalcin PetscSF procSF;
1345874ddda9SLisandro Dalcin PetscSection leafSection;
1346874ddda9SLisandro Dalcin
1347874ddda9SLisandro Dalcin if (processSF) {
13489566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Using processSF for mesh distribution\n"));
13499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)processSF));
1350874ddda9SLisandro Dalcin procSF = processSF;
1351874ddda9SLisandro Dalcin } else {
13529566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Using processSF for mesh distribution (MPI overflow)\n"));
13539566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &procSF));
13549566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphWithPattern(procSF, NULL, PETSCSF_PATTERN_ALLTOALL));
1355874ddda9SLisandro Dalcin }
1356874ddda9SLisandro Dalcin
13579566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection));
13586497c311SBarry Smith PetscCall(DMPlexDistributeData(dm, procSF, rootSection, MPIU_SF_NODE, rootPoints, leafSection, (void **)&leafPoints));
13599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafSection, &leafSize));
13609566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection));
13619566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&procSF));
1362874ddda9SLisandro Dalcin }
1363874ddda9SLisandro Dalcin
136448a46eb9SPierre Jolivet for (p = 0; p < leafSize; p++) PetscCall(DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank));
1365874ddda9SLisandro Dalcin
13669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &neighbors));
13679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS));
13689566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection));
13699566063dSJacob Faibussowitsch PetscCall(PetscFree(rootPoints));
13709566063dSJacob Faibussowitsch PetscCall(PetscFree(leafPoints));
13719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelInvert, dm, 0, 0, 0));
13723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13731fd9873aSMichael Lange }
13741fd9873aSMichael Lange
1375aa3148a8SMichael Lange /*@
1376aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points
1377aa3148a8SMichael Lange
1378aa3148a8SMichael Lange Input Parameters:
1379a1cb98faSBarry Smith + dm - The `DM`
13803ac0285dSStefano Zampini . label - `DMLabel` assigning ranks to remote roots
13816497c311SBarry Smith - sortRanks - Whether or not to sort the `PetscSF` leaves by rank
1382aa3148a8SMichael Lange
1383aa3148a8SMichael Lange Output Parameter:
1384fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping
1385aa3148a8SMichael Lange
1386aa3148a8SMichael Lange Level: developer
1387aa3148a8SMichael Lange
1388a1cb98faSBarry Smith Note:
1389a1cb98faSBarry Smith The incoming label is a receiver mapping of remote points to their parent rank.
1390a1cb98faSBarry Smith
1391*7d7af440SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `PetscSF`, `DMPlexDistribute()`
1392aa3148a8SMichael Lange @*/
DMPlexPartitionLabelCreateSF(DM dm,DMLabel label,PetscBool sortRanks,PetscSF * sf)13933ac0285dSStefano Zampini PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscBool sortRanks, PetscSF *sf)
1394d71ae5a4SJacob Faibussowitsch {
13956e203dd9SStefano Zampini PetscMPIInt rank;
13966e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors;
1397aa3148a8SMichael Lange PetscSFNode *remotePoints;
13986e203dd9SStefano Zampini IS remoteRootIS, neighborsIS;
13996e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors;
14003ac0285dSStefano Zampini PetscMPIInt myRank;
1401aa3148a8SMichael Lange
1402aa3148a8SMichael Lange PetscFunctionBegin;
14039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelCreateSF, dm, 0, 0, 0));
14049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
14059566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &neighborsIS));
14063ac0285dSStefano Zampini
14073ac0285dSStefano Zampini if (sortRanks) {
14086e203dd9SStefano Zampini IS is;
14093ac0285dSStefano Zampini
14109566063dSJacob Faibussowitsch PetscCall(ISDuplicate(neighborsIS, &is));
14119566063dSJacob Faibussowitsch PetscCall(ISSort(is));
14129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS));
14136e203dd9SStefano Zampini neighborsIS = is;
14146e203dd9SStefano Zampini }
14153ac0285dSStefano Zampini myRank = sortRanks ? -1 : rank;
14163ac0285dSStefano Zampini
14179566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(neighborsIS, &nNeighbors));
14189566063dSJacob Faibussowitsch PetscCall(ISGetIndices(neighborsIS, &neighbors));
14196e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) {
14209566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, neighbors[n], &numPoints));
1421aa3148a8SMichael Lange numRemote += numPoints;
1422aa3148a8SMichael Lange }
14239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRemote, &remotePoints));
14243ac0285dSStefano Zampini
14253ac0285dSStefano Zampini /* Put owned points first if not sorting the ranks */
14263ac0285dSStefano Zampini if (!sortRanks) {
14279566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, rank, &numPoints));
142843f7d02bSMichael Lange if (numPoints > 0) {
14299566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &remoteRootIS));
14309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots));
143143f7d02bSMichael Lange for (p = 0; p < numPoints; p++) {
143243f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p];
143343f7d02bSMichael Lange remotePoints[idx].rank = rank;
143443f7d02bSMichael Lange idx++;
143543f7d02bSMichael Lange }
14369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots));
14379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS));
143843f7d02bSMichael Lange }
14393ac0285dSStefano Zampini }
14403ac0285dSStefano Zampini
144143f7d02bSMichael Lange /* Now add remote points */
14426e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) {
14436497c311SBarry Smith PetscMPIInt nn;
14446e203dd9SStefano Zampini
14456497c311SBarry Smith PetscCall(PetscMPIIntCast(neighbors[n], &nn));
14469566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, nn, &numPoints));
14473ac0285dSStefano Zampini if (nn == myRank || numPoints <= 0) continue;
14489566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, nn, &remoteRootIS));
14499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots));
1450aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) {
1451aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p];
14526e203dd9SStefano Zampini remotePoints[idx].rank = nn;
1453aa3148a8SMichael Lange idx++;
1454aa3148a8SMichael Lange }
14559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots));
14569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS));
1457aa3148a8SMichael Lange }
14583ac0285dSStefano Zampini
14599566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), sf));
14609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14619566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, pEnd - pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER));
14629566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(*sf));
14639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS));
14649566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelCreateSF, dm, 0, 0, 0));
14653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
146670034214SMatthew G. Knepley }
1467cb87ef4cSFlorian Wechsung
1468abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS)
1469abe9303eSLisandro Dalcin #include <parmetis.h>
1470abe9303eSLisandro Dalcin #endif
1471abe9303eSLisandro Dalcin
14726a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors
14736a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take
14746a3739e5SFlorian Wechsung * them out in that case. */
14756a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS)
1476a4e35b19SJacob Faibussowitsch /*
147754c05997SPierre Jolivet DMPlexRewriteSF - Rewrites the ownership of the `PetscSF` of a `DM` (in place).
14787f57c1a4SFlorian Wechsung
14796497c311SBarry Smith Input parameters:b
1480a1cb98faSBarry Smith + dm - The `DMPLEX` object.
1481fe2efc57SMark . n - The number of points.
1482a1cb98faSBarry Smith . pointsToRewrite - The points in the `PetscSF` whose ownership will change.
1483fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite.
1484a1cb98faSBarry Smith - degrees - Degrees of the points in the `PetscSF` as obtained by `PetscSFComputeDegreeBegin()`/`PetscSFComputeDegreeEnd()`.
14857f57c1a4SFlorian Wechsung
14867f57c1a4SFlorian Wechsung Level: developer
14877f57c1a4SFlorian Wechsung
1488*7d7af440SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `PetscSF`, `DMPlexDistribute()`
1489a4e35b19SJacob Faibussowitsch */
DMPlexRewriteSF(DM dm,PetscInt n,PetscInt * pointsToRewrite,PetscInt * targetOwners,const PetscInt * degrees)1490d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees)
1491d71ae5a4SJacob Faibussowitsch {
14925f80ce2aSJacob Faibussowitsch PetscInt pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs;
14937f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew;
14947f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew;
14957f57c1a4SFlorian Wechsung const PetscSFNode *iremote;
14967f57c1a4SFlorian Wechsung const PetscInt *ilocal;
14977f57c1a4SFlorian Wechsung PetscBool *isLeaf;
14987f57c1a4SFlorian Wechsung PetscSF sf;
14997f57c1a4SFlorian Wechsung MPI_Comm comm;
15005a30b08bSFlorian Wechsung PetscMPIInt rank, size;
15017f57c1a4SFlorian Wechsung
15027f57c1a4SFlorian Wechsung PetscFunctionBegin;
15039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
15059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
15069566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
15077f57c1a4SFlorian Wechsung
15089566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf));
15099566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote));
15109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isLeaf));
1511ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) isLeaf[i] = PETSC_FALSE;
1512ad540459SPierre Jolivet for (i = 0; i < nleafs; i++) isLeaf[ilocal[i] - pStart] = PETSC_TRUE;
15137f57c1a4SFlorian Wechsung
15149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart + 1, &cumSumDegrees));
15157f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0;
1516ad540459SPierre Jolivet for (i = 1; i <= pEnd - pStart; i++) cumSumDegrees[i] = cumSumDegrees[i - 1] + degrees[i - 1];
15177f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd - pStart];
15187f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */
15197f57c1a4SFlorian Wechsung
15209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &locationsOfLeafs));
15219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &rankOnLeafs));
1522ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) rankOnLeafs[i] = rank;
15239566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs));
15249566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs));
15259566063dSJacob Faibussowitsch PetscCall(PetscFree(rankOnLeafs));
15267f57c1a4SFlorian Wechsung
15277f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */
15289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs));
15299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &points));
1530ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) points[i] = pStart + i;
15319566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs));
15329566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs));
15339566063dSJacob Faibussowitsch PetscCall(PetscFree(points));
15347f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */
15359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &newOwners));
15369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &newNumbers));
15377f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) {
15387f57c1a4SFlorian Wechsung newOwners[i] = -1;
15397f57c1a4SFlorian Wechsung newNumbers[i] = -1;
15407f57c1a4SFlorian Wechsung }
15417f57c1a4SFlorian Wechsung {
15427f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner;
15437f57c1a4SFlorian Wechsung for (i = 0; i < n; i++) {
15447f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i];
15457f57c1a4SFlorian Wechsung newNumber = -1;
15467f57c1a4SFlorian Wechsung oldOwner = rank;
15477f57c1a4SFlorian Wechsung newOwner = targetOwners[i];
15487f57c1a4SFlorian Wechsung if (oldOwner == newOwner) {
15497f57c1a4SFlorian Wechsung newNumber = oldNumber;
15507f57c1a4SFlorian Wechsung } else {
15517f57c1a4SFlorian Wechsung for (j = 0; j < degrees[oldNumber]; j++) {
15527f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber] + j] == newOwner) {
15537f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber] + j];
15547f57c1a4SFlorian Wechsung break;
15557f57c1a4SFlorian Wechsung }
15567f57c1a4SFlorian Wechsung }
15577f57c1a4SFlorian Wechsung }
15585f80ce2aSJacob Faibussowitsch PetscCheck(newNumber != -1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex.");
15597f57c1a4SFlorian Wechsung
15607f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner;
15617f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber;
15627f57c1a4SFlorian Wechsung }
15637f57c1a4SFlorian Wechsung }
15649566063dSJacob Faibussowitsch PetscCall(PetscFree(cumSumDegrees));
15659566063dSJacob Faibussowitsch PetscCall(PetscFree(locationsOfLeafs));
15669566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteLocalPointOfLeafs));
15677f57c1a4SFlorian Wechsung
15689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners, MPI_REPLACE));
15699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners, MPI_REPLACE));
15709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers, MPI_REPLACE));
15719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers, MPI_REPLACE));
15727f57c1a4SFlorian Wechsung
15737f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */
15747f57c1a4SFlorian Wechsung leafCounter = 0;
15757f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) {
15767f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) {
1577ad540459SPierre Jolivet if (newOwners[i] != rank) leafCounter++;
15787f57c1a4SFlorian Wechsung } else {
1579ad540459SPierre Jolivet if (isLeaf[i]) leafCounter++;
15807f57c1a4SFlorian Wechsung }
15817f57c1a4SFlorian Wechsung }
15827f57c1a4SFlorian Wechsung
15837f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */
15849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafsNew));
15859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafLocationsNew));
15867f57c1a4SFlorian Wechsung
15877f57c1a4SFlorian Wechsung leafCounter = 0;
15887f57c1a4SFlorian Wechsung counter = 0;
15897f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) {
15907f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) {
15917f57c1a4SFlorian Wechsung if (newOwners[i] != rank) {
15927f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i;
15937f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i];
15947f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i];
15957f57c1a4SFlorian Wechsung leafCounter++;
15967f57c1a4SFlorian Wechsung }
15977f57c1a4SFlorian Wechsung } else {
15987f57c1a4SFlorian Wechsung if (isLeaf[i]) {
15997f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i;
16007f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank;
16017f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index;
16027f57c1a4SFlorian Wechsung leafCounter++;
16037f57c1a4SFlorian Wechsung }
16047f57c1a4SFlorian Wechsung }
1605ad540459SPierre Jolivet if (isLeaf[i]) counter++;
16067f57c1a4SFlorian Wechsung }
16077f57c1a4SFlorian Wechsung
16089566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER));
16099566063dSJacob Faibussowitsch PetscCall(PetscFree(newOwners));
16109566063dSJacob Faibussowitsch PetscCall(PetscFree(newNumbers));
16119566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf));
16123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
16137f57c1a4SFlorian Wechsung }
16147f57c1a4SFlorian Wechsung
DMPlexViewDistribution(MPI_Comm comm,PetscInt n,PetscInt skip,PetscInt * vtxwgt,PetscInt * part,PetscViewer viewer)1615d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer)
1616d71ae5a4SJacob Faibussowitsch {
16175f80ce2aSJacob Faibussowitsch PetscInt *distribution, min, max, sum;
16185a30b08bSFlorian Wechsung PetscMPIInt rank, size;
16195f80ce2aSJacob Faibussowitsch
1620125d2a8fSFlorian Wechsung PetscFunctionBegin;
16219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
16229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
16239566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &distribution));
16245f80ce2aSJacob Faibussowitsch for (PetscInt i = 0; i < n; i++) {
1625125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip * i];
1626125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip * i];
1627125d2a8fSFlorian Wechsung }
1628462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm));
1629125d2a8fSFlorian Wechsung min = distribution[0];
1630125d2a8fSFlorian Wechsung max = distribution[0];
1631125d2a8fSFlorian Wechsung sum = distribution[0];
16325f80ce2aSJacob Faibussowitsch for (PetscInt i = 1; i < size; i++) {
1633125d2a8fSFlorian Wechsung if (distribution[i] < min) min = distribution[i];
1634125d2a8fSFlorian Wechsung if (distribution[i] > max) max = distribution[i];
1635125d2a8fSFlorian Wechsung sum += distribution[i];
1636125d2a8fSFlorian Wechsung }
163763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Min: %" PetscInt_FMT ", Avg: %" PetscInt_FMT ", Max: %" PetscInt_FMT ", Balance: %f\n", min, sum / size, max, (max * 1. * size) / sum));
16389566063dSJacob Faibussowitsch PetscCall(PetscFree(distribution));
16393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1640125d2a8fSFlorian Wechsung }
1641125d2a8fSFlorian Wechsung
16426a3739e5SFlorian Wechsung #endif
16436a3739e5SFlorian Wechsung
1644cb87ef4cSFlorian Wechsung /*@
1645a1cb98faSBarry Smith DMPlexRebalanceSharedPoints - Redistribute points in the plex that are shared in order to achieve better balancing. This routine updates the `PointSF` of the `DM` inplace.
1646cb87ef4cSFlorian Wechsung
164760225df5SJacob Faibussowitsch Input Parameters:
1648a1cb98faSBarry Smith + dm - The `DMPLEX` object.
1649fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices).
1650fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS).
1651fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS.
1652cb87ef4cSFlorian Wechsung
165360225df5SJacob Faibussowitsch Output Parameter:
1654252a1336SBarry Smith . success - whether the graph partitioning was successful or not, optional. Unsuccessful simply means no change to the partitioning
1655252a1336SBarry Smith
1656a1cb98faSBarry Smith Options Database Keys:
1657252a1336SBarry Smith + -dm_plex_rebalance_shared_points_parmetis - Use ParMetis instead of Metis for the partitioner
1658252a1336SBarry Smith . -dm_plex_rebalance_shared_points_use_initial_guess - Use current partition to bootstrap ParMetis partition
1659252a1336SBarry Smith . -dm_plex_rebalance_shared_points_use_mat_partitioning - Use the MatPartitioning object to perform the partition, the prefix for those operations is -dm_plex_rebalance_shared_points_
1660252a1336SBarry Smith - -dm_plex_rebalance_shared_points_monitor - Monitor the shared points rebalance process
1661252a1336SBarry Smith
166290ea27d8SSatish Balay Level: intermediate
1663a1cb98faSBarry Smith
1664*7d7af440SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexDistribute()`
1665cb87ef4cSFlorian Wechsung @*/
DMPlexRebalanceSharedPoints(DM dm,PetscInt entityDepth,PetscBool useInitialGuess,PetscBool parallel,PetscBool * success)1666d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success)
1667d71ae5a4SJacob Faibussowitsch {
166841525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS)
1669cb87ef4cSFlorian Wechsung PetscSF sf;
16700faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx;
16717f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd;
16727f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal;
16737f57c1a4SFlorian Wechsung const PetscSFNode *iremote;
1674cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned;
1675cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned;
1676cb87ef4cSFlorian Wechsung PetscMPIInt rank, size;
16777f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers;
16785dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices;
1679cb87ef4cSFlorian Wechsung PetscInt offset, counter;
1680252a1336SBarry Smith PetscInt *vtxwgt;
1681252a1336SBarry Smith const PetscInt *xadj, *adjncy;
1682cb87ef4cSFlorian Wechsung PetscInt *part, *options;
1683cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut;
1684cb87ef4cSFlorian Wechsung real_t *ubvec;
1685cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering;
1686cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal;
1687cb87ef4cSFlorian Wechsung MPI_Comm comm;
1688252a1336SBarry Smith Mat A;
16897d197802SFlorian Wechsung PetscViewer viewer;
16907d197802SFlorian Wechsung PetscViewerFormat format;
16915a30b08bSFlorian Wechsung PetscLayout layout;
1692252a1336SBarry Smith real_t *tpwgts;
1693252a1336SBarry Smith PetscMPIInt *counts, *mpiCumSumVertices;
1694252a1336SBarry Smith PetscInt *pointsToRewrite;
1695252a1336SBarry Smith PetscInt numRows;
1696252a1336SBarry Smith PetscBool done, usematpartitioning = PETSC_FALSE;
1697252a1336SBarry Smith IS ispart = NULL;
1698252a1336SBarry Smith MatPartitioning mp;
1699252a1336SBarry Smith const char *prefix;
170012617df9SFlorian Wechsung
170112617df9SFlorian Wechsung PetscFunctionBegin;
17029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
17039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
1704252a1336SBarry Smith if (size == 1) {
1705252a1336SBarry Smith if (success) *success = PETSC_TRUE;
17063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1707252a1336SBarry Smith }
1708252a1336SBarry Smith if (success) *success = PETSC_FALSE;
1709252a1336SBarry Smith PetscCallMPI(MPI_Comm_rank(comm, &rank));
1710252a1336SBarry Smith
1711252a1336SBarry Smith parallel = PETSC_FALSE;
1712252a1336SBarry Smith useInitialGuess = PETSC_FALSE;
1713252a1336SBarry Smith PetscObjectOptionsBegin((PetscObject)dm);
1714252a1336SBarry Smith PetscCall(PetscOptionsName("-dm_plex_rebalance_shared_points_parmetis", "Use ParMetis instead of Metis for the partitioner", "DMPlexRebalanceSharedPoints", ¶llel));
1715252a1336SBarry Smith PetscCall(PetscOptionsBool("-dm_plex_rebalance_shared_points_use_initial_guess", "Use current partition to bootstrap ParMetis partition", "DMPlexRebalanceSharedPoints", useInitialGuess, &useInitialGuess, NULL));
1716252a1336SBarry Smith PetscCall(PetscOptionsBool("-dm_plex_rebalance_shared_points_use_mat_partitioning", "Use the MatPartitioning object to partition", "DMPlexRebalanceSharedPoints", usematpartitioning, &usematpartitioning, NULL));
1717252a1336SBarry Smith PetscCall(PetscOptionsViewer("-dm_plex_rebalance_shared_points_monitor", "Monitor the shared points rebalance process", "DMPlexRebalanceSharedPoints", &viewer, &format, NULL));
1718252a1336SBarry Smith PetscOptionsEnd();
1719252a1336SBarry Smith if (viewer) PetscCall(PetscViewerPushFormat(viewer, format));
17207f57c1a4SFlorian Wechsung
17219566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0));
172241525646SFlorian Wechsung
1723252a1336SBarry Smith PetscCall(DMGetOptionsPrefix(dm, &prefix));
1724648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)dm)->options, prefix, "-dm_rebalance_partition_view", &viewer, &format, NULL));
17251baa6e33SBarry Smith if (viewer) PetscCall(PetscViewerPushFormat(viewer, format));
17267d197802SFlorian Wechsung
1727ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */
17289566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd));
17299566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
17309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &toBalance));
1731ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) toBalance[i] = (PetscBool)(i >= eBegin && i < eEnd);
1732cb87ef4cSFlorian Wechsung
1733cf818975SFlorian Wechsung /* There are three types of points:
1734cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process
1735cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process
1736cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process
1737cf818975SFlorian Wechsung */
17389566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf));
17399566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote));
17409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isLeaf));
17419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isNonExclusivelyOwned));
17429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isExclusivelyOwned));
1743cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) {
1744cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE;
1745cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE;
1746cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE;
1747cb87ef4cSFlorian Wechsung }
1748cf818975SFlorian Wechsung
1749252a1336SBarry Smith /* mark all the leafs */
1750ad540459SPierre Jolivet for (i = 0; i < nleafs; i++) isLeaf[ilocal[i] - pStart] = PETSC_TRUE;
1751cb87ef4cSFlorian Wechsung
1752cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or
1753cf818975SFlorian Wechsung * not by calculating its degree */
17549566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, °rees));
17559566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, °rees));
1756cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0;
1757cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0;
1758cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) {
1759cb87ef4cSFlorian Wechsung if (toBalance[i]) {
17607f57c1a4SFlorian Wechsung if (degrees[i] > 0) {
1761cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE;
1762cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1;
1763cb87ef4cSFlorian Wechsung } else {
1764cb87ef4cSFlorian Wechsung if (!isLeaf[i]) {
1765cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE;
1766cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1;
1767cb87ef4cSFlorian Wechsung }
1768cb87ef4cSFlorian Wechsung }
1769cb87ef4cSFlorian Wechsung }
1770cb87ef4cSFlorian Wechsung }
1771cb87ef4cSFlorian Wechsung
1772252a1336SBarry Smith /* Build a graph with one vertex per core representing the
1773cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned
1774cf818975SFlorian Wechsung * point. */
17759566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &layout));
17769566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned));
17779566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(layout));
17789566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRanges(layout, &cumSumVertices));
17799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &globalNumbersOfLocalOwnedVertices));
1780ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) globalNumbersOfLocalOwnedVertices[i] = pStart - 1;
1781cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank];
1782cb87ef4cSFlorian Wechsung counter = 0;
1783cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) {
1784cb87ef4cSFlorian Wechsung if (toBalance[i]) {
17857f57c1a4SFlorian Wechsung if (degrees[i] > 0) {
1786cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset;
1787cb87ef4cSFlorian Wechsung counter++;
1788cb87ef4cSFlorian Wechsung }
1789cb87ef4cSFlorian Wechsung }
1790cb87ef4cSFlorian Wechsung }
1791cb87ef4cSFlorian Wechsung
1792cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */
17939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &leafGlobalNumbers));
17949566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers, MPI_REPLACE));
17959566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers, MPI_REPLACE));
1796cb87ef4cSFlorian Wechsung
1797252a1336SBarry Smith /* Build the graph for partitioning */
1798252a1336SBarry Smith numRows = 1 + numNonExclusivelyOwned;
1799252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalBuildGraph, dm, 0, 0, 0));
18009566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A));
1801252a1336SBarry Smith PetscCall(MatSetType(A, MATMPIADJ));
1802252a1336SBarry Smith PetscCall(MatSetSizes(A, numRows, numRows, cumSumVertices[size], cumSumVertices[size]));
1803252a1336SBarry Smith idx = cumSumVertices[rank];
18044baf1206SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) {
18054baf1206SFlorian Wechsung if (toBalance[i]) {
18060faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i];
18070faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i];
18080faf6628SFlorian Wechsung else continue;
18099566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, idx, jdx, 1, INSERT_VALUES));
18109566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, jdx, idx, 1, INSERT_VALUES));
18110941debbSFlorian Wechsung }
18120941debbSFlorian Wechsung }
1813252a1336SBarry Smith PetscCall(PetscFree(globalNumbersOfLocalOwnedVertices));
1814252a1336SBarry Smith PetscCall(PetscFree(leafGlobalNumbers));
18159566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
18169566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
1817252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalBuildGraph, dm, 0, 0, 0));
18184baf1206SFlorian Wechsung
181941525646SFlorian Wechsung nparts = size;
1820252a1336SBarry Smith ncon = 1;
18219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon * nparts, &tpwgts));
18226497c311SBarry Smith for (i = 0; i < ncon * nparts; i++) tpwgts[i] = (real_t)(1. / (nparts));
18239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon, &ubvec));
18246497c311SBarry Smith for (i = 0; i < ncon; i++) ubvec[i] = (real_t)1.05;
18258c9a1619SFlorian Wechsung
18269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon * (1 + numNonExclusivelyOwned), &vtxwgt));
1827252a1336SBarry Smith if (ncon == 2) {
182841525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned;
1829252a1336SBarry Smith vtxwgt[1] = 1;
183041525646SFlorian Wechsung for (i = 0; i < numNonExclusivelyOwned; i++) {
183141525646SFlorian Wechsung vtxwgt[ncon * (i + 1)] = 1;
1832252a1336SBarry Smith vtxwgt[ncon * (i + 1) + 1] = 0;
1833252a1336SBarry Smith }
1834252a1336SBarry Smith } else {
1835252a1336SBarry Smith PetscInt base, ms;
1836462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&numExclusivelyOwned, &base, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1837252a1336SBarry Smith PetscCall(MatGetSize(A, &ms, NULL));
1838252a1336SBarry Smith ms -= size;
1839252a1336SBarry Smith base = PetscMax(base, ms);
1840252a1336SBarry Smith vtxwgt[0] = base + numExclusivelyOwned;
1841ad540459SPierre Jolivet for (i = 0; i < numNonExclusivelyOwned; i++) vtxwgt[i + 1] = 1;
184241525646SFlorian Wechsung }
18438c9a1619SFlorian Wechsung
18445dc86ac1SFlorian Wechsung if (viewer) {
184563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %" PetscInt_FMT " on interface of mesh distribution.\n", entityDepth));
184663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %" PetscInt_FMT "\n", cumSumVertices[size]));
184712617df9SFlorian Wechsung }
1848252a1336SBarry Smith /* TODO: Drop the parallel/sequential choice here and just use MatPartioner for much more flexibility */
1849252a1336SBarry Smith if (usematpartitioning) {
1850252a1336SBarry Smith const char *prefix;
1851252a1336SBarry Smith
1852252a1336SBarry Smith PetscCall(MatPartitioningCreate(PetscObjectComm((PetscObject)dm), &mp));
1853252a1336SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mp, "dm_plex_rebalance_shared_points_"));
1854252a1336SBarry Smith PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
1855252a1336SBarry Smith PetscCall(PetscObjectPrependOptionsPrefix((PetscObject)mp, prefix));
1856252a1336SBarry Smith PetscCall(MatPartitioningSetAdjacency(mp, A));
1857252a1336SBarry Smith PetscCall(MatPartitioningSetNumberVertexWeights(mp, ncon));
1858252a1336SBarry Smith PetscCall(MatPartitioningSetVertexWeights(mp, vtxwgt));
1859252a1336SBarry Smith PetscCall(MatPartitioningSetFromOptions(mp));
1860252a1336SBarry Smith PetscCall(MatPartitioningApply(mp, &ispart));
1861252a1336SBarry Smith PetscCall(ISGetIndices(ispart, (const PetscInt **)&part));
1862252a1336SBarry Smith } else if (parallel) {
1863252a1336SBarry Smith if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n"));
1864252a1336SBarry Smith PetscCall(PetscMalloc1(cumSumVertices[rank + 1] - cumSumVertices[rank], &part));
1865252a1336SBarry Smith PetscCall(MatGetRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, &xadj, &adjncy, &done));
1866252a1336SBarry Smith PetscCheck(done, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Could not get adjacency information");
18679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(4, &options));
18685a30b08bSFlorian Wechsung options[0] = 1;
18695a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */
1870252a1336SBarry Smith if (viewer) options[1] = 1;
18715a30b08bSFlorian Wechsung options[2] = 0; /* Seed */
18725a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */
1873252a1336SBarry Smith wgtflag = 2;
1874252a1336SBarry Smith numflag = 0;
18758c9a1619SFlorian Wechsung if (useInitialGuess) {
1876252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "THIS DOES NOT WORK! I don't know why. Using current distribution of points as initial guess.\n"));
1877252a1336SBarry Smith for (i = 0; i < numRows; i++) part[i] = rank;
18789566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n"));
1879792fecdfSBarry Smith PetscStackPushExternal("ParMETIS_V3_RefineKway");
1880252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0));
1881252a1336SBarry Smith ierr = ParMETIS_V3_RefineKway((PetscInt *)cumSumVertices, (idx_t *)xadj, (idx_t *)adjncy, vtxwgt, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm);
1882252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0));
18838c9a1619SFlorian Wechsung PetscStackPop;
1884252a1336SBarry Smith PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()");
18858c9a1619SFlorian Wechsung } else {
1886792fecdfSBarry Smith PetscStackPushExternal("ParMETIS_V3_PartKway");
1887252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0));
1888252a1336SBarry Smith ierr = ParMETIS_V3_PartKway((PetscInt *)cumSumVertices, (idx_t *)xadj, (idx_t *)adjncy, vtxwgt, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm);
1889252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0));
18908c9a1619SFlorian Wechsung PetscStackPop;
18915f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()");
18928c9a1619SFlorian Wechsung }
1893252a1336SBarry Smith PetscCall(MatRestoreRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, &xadj, &adjncy, &done));
18949566063dSJacob Faibussowitsch PetscCall(PetscFree(options));
189541525646SFlorian Wechsung } else {
18969566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n"));
189741525646SFlorian Wechsung Mat As;
189841525646SFlorian Wechsung PetscInt *partGlobal;
189941525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll;
1900252a1336SBarry Smith
1901252a1336SBarry Smith PetscCall(PetscMalloc1(cumSumVertices[rank + 1] - cumSumVertices[rank], &part));
1902252a1336SBarry Smith PetscCall(MatGetSize(A, &numRows, NULL));
1903252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalGatherGraph, dm, 0, 0, 0));
1904252a1336SBarry Smith PetscCall(MatMPIAdjToSeqRankZero(A, &As));
1905252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalGatherGraph, dm, 0, 0, 0));
1906252a1336SBarry Smith
19079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &numExclusivelyOwnedAll));
190841525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned;
19099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, numExclusivelyOwnedAll, 1, MPIU_INT, comm));
1910cb87ef4cSFlorian Wechsung
19119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &partGlobal));
1912252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0));
1913dd400576SPatrick Sanan if (rank == 0) {
1914252a1336SBarry Smith PetscInt *vtxwgt_g, numRows_g;
191541525646SFlorian Wechsung
1916252a1336SBarry Smith PetscCall(MatGetRowIJ(As, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows_g, &xadj, &adjncy, &done));
1917252a1336SBarry Smith PetscCall(PetscMalloc1(2 * numRows_g, &vtxwgt_g));
191841525646SFlorian Wechsung for (i = 0; i < size; i++) {
191941525646SFlorian Wechsung vtxwgt_g[ncon * cumSumVertices[i]] = numExclusivelyOwnedAll[i];
192041525646SFlorian Wechsung if (ncon > 1) vtxwgt_g[ncon * cumSumVertices[i] + 1] = 1;
192141525646SFlorian Wechsung for (j = cumSumVertices[i] + 1; j < cumSumVertices[i + 1]; j++) {
192241525646SFlorian Wechsung vtxwgt_g[ncon * j] = 1;
192341525646SFlorian Wechsung if (ncon > 1) vtxwgt_g[2 * j + 1] = 0;
192441525646SFlorian Wechsung }
192541525646SFlorian Wechsung }
1926252a1336SBarry Smith
19279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(64, &options));
192841525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */
19295f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()");
193041525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1;
1931792fecdfSBarry Smith PetscStackPushExternal("METIS_PartGraphKway");
1932252a1336SBarry Smith ierr = METIS_PartGraphKway(&numRows_g, &ncon, (idx_t *)xadj, (idx_t *)adjncy, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal);
193341525646SFlorian Wechsung PetscStackPop;
19345f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()");
19359566063dSJacob Faibussowitsch PetscCall(PetscFree(options));
19369566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt_g));
1937252a1336SBarry Smith PetscCall(MatRestoreRowIJ(As, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows_g, &xadj, &adjncy, &done));
1938252a1336SBarry Smith PetscCall(MatDestroy(&As));
193941525646SFlorian Wechsung }
1940252a1336SBarry Smith PetscCall(PetscBarrier((PetscObject)dm));
1941252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0));
19429566063dSJacob Faibussowitsch PetscCall(PetscFree(numExclusivelyOwnedAll));
194341525646SFlorian Wechsung
1944252a1336SBarry Smith /* scatter the partitioning information to ranks */
1945252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalScatterPart, 0, 0, 0, 0));
19469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &counts));
19479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size + 1, &mpiCumSumVertices));
1948f4f49eeaSPierre Jolivet for (i = 0; i < size; i++) PetscCall(PetscMPIIntCast(cumSumVertices[i + 1] - cumSumVertices[i], &counts[i]));
1949f4f49eeaSPierre Jolivet for (i = 0; i <= size; i++) PetscCall(PetscMPIIntCast(cumSumVertices[i], &mpiCumSumVertices[i]));
19509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm));
19519566063dSJacob Faibussowitsch PetscCall(PetscFree(counts));
19529566063dSJacob Faibussowitsch PetscCall(PetscFree(mpiCumSumVertices));
19539566063dSJacob Faibussowitsch PetscCall(PetscFree(partGlobal));
1954252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalScatterPart, 0, 0, 0, 0));
195541525646SFlorian Wechsung }
19569566063dSJacob Faibussowitsch PetscCall(PetscFree(ubvec));
19579566063dSJacob Faibussowitsch PetscCall(PetscFree(tpwgts));
1958cb87ef4cSFlorian Wechsung
1959252a1336SBarry Smith /* Rename the result so that the vertex resembling the exclusively owned points stays on the same rank */
1960252a1336SBarry Smith PetscCall(PetscMalloc2(size, &firstVertices, size, &renumbering));
1961cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0];
19629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, firstVertices, 1, MPIU_INT, comm));
1963ad540459SPierre Jolivet for (i = 0; i < size; i++) renumbering[firstVertices[i]] = i;
1964ad540459SPierre Jolivet for (i = 0; i < cumSumVertices[rank + 1] - cumSumVertices[rank]; i++) part[i] = renumbering[part[i]];
1965252a1336SBarry Smith PetscCall(PetscFree2(firstVertices, renumbering));
1966252a1336SBarry Smith
1967cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */
1968cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank);
1969462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm));
1970cb87ef4cSFlorian Wechsung if (failedGlobal > 0) {
1971aaa8cc7dSPierre Jolivet PetscCheck(failedGlobal <= 0, comm, PETSC_ERR_LIB, "Metis/Parmetis returned a bad partition");
19729566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt));
19739566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance));
19749566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf));
19759566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned));
19769566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned));
1977252a1336SBarry Smith if (usematpartitioning) {
1978252a1336SBarry Smith PetscCall(ISRestoreIndices(ispart, (const PetscInt **)&part));
1979252a1336SBarry Smith PetscCall(ISDestroy(&ispart));
1980252a1336SBarry Smith } else PetscCall(PetscFree(part));
19817f57c1a4SFlorian Wechsung if (viewer) {
19829566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer));
1983648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer));
19847f57c1a4SFlorian Wechsung }
19859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0));
19863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1987cb87ef4cSFlorian Wechsung }
1988cb87ef4cSFlorian Wechsung
1989252a1336SBarry Smith /* Check how well we did distributing points*/
19905dc86ac1SFlorian Wechsung if (viewer) {
1991252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Number of owned entities of depth %" PetscInt_FMT ".\n", entityDepth));
1992252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Initial "));
19939566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, NULL, viewer));
1994252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Rebalanced "));
19959566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, part, viewer));
19967407ba93SFlorian Wechsung }
19977407ba93SFlorian Wechsung
1998252a1336SBarry Smith /* Check that every vertex is owned by a process that it is actually connected to. */
1999252a1336SBarry Smith PetscCall(MatGetRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done));
200041525646SFlorian Wechsung for (i = 1; i <= numNonExclusivelyOwned; i++) {
2001cb87ef4cSFlorian Wechsung PetscInt loc = 0;
20029566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cumSumVertices[part[i]], xadj[i + 1] - xadj[i], &adjncy[xadj[i]], &loc));
20037407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */
2004ad540459SPierre Jolivet if (loc < 0) part[i] = rank;
2005cb87ef4cSFlorian Wechsung }
2006252a1336SBarry Smith PetscCall(MatRestoreRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done));
2007252a1336SBarry Smith PetscCall(MatDestroy(&A));
2008cb87ef4cSFlorian Wechsung
2009252a1336SBarry Smith /* See how significant the influences of the previous fixing up step was.*/
20105dc86ac1SFlorian Wechsung if (viewer) {
2011252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "After fix "));
20129566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, part, viewer));
20137407ba93SFlorian Wechsung }
2014252a1336SBarry Smith if (!usematpartitioning) PetscCall(PetscFree(vtxwgt));
2015252a1336SBarry Smith else PetscCall(MatPartitioningDestroy(&mp));
20167407ba93SFlorian Wechsung
20179566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout));
2018cb87ef4cSFlorian Wechsung
2019252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalRewriteSF, dm, 0, 0, 0));
2020252a1336SBarry Smith /* Rewrite the SF to reflect the new ownership. */
20219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite));
20227f57c1a4SFlorian Wechsung counter = 0;
2023cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) {
2024cb87ef4cSFlorian Wechsung if (toBalance[i]) {
2025cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) {
20267f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart;
2027cb87ef4cSFlorian Wechsung counter++;
2028cb87ef4cSFlorian Wechsung }
2029cb87ef4cSFlorian Wechsung }
2030cb87ef4cSFlorian Wechsung }
20319566063dSJacob Faibussowitsch PetscCall(DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part + 1, degrees));
20329566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsToRewrite));
2033252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalRewriteSF, dm, 0, 0, 0));
2034cb87ef4cSFlorian Wechsung
20359566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance));
20369566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf));
20379566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned));
20389566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned));
2039252a1336SBarry Smith if (usematpartitioning) {
2040252a1336SBarry Smith PetscCall(ISRestoreIndices(ispart, (const PetscInt **)&part));
2041252a1336SBarry Smith PetscCall(ISDestroy(&ispart));
2042252a1336SBarry Smith } else PetscCall(PetscFree(part));
20435dc86ac1SFlorian Wechsung if (viewer) {
20449566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer));
20459566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer));
20467d197802SFlorian Wechsung }
20478b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE;
20489566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0));
20493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2050240408d3SFlorian Wechsung #else
20515f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis.");
205241525646SFlorian Wechsung #endif
2053cb87ef4cSFlorian Wechsung }
2054